summaryrefslogtreecommitdiffstats
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 000000000..b0fc3adf9
--- /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);
+}