about summary refs log tree commit diff
path: root/src/tools/rust-analyzer/crates/test-utils
diff options
context:
space:
mode:
authorLaurențiu Nicola <lnicola@dend.ro>2023-06-05 12:04:23 +0300
committerLaurențiu Nicola <lnicola@dend.ro>2023-06-05 12:04:23 +0300
commitb8a7d439db0cfd765ed4bfedd2bbaeeee58b05a5 (patch)
tree5adcbc6cf50af3bebc2cd4f42d5252a4d728690e /src/tools/rust-analyzer/crates/test-utils
parent51f714c8c5021fe25442e46798b1cbef2f2249ed (diff)
parentaa9bc8612514d216f84eec218dfd19ab83f3598a (diff)
downloadrust-b8a7d439db0cfd765ed4bfedd2bbaeeee58b05a5.tar.gz
rust-b8a7d439db0cfd765ed4bfedd2bbaeeee58b05a5.zip
Merge commit 'aa9bc8612514d216f84eec218dfd19ab83f3598a' into sync-from-ra
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.rs92
-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.rs532
4 files changed, 575 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 92b1ef23e69..2b5b6f49561 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 cd1235fa6dc..05f32f8e51e 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();
 
@@ -372,7 +399,7 @@ impl MiniCore {
 #[test]
 #[should_panic]
 fn parse_fixture_checks_further_indented_metadata() {
-    Fixture::parse(
+    FixtureWithProjectMeta::parse(
         r"
         //- /lib.rs
           mod bar;
@@ -386,15 +413,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 a7a52e08e75..fd3e68e2d2c 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 ca6de4061a4..c79b4e966d6 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,19 +23,23 @@
 //!     drop:
 //!     eq: sized
 //!     error: fmt
-//!     fmt: result
+//!     fmt: result, transmute, coerce_unsized
 //!     fn:
 //!     from: sized
 //!     future: pin
 //!     generator: pin
 //!     hash:
+//!     include:
 //!     index: sized
 //!     infallible:
 //!     iterator: option
 //!     iterators: iterator, fn
+//!     manually_drop: drop
 //!     non_zero:
-//!     option:
+//!     option: panic
 //!     ord: eq, option
+//!     panic: fmt
+//!     phantom_data:
 //!     pin:
 //!     range:
 //!     result:
@@ -41,6 +47,7 @@
 //!     sized:
 //!     slice:
 //!     sync: sized
+//!     transmute:
 //!     try: infallible
 //!     unsize: sized
 
@@ -106,6 +113,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 +121,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 +137,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 +168,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 +300,68 @@ 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
+}
+
+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
+}
+
 pub mod ops {
     // region:coerce_unsized
     mod unsize {
@@ -309,12 +486,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 +546,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 +637,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 +727,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 +815,114 @@ 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 ArgumentV1<'a> {
+        value: &'a Opaque,
+        formatter: fn(&Opaque, &mut Formatter<'_>) -> Result,
+    }
+
+    impl<'a> ArgumentV1<'a> {
+        pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> {
+            use crate::mem::transmute;
+            unsafe { ArgumentV1 { formatter: transmute(f), value: transmute(x) } }
+        }
+    }
+
+    #[lang = "format_arguments"]
+    pub struct Arguments<'a> {
+        pieces: &'a [&'static str],
+        args: &'a [ArgumentV1<'a>],
+    }
+
+    impl<'a> Arguments<'a> {
+        pub const fn new_v1(
+            pieces: &'a [&'static str],
+            args: &'a [ArgumentV1<'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 +955,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 +1149,6 @@ pub mod iter {
 
     mod traits {
         mod iterator {
-            use super::super::Take;
-
             pub trait Iterator {
                 type Item;
                 #[lang = "next"]
@@ -764,12 +1198,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 +1226,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 {
@@ -848,6 +1337,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
         };
     }