summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/test-utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/crates/test-utils')
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/fixture.rs96
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/minicore.rs565
4 files changed, 612 insertions, 55 deletions
diff --git a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml
index 92b1ef23e..2b5b6f495 100644
--- a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml
@@ -14,7 +14,7 @@ doctest = false
[dependencies]
# Avoid adding deps here, this crate is widely used in tests it should compile fast!
dissimilar = "1.0.4"
-text-size = "1.1.0"
+text-size.workspace = true
rustc-hash = "1.1.0"
stdx.workspace = true
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
index cd1235fa6..602baed37 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
@@ -86,7 +86,14 @@ pub struct MiniCore {
valid_flags: Vec<String>,
}
-impl Fixture {
+pub struct FixtureWithProjectMeta {
+ pub fixture: Vec<Fixture>,
+ pub mini_core: Option<MiniCore>,
+ pub proc_macro_names: Vec<String>,
+ pub toolchain: Option<String>,
+}
+
+impl FixtureWithProjectMeta {
/// Parses text which looks like this:
///
/// ```not_rust
@@ -96,37 +103,41 @@ impl Fixture {
/// //- other meta
/// ```
///
- /// Fixture can also start with a proc_macros and minicore declaration(in that order):
+ /// Fixture can also start with a proc_macros and minicore declaration (in that order):
///
/// ```
+ /// //- toolchain: nightly
/// //- proc_macros: identity
/// //- minicore: sized
/// ```
///
- /// That will include predefined proc macros and a subset of `libcore` into the fixture, see
- /// `minicore.rs` for what's available.
- pub fn parse(ra_fixture: &str) -> (Option<MiniCore>, Vec<String>, Vec<Fixture>) {
+ /// That will set toolchain to nightly and include predefined proc macros and a subset of
+ /// `libcore` into the fixture, see `minicore.rs` for what's available. Note that toolchain
+ /// defaults to stable.
+ pub fn parse(ra_fixture: &str) -> Self {
let fixture = trim_indent(ra_fixture);
let mut fixture = fixture.as_str();
+ let mut toolchain = None;
let mut mini_core = None;
let mut res: Vec<Fixture> = Vec::new();
- let mut test_proc_macros = vec![];
-
- if fixture.starts_with("//- proc_macros:") {
- let first_line = fixture.split_inclusive('\n').next().unwrap();
- test_proc_macros = first_line
- .strip_prefix("//- proc_macros:")
- .unwrap()
- .split(',')
- .map(|it| it.trim().to_string())
- .collect();
- fixture = &fixture[first_line.len()..];
+ let mut proc_macro_names = vec![];
+
+ if let Some(meta) = fixture.strip_prefix("//- toolchain:") {
+ let (meta, remain) = meta.split_once('\n').unwrap();
+ toolchain = Some(meta.trim().to_string());
+ fixture = remain;
+ }
+
+ if let Some(meta) = fixture.strip_prefix("//- proc_macros:") {
+ let (meta, remain) = meta.split_once('\n').unwrap();
+ proc_macro_names = meta.split(',').map(|it| it.trim().to_string()).collect();
+ fixture = remain;
}
- if fixture.starts_with("//- minicore:") {
- let first_line = fixture.split_inclusive('\n').next().unwrap();
- mini_core = Some(MiniCore::parse(first_line));
- fixture = &fixture[first_line.len()..];
+ if let Some(meta) = fixture.strip_prefix("//- minicore:") {
+ let (meta, remain) = meta.split_once('\n').unwrap();
+ mini_core = Some(MiniCore::parse(meta));
+ fixture = remain;
}
let default = if fixture.contains("//-") { None } else { Some("//- /main.rs") };
@@ -142,7 +153,7 @@ impl Fixture {
}
if line.starts_with("//-") {
- let meta = Fixture::parse_meta_line(line);
+ let meta = Self::parse_meta_line(line);
res.push(meta);
} else {
if line.starts_with("// ")
@@ -160,7 +171,7 @@ impl Fixture {
}
}
- (mini_core, test_proc_macros, res)
+ Self { fixture: res, mini_core, proc_macro_names, toolchain }
}
//- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
@@ -243,10 +254,19 @@ impl Fixture {
}
impl MiniCore {
+ const RAW_SOURCE: &str = include_str!("./minicore.rs");
+
fn has_flag(&self, flag: &str) -> bool {
self.activated_flags.iter().any(|it| it == flag)
}
+ pub fn from_flags<'a>(flags: impl IntoIterator<Item = &'a str>) -> Self {
+ MiniCore {
+ activated_flags: flags.into_iter().map(|x| x.to_owned()).collect(),
+ valid_flags: Vec::new(),
+ }
+ }
+
#[track_caller]
fn assert_valid_flag(&self, flag: &str) {
if !self.valid_flags.iter().any(|it| it == flag) {
@@ -257,8 +277,7 @@ impl MiniCore {
fn parse(line: &str) -> MiniCore {
let mut res = MiniCore { activated_flags: Vec::new(), valid_flags: Vec::new() };
- let line = line.strip_prefix("//- minicore:").unwrap().trim();
- for entry in line.split(", ") {
+ for entry in line.trim().split(", ") {
if res.has_flag(entry) {
panic!("duplicate minicore flag: {entry:?}");
}
@@ -268,13 +287,21 @@ impl MiniCore {
res
}
+ pub fn available_flags() -> impl Iterator<Item = &'static str> {
+ let lines = MiniCore::RAW_SOURCE.split_inclusive('\n');
+ lines
+ .map_while(|x| x.strip_prefix("//!"))
+ .skip_while(|line| !line.contains("Available flags:"))
+ .skip(1)
+ .map(|x| x.split_once(':').unwrap().0.trim())
+ }
+
/// Strips parts of minicore.rs which are flagged by inactive flags.
///
/// This is probably over-engineered to support flags dependencies.
pub fn source_code(mut self) -> String {
let mut buf = String::new();
- let raw_mini_core = include_str!("./minicore.rs");
- let mut lines = raw_mini_core.split_inclusive('\n');
+ let mut lines = MiniCore::RAW_SOURCE.split_inclusive('\n');
let mut implications = Vec::new();
@@ -360,6 +387,10 @@ impl MiniCore {
}
}
+ if !active_regions.is_empty() {
+ panic!("unclosed regions: {:?} Add an `endregion` comment", active_regions);
+ }
+
for flag in &self.valid_flags {
if !seen_regions.iter().any(|it| it == flag) {
panic!("unused minicore flag: {flag:?}");
@@ -372,7 +403,7 @@ impl MiniCore {
#[test]
#[should_panic]
fn parse_fixture_checks_further_indented_metadata() {
- Fixture::parse(
+ FixtureWithProjectMeta::parse(
r"
//- /lib.rs
mod bar;
@@ -386,15 +417,18 @@ fn parse_fixture_checks_further_indented_metadata() {
#[test]
fn parse_fixture_gets_full_meta() {
- let (mini_core, proc_macros, parsed) = Fixture::parse(
- r#"
+ let FixtureWithProjectMeta { fixture: parsed, mini_core, proc_macro_names, toolchain } =
+ FixtureWithProjectMeta::parse(
+ r#"
+//- toolchain: nightly
//- proc_macros: identity
//- minicore: coerce_unsized
//- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b,atom env:OUTDIR=path/to,OTHER=foo
mod m;
"#,
- );
- assert_eq!(proc_macros, vec!["identity".to_string()]);
+ );
+ assert_eq!(toolchain, Some("nightly".to_string()));
+ assert_eq!(proc_macro_names, vec!["identity".to_string()]);
assert_eq!(mini_core.unwrap().activated_flags, vec!["coerce_unsized".to_string()]);
assert_eq!(1, parsed.len());
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/lib.rs b/src/tools/rust-analyzer/crates/test-utils/src/lib.rs
index a7a52e08e..fd3e68e2d 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/lib.rs
@@ -27,7 +27,7 @@ pub use rustc_hash::FxHashMap;
pub use crate::{
assert_linear::AssertLinear,
- fixture::{Fixture, MiniCore},
+ fixture::{Fixture, FixtureWithProjectMeta, MiniCore},
};
pub const CURSOR_MARKER: &str = "$0";
@@ -95,7 +95,7 @@ fn try_extract_range(text: &str) -> Option<(TextRange, String)> {
Some((TextRange::new(start, end), text))
}
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
pub enum RangeOrOffset {
Range(TextRange),
Offset(TextSize),
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
index ca6de4061..266bc2391 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
@@ -11,6 +11,8 @@
//! add:
//! as_ref: sized
//! bool_impl: option, fn
+//! builtin_impls:
+//! cell: copy, drop
//! clone: sized
//! coerce_unsized: unsize
//! copy: clone
@@ -21,26 +23,34 @@
//! drop:
//! eq: sized
//! error: fmt
-//! fmt: result
+//! fmt: result, transmute, coerce_unsized
//! fn:
//! from: sized
//! future: pin
//! generator: pin
//! hash:
+//! include:
//! index: sized
//! infallible:
+//! int_impl: size_of, transmute
//! iterator: option
//! iterators: iterator, fn
+//! manually_drop: drop
//! non_zero:
-//! option:
+//! option: panic
//! ord: eq, option
+//! panic: fmt
+//! phantom_data:
//! pin:
+//! pointee:
//! range:
//! result:
//! send: sized
+//! size_of: sized
//! sized:
//! slice:
//! sync: sized
+//! transmute:
//! try: infallible
//! unsize: sized
@@ -106,6 +116,7 @@ pub mod marker {
impl<T: ?Sized> Copy for *const T {}
impl<T: ?Sized> Copy for *mut T {}
impl<T: ?Sized> Copy for &T {}
+ impl Copy for ! {}
}
// endregion:copy
@@ -113,6 +124,11 @@ pub mod marker {
#[lang = "tuple_trait"]
pub trait Tuple {}
// endregion:fn
+
+ // region:phantom_data
+ #[lang = "phantom_data"]
+ pub struct PhantomData<T: ?Sized>;
+ // endregion:phantom_data
}
// region:default
@@ -124,6 +140,27 @@ pub mod default {
#[rustc_builtin_macro(Default, attributes(default))]
pub macro Default($item:item) {}
// endregion:derive
+
+ // region:builtin_impls
+ macro_rules! impl_default {
+ ($v:literal; $($t:ty)*) => {
+ $(
+ impl const Default for $t {
+ fn default() -> Self {
+ $v
+ }
+ }
+ )*
+ }
+ }
+
+ impl_default! {
+ 0; usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128
+ }
+ impl_default! {
+ 0.0; f32 f64
+ }
+ // endregion:builtin_impls
}
// endregion:default
@@ -134,15 +171,100 @@ pub mod hash {
pub trait Hash {
fn hash<H: Hasher>(&self, state: &mut H);
}
+
+ // region:derive
+ #[rustc_builtin_macro]
+ pub macro Hash($item:item) {}
+ // endregion:derive
}
// endregion:hash
+// region:cell
+pub mod cell {
+ use crate::mem;
+
+ #[lang = "unsafe_cell"]
+ pub struct UnsafeCell<T: ?Sized> {
+ value: T,
+ }
+
+ impl<T> UnsafeCell<T> {
+ pub const fn new(value: T) -> UnsafeCell<T> {
+ UnsafeCell { value }
+ }
+
+ pub const fn get(&self) -> *mut T {
+ self as *const UnsafeCell<T> as *const T as *mut T
+ }
+ }
+
+ pub struct Cell<T: ?Sized> {
+ value: UnsafeCell<T>,
+ }
+
+ impl<T> Cell<T> {
+ pub const fn new(value: T) -> Cell<T> {
+ Cell { value: UnsafeCell::new(value) }
+ }
+
+ pub fn set(&self, val: T) {
+ let old = self.replace(val);
+ mem::drop(old);
+ }
+
+ pub fn replace(&self, val: T) -> T {
+ mem::replace(unsafe { &mut *self.value.get() }, val)
+ }
+ }
+
+ impl<T: Copy> Cell<T> {
+ pub fn get(&self) -> T {
+ unsafe { *self.value.get() }
+ }
+ }
+}
+// endregion:cell
+
// region:clone
pub mod clone {
#[lang = "clone"]
pub trait Clone: Sized {
fn clone(&self) -> Self;
}
+
+ impl<T> Clone for &T {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+
+ // region:builtin_impls
+ macro_rules! impl_clone {
+ ($($t:ty)*) => {
+ $(
+ impl const Clone for $t {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+ )*
+ }
+ }
+
+ impl_clone! {
+ usize u8 u16 u32 u64 u128
+ isize i8 i16 i32 i64 i128
+ f32 f64
+ bool char
+ }
+
+ impl Clone for ! {
+ fn clone(&self) {
+ *self
+ }
+ }
+ // endregion:builtin_impls
+
// region:derive
#[rustc_builtin_macro]
pub macro Clone($item:item) {}
@@ -181,10 +303,82 @@ pub mod convert {
}
// endregion:as_ref
// region:infallible
- pub enum Infallibe {}
+ pub enum Infallible {}
// endregion:infallible
}
+pub mod mem {
+ // region:drop
+ // region:manually_drop
+ #[lang = "manually_drop"]
+ #[repr(transparent)]
+ pub struct ManuallyDrop<T: ?Sized> {
+ value: T,
+ }
+
+ impl<T> ManuallyDrop<T> {
+ pub const fn new(value: T) -> ManuallyDrop<T> {
+ ManuallyDrop { value }
+ }
+ }
+
+ // region:deref
+ impl<T: ?Sized> crate::ops::Deref for ManuallyDrop<T> {
+ type Target = T;
+ fn deref(&self) -> &T {
+ &self.value
+ }
+ }
+ // endregion:deref
+
+ // endregion:manually_drop
+
+ pub fn drop<T>(_x: T) {}
+ pub const fn replace<T>(dest: &mut T, src: T) -> T {
+ unsafe {
+ let result = crate::ptr::read(dest);
+ crate::ptr::write(dest, src);
+ result
+ }
+ }
+ // endregion:drop
+
+ // region:transmute
+ extern "rust-intrinsic" {
+ pub fn transmute<Src, Dst>(src: Src) -> Dst;
+ }
+ // endregion:transmute
+
+ // region:size_of
+ extern "rust-intrinsic" {
+ pub fn size_of<T>() -> usize;
+ }
+ // endregion:size_of
+}
+
+pub mod ptr {
+ // region:drop
+ #[lang = "drop_in_place"]
+ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+ unsafe { drop_in_place(to_drop) }
+ }
+ pub const unsafe fn read<T>(src: *const T) -> T {
+ *src
+ }
+ pub const unsafe fn write<T>(dst: *mut T, src: T) {
+ *dst = src;
+ }
+ // endregion:drop
+
+ // region:pointee
+ #[lang = "pointee_trait"]
+ pub trait Pointee {
+ #[lang = "metadata_type"]
+ type Metadata;
+ }
+ // endregion:pointee
+}
+
pub mod ops {
// region:coerce_unsized
mod unsize {
@@ -309,12 +503,6 @@ pub mod ops {
pub use self::index::{Index, IndexMut};
// endregion:index
- // region:drop
- pub mod mem {
- pub fn drop<T>(_x: T) {}
- }
- // endregion:drop
-
// region:range
mod range {
#[lang = "RangeFull"]
@@ -375,16 +563,82 @@ pub mod ops {
type Output;
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}
+
+ mod impls {
+ use crate::marker::Tuple;
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
+ impl<A: Tuple, F: ?Sized> const Fn<A> for &F
+ where
+ F: ~const Fn<A>,
+ {
+ extern "rust-call" fn call(&self, args: A) -> F::Output {
+ (**self).call(args)
+ }
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
+ impl<A: Tuple, F: ?Sized> const FnMut<A> for &F
+ where
+ F: ~const Fn<A>,
+ {
+ extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
+ (**self).call(args)
+ }
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
+ impl<A: Tuple, F: ?Sized> const FnOnce<A> for &F
+ where
+ F: ~const Fn<A>,
+ {
+ type Output = F::Output;
+
+ extern "rust-call" fn call_once(self, args: A) -> F::Output {
+ (*self).call(args)
+ }
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
+ impl<A: Tuple, F: ?Sized> const FnMut<A> for &mut F
+ where
+ F: ~const FnMut<A>,
+ {
+ extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
+ (*self).call_mut(args)
+ }
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
+ impl<A: Tuple, F: ?Sized> const FnOnce<A> for &mut F
+ where
+ F: ~const FnMut<A>,
+ {
+ type Output = F::Output;
+ extern "rust-call" fn call_once(self, args: A) -> F::Output {
+ (*self).call_mut(args)
+ }
+ }
+ }
}
pub use self::function::{Fn, FnMut, FnOnce};
// endregion:fn
// region:try
mod try_ {
+ use super::super::convert::Infallible;
+
pub enum ControlFlow<B, C = ()> {
+ #[lang = "Continue"]
Continue(C),
+ #[lang = "Break"]
Break(B),
}
- pub trait FromResidual<R = Self::Residual> {
+ pub trait FromResidual<R = <Self as Try>::Residual> {
#[lang = "from_residual"]
fn from_residual(residual: R) -> Self;
}
@@ -400,14 +654,80 @@ pub mod ops {
impl<B, C> Try for ControlFlow<B, C> {
type Output = C;
- type Residual = ControlFlow<B, convert::Infallible>;
- fn from_output(output: Self::Output) -> Self {}
- fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {}
+ type Residual = ControlFlow<B, Infallible>;
+ fn from_output(output: Self::Output) -> Self {
+ ControlFlow::Continue(output)
+ }
+ fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+ match self {
+ ControlFlow::Continue(x) => ControlFlow::Continue(x),
+ ControlFlow::Break(x) => ControlFlow::Break(ControlFlow::Break(x)),
+ }
+ }
}
impl<B, C> FromResidual for ControlFlow<B, C> {
- fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self {}
+ fn from_residual(residual: ControlFlow<B, Infallible>) -> Self {
+ match residual {
+ ControlFlow::Break(b) => ControlFlow::Break(b),
+ ControlFlow::Continue(_) => loop {},
+ }
+ }
}
+ // region:option
+ impl<T> Try for Option<T> {
+ type Output = T;
+ type Residual = Option<Infallible>;
+ fn from_output(output: Self::Output) -> Self {
+ Some(output)
+ }
+ fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+ match self {
+ Some(x) => ControlFlow::Continue(x),
+ None => ControlFlow::Break(None),
+ }
+ }
+ }
+
+ impl<T> FromResidual for Option<T> {
+ fn from_residual(x: Option<Infallible>) -> Self {
+ match x {
+ None => None,
+ Some(_) => loop {},
+ }
+ }
+ }
+ // endregion:option
+ // region:result
+ // region:from
+ use super::super::convert::From;
+
+ impl<T, E> Try for Result<T, E> {
+ type Output = T;
+ type Residual = Result<Infallible, E>;
+
+ fn from_output(output: Self::Output) -> Self {
+ Ok(output)
+ }
+
+ fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+ match self {
+ Ok(v) => ControlFlow::Continue(v),
+ Err(e) => ControlFlow::Break(Err(e)),
+ }
+ }
+ }
+
+ impl<T, E, F: From<E>> FromResidual<Result<Infallible, E>> for Result<T, F> {
+ fn from_residual(residual: Result<Infallible, E>) -> Self {
+ match residual {
+ Err(e) => Err(From::from(e)),
+ Ok(_) => loop {},
+ }
+ }
+ }
+ // endregion:from
+ // endregion:result
}
pub use self::try_::{ControlFlow, FromResidual, Try};
// endregion:try
@@ -424,6 +744,19 @@ pub mod ops {
pub trait AddAssign<Rhs = Self> {
fn add_assign(&mut self, rhs: Rhs);
}
+
+ // region:builtin_impls
+ macro_rules! add_impl {
+ ($($t:ty)*) => ($(
+ impl const Add for $t {
+ type Output = $t;
+ fn add(self, other: $t) -> $t { self + other }
+ }
+ )*)
+ }
+
+ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
+ // endregion:builtin_impls
// endregion:add
// region:generator
@@ -499,12 +832,111 @@ pub mod fmt {
pub struct Error;
pub type Result = Result<(), Error>;
pub struct Formatter<'a>;
+ pub struct DebugTuple;
+ pub struct DebugStruct;
+ impl Formatter<'_> {
+ pub fn debug_tuple(&mut self, name: &str) -> DebugTuple {
+ DebugTuple
+ }
+
+ pub fn debug_struct(&mut self, name: &str) -> DebugStruct {
+ DebugStruct
+ }
+ }
+
+ impl DebugTuple {
+ pub fn field(&mut self, value: &dyn Debug) -> &mut Self {
+ self
+ }
+
+ pub fn finish(&mut self) -> Result {
+ Ok(())
+ }
+ }
+
+ impl DebugStruct {
+ pub fn field(&mut self, name: &str, value: &dyn Debug) -> &mut Self {
+ self
+ }
+
+ pub fn finish(&mut self) -> Result {
+ Ok(())
+ }
+ }
+
pub trait Debug {
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
}
pub trait Display {
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
}
+
+ extern "C" {
+ type Opaque;
+ }
+
+ #[lang = "format_argument"]
+ pub struct Argument<'a> {
+ value: &'a Opaque,
+ formatter: fn(&Opaque, &mut Formatter<'_>) -> Result,
+ }
+
+ impl<'a> Argument<'a> {
+ pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'b> {
+ use crate::mem::transmute;
+ unsafe { Argument { formatter: transmute(f), value: transmute(x) } }
+ }
+ }
+
+ #[lang = "format_arguments"]
+ pub struct Arguments<'a> {
+ pieces: &'a [&'static str],
+ args: &'a [Argument<'a>],
+ }
+
+ impl<'a> Arguments<'a> {
+ pub const fn new_v1(pieces: &'a [&'static str], args: &'a [Argument<'a>]) -> Arguments<'a> {
+ Arguments { pieces, args }
+ }
+ }
+
+ // region:derive
+ #[rustc_builtin_macro]
+ pub macro Debug($item:item) {}
+ // endregion:derive
+
+ // region:builtin_impls
+ macro_rules! impl_debug {
+ ($($t:ty)*) => {
+ $(
+ impl const Debug for $t {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ Ok(())
+ }
+ }
+ )*
+ }
+ }
+
+ impl_debug! {
+ usize u8 u16 u32 u64 u128
+ isize i8 i16 i32 i64 i128
+ f32 f64
+ bool char
+ }
+
+ impl<T: Debug> Debug for [T] {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ Ok(())
+ }
+ }
+
+ impl<T: Debug + ?Sized> Debug for &T {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ (&**self).fmt(f)
+ }
+ }
+ // endregion:builtin_impls
}
// endregion:fmt
@@ -537,12 +969,30 @@ pub mod option {
}
}
+ pub const fn as_ref(&self) -> Option<&T> {
+ match self {
+ Some(x) => Some(x),
+ None => None,
+ }
+ }
+
pub fn and<U>(self, optb: Option<U>) -> Option<U> {
loop {}
}
pub fn unwrap_or(self, default: T) -> T {
- loop {}
+ match self {
+ Some(val) => val,
+ None => default,
+ }
}
+ // region:result
+ pub const fn ok_or<E>(self, err: E) -> Result<T, E> {
+ match self {
+ Some(v) => Ok(v),
+ None => Err(err),
+ }
+ }
+ // endregion:result
// region:fn
pub fn and_then<U, F>(self, f: F) -> Option<U>
where
@@ -713,8 +1163,6 @@ pub mod iter {
mod traits {
mod iterator {
- use super::super::Take;
-
pub trait Iterator {
type Item;
#[lang = "next"]
@@ -764,12 +1212,19 @@ pub mod iter {
self
}
}
- pub struct IntoIter<T, const N: usize>([T; N]);
+ struct IndexRange {
+ start: usize,
+ end: usize,
+ }
+ pub struct IntoIter<T, const N: usize> {
+ data: [T; N],
+ range: IndexRange,
+ }
impl<T, const N: usize> IntoIterator for [T; N] {
type Item = T;
type IntoIter = IntoIter<T, N>;
fn into_iter(self) -> I {
- IntoIter(self)
+ IntoIter { data: self, range: IndexRange { start: 0, end: loop {} } }
}
}
impl<T, const N: usize> Iterator for IntoIter<T, N> {
@@ -785,16 +1240,64 @@ pub mod iter {
}
// endregion:iterator
-// region:derive
+// region:panic
+mod panic {
+ pub macro panic_2021 {
+ ($($t:tt)+) => (
+ $crate::panicking::panic_fmt($crate::const_format_args!($($t)+))
+ ),
+ }
+}
+
+mod panicking {
+ #[lang = "panic_fmt"]
+ pub const fn panic_fmt(fmt: crate::fmt::Arguments<'_>) -> ! {
+ loop {}
+ }
+}
+// endregion:panic
+
mod macros {
+ // region:panic
+ #[macro_export]
+ #[rustc_builtin_macro(std_panic)]
+ macro_rules! panic {
+ ($($arg:tt)*) => {
+ /* compiler built-in */
+ };
+ }
+
+ pub(crate) use panic;
+ // endregion:panic
+
+ // region:fmt
+ #[macro_export]
+ #[rustc_builtin_macro]
+ macro_rules! const_format_args {
+ ($fmt:expr) => {{ /* compiler built-in */ }};
+ ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }};
+ }
+
+ pub(crate) use const_format_args;
+ // endregion:fmt
+
+ // region:derive
pub(crate) mod builtin {
#[rustc_builtin_macro]
pub macro derive($item:item) {
/* compiler built-in */
}
}
+ // endregion:derive
+
+ // region:include
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! include {
+ ($file:expr $(,)?) => {{ /* compiler built-in */ }};
+ }
+ // endregion:include
}
-// endregion:derive
// region:non_zero
pub mod num {
@@ -818,6 +1321,25 @@ impl bool {
}
// endregion:bool_impl
+// region:int_impl
+macro_rules! impl_int {
+ ($($t:ty)*) => {
+ $(
+ impl $t {
+ pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+ unsafe { mem::transmute(bytes) }
+ }
+ }
+ )*
+ }
+}
+
+impl_int! {
+ usize u8 u16 u32 u64 u128
+ isize i8 i16 i32 i64 i128
+}
+// endregion:int_impl
+
// region:error
pub mod error {
#[rustc_has_incoherent_inherent_impls]
@@ -848,6 +1370,7 @@ pub mod prelude {
ops::Drop, // :drop
ops::{Fn, FnMut, FnOnce}, // :fn
option::Option::{self, None, Some}, // :option
+ panic, // :panic
result::Result::{self, Err, Ok}, // :result
};
}