diff options
Diffstat (limited to 'src/tools/rust-analyzer/crates/test-utils')
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 }; } |