about summary refs log tree commit diff
path: root/tests/ui/rfc-2632-const-trait-impl/const-drop.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/rfc-2632-const-trait-impl/const-drop.rs')
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-drop.rs113
1 files changed, 113 insertions, 0 deletions
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-drop.rs b/tests/ui/rfc-2632-const-trait-impl/const-drop.rs
new file mode 100644
index 00000000000..b0fc3adf984
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-drop.rs
@@ -0,0 +1,113 @@
+// run-pass
+// revisions: stock precise
+#![feature(const_trait_impl)]
+#![feature(const_mut_refs)]
+#![feature(never_type)]
+#![cfg_attr(precise, feature(const_precise_live_drops))]
+
+use std::marker::Destruct;
+
+struct S<'a>(&'a mut u8);
+
+impl<'a> const Drop for S<'a> {
+    fn drop(&mut self) {
+        *self.0 += 1;
+    }
+}
+
+const fn a<T: ~const Destruct>(_: T) {}
+
+const fn b() -> u8 {
+    let mut c = 0;
+    let _ = S(&mut c);
+    a(S(&mut c));
+    c
+}
+
+const C: u8 = b();
+
+macro_rules! implements_const_drop {
+    ($($exp:expr),*$(,)?) => {
+        $(
+            const _: () = a($exp);
+        )*
+    }
+}
+
+#[allow(dead_code)]
+mod t {
+    pub struct Foo;
+    pub enum Bar { A }
+    pub fn foo() {}
+    pub struct ConstDrop;
+
+    impl const Drop for ConstDrop {
+        fn drop(&mut self) {}
+    }
+
+    pub struct HasConstDrop(pub ConstDrop);
+    pub struct TrivialFields(pub u8, pub i8, pub usize, pub isize);
+
+    #[const_trait]
+    pub trait SomeTrait {
+        fn foo();
+    }
+    impl const SomeTrait for () {
+        fn foo() {}
+    }
+    // non-const impl
+    impl SomeTrait for i32 {
+        fn foo() {}
+    }
+
+    pub struct ConstDropWithBound<T: ~const SomeTrait>(pub core::marker::PhantomData<T>);
+
+    impl<T: ~const SomeTrait> const Drop for ConstDropWithBound<T> {
+        fn drop(&mut self) {
+            T::foo();
+        }
+    }
+
+    pub struct ConstDropWithNonconstBound<T: SomeTrait>(pub core::marker::PhantomData<T>);
+
+    impl<T: SomeTrait> const Drop for ConstDropWithNonconstBound<T> {
+        fn drop(&mut self) {
+            // Note: we DON'T use the `T: SomeTrait` bound
+        }
+    }
+}
+
+use t::*;
+
+implements_const_drop! {
+    1u8,
+    2,
+    3.0,
+    Foo,
+    Bar::A,
+    foo,
+    ConstDrop,
+    HasConstDrop(ConstDrop),
+    TrivialFields(1, 2, 3, 4),
+    &1,
+    &1 as *const i32,
+    ConstDropWithBound::<()>,
+    ConstDropWithNonconstBound::<i32>,
+    Result::<i32, !>::Ok(1),
+}
+
+fn main() {
+    struct HasDropGlue(#[allow(unused_tuple_struct_fields)] Box<u8>);
+    struct HasDropImpl;
+    impl Drop for HasDropImpl {
+        fn drop(&mut self) {
+            println!("not trivial drop");
+        }
+    }
+
+    // These types should pass because ~const in a non-const context should have no effect.
+    a(HasDropGlue(Box::new(0)));
+    a(HasDropImpl);
+
+    assert_eq!(C, 2);
+}