diff options
| author | bors <bors@rust-lang.org> | 2021-09-15 03:51:03 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-09-15 03:51:03 +0000 |
| commit | cdeba02ff71416e014f7130f75166890688be986 (patch) | |
| tree | 7abdff0663fd163ce1684276436982235b47f082 /src/test | |
| parent | c3c0f80d6081092faff801542dd82f0e2420152b (diff) | |
| parent | f749e05f6b95b66485c0417996d9aeb369def8da (diff) | |
| download | rust-cdeba02ff71416e014f7130f75166890688be986.tar.gz rust-cdeba02ff71416e014f7130f75166890688be986.zip | |
Auto merge of #88558 - fee1-dead:const-drop, r=oli-obk
Const drop
The changes are pretty primitive at this point. But at least it works. ^-^
Problems with the current change that I can think of now:
- [x] `~const Drop` shouldn't change anything in the non-const world.
- [x] types that do not have drop glues shouldn't fail to satisfy `~const Drop` in const contexts. `struct S { a: u8, b: u16 }` This might not fail for `needs_non_const_drop`, but it will fail in `rustc_trait_selection`.
- [x] The current change accepts types that have `const Drop` impls but have non-const `Drop` glue.
Fixes #88424.
Significant Changes:
- `~const Drop` is no longer treated as a normal trait bound. In non-const contexts, this bound has no effect, but in const contexts, this restricts the input type and all of its transitive fields to either a) have a `const Drop` impl or b) can be trivially dropped (i.e. no drop glue)
- `T: ~const Drop` will not be linted like `T: Drop`.
- Instead of recursing and iterating through the type in `rustc_mir::transform::check_consts`, we use the trait system to special case `~const Drop`. See [`rustc_trait_selection::...::candidate_assembly#assemble_const_drop_candidates`](https://github.com/fee1-dead/rust/blob/const-drop/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs#L817) and others.
Changes not related to `const Drop`ping and/or changes that are insignificant:
- `Node.constness_for_typeck` no longer returns `hir::Constness::Const` for type aliases in traits. This was previously used to hack how we determine default bound constness for items. But because we now use an explicit opt-in, it is no longer needed.
- Removed `is_const_impl_raw` query. We have `impl_constness`, and the only existing use of that query uses `HirId`, which means we can just operate it with hir.
- `ty::Destructor` now has a field `constness`, which represents the constness of the destructor.
r? `@oli-obk`
Diffstat (limited to 'src/test')
5 files changed, 274 insertions, 0 deletions
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr new file mode 100644 index 00000000000..1ac62f0bfec --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr @@ -0,0 +1,59 @@ +error: `~const` is not allowed here + --> $DIR/const-drop-fail.rs:27:35 + | +LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>); + | ^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions + +error[E0277]: the trait bound `NonTrivialDrop: Drop` is not satisfied + --> $DIR/const-drop-fail.rs:45:5 + | +LL | NonTrivialDrop, + | ^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `NonTrivialDrop` + | +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:36:19 + | +LL | const fn check<T: ~const Drop>(_: T) {} + | ^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `ConstImplWithDropGlue: Drop` is not satisfied + --> $DIR/const-drop-fail.rs:47:5 + | +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `ConstImplWithDropGlue` + | +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:36:19 + | +LL | const fn check<T: ~const Drop>(_: T) {} + | ^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied + --> $DIR/const-drop-fail.rs:49:5 + | +LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop` + | +note: required by `ConstDropImplWithBounds` + --> $DIR/const-drop-fail.rs:27:1 + | +LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied + --> $DIR/const-drop-fail.rs:49:5 + | +LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop` + | +note: required by a bound in `ConstDropImplWithBounds` + --> $DIR/const-drop-fail.rs:27:35 + | +LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>); + | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs new file mode 100644 index 00000000000..3d4de088f55 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs @@ -0,0 +1,54 @@ +// revisions: stock precise +#![feature(const_trait_impl)] +#![feature(const_mut_refs)] +#![feature(const_fn_trait_bound)] +#![cfg_attr(precise, feature(const_precise_live_drops))] + +use std::marker::PhantomData; + +struct NonTrivialDrop; + +impl Drop for NonTrivialDrop { + fn drop(&mut self) { + println!("Non trivial drop"); + } +} + +struct ConstImplWithDropGlue(NonTrivialDrop); + +impl const Drop for ConstImplWithDropGlue { + fn drop(&mut self) {} +} + +trait A { fn a() { println!("A"); } } + +impl A for NonTrivialDrop {} + +struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>); +//~^ ERROR `~const` is not allowed + +impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> { + fn drop(&mut self) { + T::a(); + } +} + +const fn check<T: ~const Drop>(_: T) {} + +macro_rules! check_all { + ($($exp:expr),*$(,)?) => {$( + const _: () = check($exp); + )*}; +} + +check_all! { + NonTrivialDrop, + //~^ ERROR the trait bound + ConstImplWithDropGlue(NonTrivialDrop), + //~^ ERROR the trait bound + ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), + //~^ ERROR the trait bound + //~| ERROR the trait bound +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr new file mode 100644 index 00000000000..1ac62f0bfec --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr @@ -0,0 +1,59 @@ +error: `~const` is not allowed here + --> $DIR/const-drop-fail.rs:27:35 + | +LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>); + | ^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions + +error[E0277]: the trait bound `NonTrivialDrop: Drop` is not satisfied + --> $DIR/const-drop-fail.rs:45:5 + | +LL | NonTrivialDrop, + | ^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `NonTrivialDrop` + | +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:36:19 + | +LL | const fn check<T: ~const Drop>(_: T) {} + | ^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `ConstImplWithDropGlue: Drop` is not satisfied + --> $DIR/const-drop-fail.rs:47:5 + | +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `ConstImplWithDropGlue` + | +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:36:19 + | +LL | const fn check<T: ~const Drop>(_: T) {} + | ^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied + --> $DIR/const-drop-fail.rs:49:5 + | +LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop` + | +note: required by `ConstDropImplWithBounds` + --> $DIR/const-drop-fail.rs:27:1 + | +LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied + --> $DIR/const-drop-fail.rs:49:5 + | +LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop` + | +note: required by a bound in `ConstDropImplWithBounds` + --> $DIR/const-drop-fail.rs:27:35 + | +LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>); + | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs new file mode 100644 index 00000000000..9a1b554f45f --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs @@ -0,0 +1,81 @@ +// run-pass +// revisions: stock precise +#![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] +#![feature(const_mut_refs)] +#![feature(const_panic)] +#![cfg_attr(precise, feature(const_precise_live_drops))] + +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 Drop>(_: 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); +} + +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, +} + +fn main() { + struct HasDropGlue(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); +} diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs new file mode 100644 index 00000000000..fe1015b3bf7 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs @@ -0,0 +1,21 @@ +// check-pass +#![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] + +struct S; + +trait A {} +trait B {} + +impl const A for S {} +impl const B for S {} + +impl S { + const fn a<T: ~const A>() where T: ~const B { + + } +} + +const _: () = S::a::<S>(); + +fn main() {} |
