about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-12-29 04:42:21 +0000
committerMichael Goulet <michael@errs.io>2025-01-08 18:14:58 +0000
commitc64f859521d9f86c96144f487201055b2146e19f (patch)
treea49597a9703983eb8fbf57de699865668bd399a3
parent6afee111c2faf86ba884ea748967130abad37b52 (diff)
downloadrust-c64f859521d9f86c96144f487201055b2146e19f.tar.gz
rust-c64f859521d9f86c96144f487201055b2146e19f.zip
Implement const Destruct in old solver
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs4
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/effects.rs106
-rw-r--r--tests/ui/consts/fn_trait_refs.stderr93
-rw-r--r--tests/ui/consts/promoted_const_call.stderr4
-rw-r--r--tests/ui/impl-trait/normalize-tait-in-const.stderr19
-rw-r--r--tests/ui/traits/const-traits/const-drop-bound.rs3
-rw-r--r--tests/ui/traits/const-traits/const-drop-bound.stderr17
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr9
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr9
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr (renamed from tests/ui/traits/const-traits/const-drop-fail.precise.stderr)8
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr (renamed from tests/ui/traits/const-traits/const-drop-fail.stock.stderr)8
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr33
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr33
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.rs7
15 files changed, 222 insertions, 133 deletions
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 5e929fbec0b..2d69386176b 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1417,8 +1417,8 @@ impl Hash for FieldDef {
 impl<'tcx> FieldDef {
     /// Returns the type of this field. The resulting type is not normalized. The `arg` is
     /// typically obtained via the second field of [`TyKind::Adt`].
-    pub fn ty(&self, tcx: TyCtxt<'tcx>, arg: GenericArgsRef<'tcx>) -> Ty<'tcx> {
-        tcx.type_of(self.did).instantiate(tcx, arg)
+    pub fn ty(&self, tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
+        tcx.type_of(self.did).instantiate(tcx, args)
     }
 
     /// Computes the `Ident` of this variant by looking up the `Span`
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
index 7da4f5e0107..3c5d9b95e77 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
@@ -712,6 +712,8 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
     }
 }
 
+// NOTE: Keep this in sync with `evaluate_host_effect_for_destruct_goal` in
+// the old solver, for as long as that exists.
 pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
     cx: I,
     self_ty: I::Ty,
diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs
index 0ac24eb54e7..b32909efe0b 100644
--- a/compiler/rustc_trait_selection/src/traits/effects.rs
+++ b/compiler/rustc_trait_selection/src/traits/effects.rs
@@ -1,4 +1,4 @@
-use rustc_hir as hir;
+use rustc_hir::{self as hir, LangItem};
 use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
 use rustc_infer::traits::{
     ImplDerivedHostCause, ImplSource, Obligation, ObligationCauseCode, PredicateObligation,
@@ -48,6 +48,12 @@ pub fn evaluate_host_effect_obligation<'tcx>(
         Err(EvaluationFailure::NoSolution) => {}
     }
 
+    match evaluate_host_effect_from_builtin_impls(selcx, obligation) {
+        Ok(result) => return Ok(result),
+        Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
+        Err(EvaluationFailure::NoSolution) => {}
+    }
+
     match evaluate_host_effect_from_selection_candiate(selcx, obligation) {
         Ok(result) => return Ok(result),
         Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
@@ -228,6 +234,104 @@ fn evaluate_host_effect_from_item_bounds<'tcx>(
     }
 }
 
+fn evaluate_host_effect_from_builtin_impls<'tcx>(
+    selcx: &mut SelectionContext<'_, 'tcx>,
+    obligation: &HostEffectObligation<'tcx>,
+) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
+    match selcx.tcx().as_lang_item(obligation.predicate.def_id()) {
+        Some(LangItem::Destruct) => evaluate_host_effect_for_destruct_goal(selcx, obligation),
+        _ => Err(EvaluationFailure::NoSolution),
+    }
+}
+
+// NOTE: Keep this in sync with `const_conditions_for_destruct` in the new solver.
+fn evaluate_host_effect_for_destruct_goal<'tcx>(
+    selcx: &mut SelectionContext<'_, 'tcx>,
+    obligation: &HostEffectObligation<'tcx>,
+) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
+    let tcx = selcx.tcx();
+    let destruct_def_id = tcx.require_lang_item(LangItem::Destruct, None);
+    let self_ty = obligation.predicate.self_ty();
+
+    let const_conditions = match *self_ty.kind() {
+        // An ADT is `~const Destruct` only if all of the fields are,
+        // *and* if there is a `Drop` impl, that `Drop` impl is also `~const`.
+        ty::Adt(adt_def, args) => {
+            let mut const_conditions: ThinVec<_> = adt_def
+                .all_fields()
+                .map(|field| ty::TraitRef::new(tcx, destruct_def_id, [field.ty(tcx, args)]))
+                .collect();
+            match adt_def.destructor(tcx).map(|dtor| dtor.constness) {
+                // `Drop` impl exists, but it's not const. Type cannot be `~const Destruct`.
+                Some(hir::Constness::NotConst) => return Err(EvaluationFailure::NoSolution),
+                // `Drop` impl exists, and it's const. Require `Ty: ~const Drop` to hold.
+                Some(hir::Constness::Const) => {
+                    let drop_def_id = tcx.require_lang_item(LangItem::Drop, None);
+                    let drop_trait_ref = ty::TraitRef::new(tcx, drop_def_id, [self_ty]);
+                    const_conditions.push(drop_trait_ref);
+                }
+                // No `Drop` impl, no need to require anything else.
+                None => {}
+            }
+            const_conditions
+        }
+
+        ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
+            thin_vec![ty::TraitRef::new(tcx, destruct_def_id, [ty])]
+        }
+
+        ty::Tuple(tys) => {
+            tys.iter().map(|field_ty| ty::TraitRef::new(tcx, destruct_def_id, [field_ty])).collect()
+        }
+
+        // Trivially implement `~const Destruct`
+        ty::Bool
+        | ty::Char
+        | ty::Int(..)
+        | ty::Uint(..)
+        | ty::Float(..)
+        | ty::Str
+        | ty::RawPtr(..)
+        | ty::Ref(..)
+        | ty::FnDef(..)
+        | ty::FnPtr(..)
+        | ty::Never
+        | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
+        | ty::Error(_) => thin_vec![],
+
+        // Coroutines and closures could implement `~const Drop`,
+        // but they don't really need to right now.
+        ty::Closure(_, _)
+        | ty::CoroutineClosure(_, _)
+        | ty::Coroutine(_, _)
+        | ty::CoroutineWitness(_, _) => return Err(EvaluationFailure::NoSolution),
+
+        // FIXME(unsafe_binders): Unsafe binders could implement `~const Drop`
+        // if their inner type implements it.
+        ty::UnsafeBinder(_) => return Err(EvaluationFailure::NoSolution),
+
+        ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
+            return Err(EvaluationFailure::NoSolution);
+        }
+
+        ty::Bound(..)
+        | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+            panic!("unexpected type `{self_ty:?}`")
+        }
+    };
+
+    Ok(const_conditions
+        .into_iter()
+        .map(|trait_ref| {
+            obligation.with(
+                tcx,
+                ty::Binder::dummy(trait_ref)
+                    .to_host_effect_clause(tcx, obligation.predicate.constness),
+            )
+        })
+        .collect())
+}
+
 fn evaluate_host_effect_from_selection_candiate<'tcx>(
     selcx: &mut SelectionContext<'_, 'tcx>,
     obligation: &HostEffectObligation<'tcx>,
diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr
index e0dbecff8e5..d688bfbde2b 100644
--- a/tests/ui/consts/fn_trait_refs.stderr
+++ b/tests/ui/consts/fn_trait_refs.stderr
@@ -155,90 +155,21 @@ note: `FnMut` can't be used with `~const` because it isn't annotated with `#[con
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error[E0277]: the trait bound `fn() -> i32 {one}: const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:70:32
+error[E0015]: cannot call non-const operator in constants
+  --> $DIR/fn_trait_refs.rs:71:17
    |
-LL |         let test_one = test_fn(one);
-   |                        ------- ^^^
-   |                        |
-   |                        required by a bound introduced by this call
+LL |         assert!(test_one == (1, 1, 1));
+   |                 ^^^^^^^^^^^^^^^^^^^^^
    |
-note: required by a bound in `test_fn`
-  --> $DIR/fn_trait_refs.rs:35:24
-   |
-LL | const fn test_fn<T>(mut f: T) -> (T::Output, T::Output, T::Output)
-   |          ------- required by a bound in this function
-LL | where
-LL |     T: ~const Fn<()> + ~const Destruct,
-   |                        ^^^^^^ required by this bound in `test_fn`
-
-error[E0277]: the trait bound `fn() -> i32 {two}: const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:73:36
-   |
-LL |         let test_two = test_fn_mut(two);
-   |                        ----------- ^^^
-   |                        |
-   |                        required by a bound introduced by this call
-   |
-note: required by a bound in `test_fn_mut`
-  --> $DIR/fn_trait_refs.rs:49:27
-   |
-LL | const fn test_fn_mut<T>(mut f: T) -> (T::Output, T::Output)
-   |          ----------- required by a bound in this function
-LL | where
-LL |     T: ~const FnMut<()> + ~const Destruct,
-   |                           ^^^^^^ required by this bound in `test_fn_mut`
+   = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
-error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:39:19
-   |
-LL |         tester_fn(&f),
-   |         --------- ^^
-   |         |
-   |         required by a bound introduced by this call
+error[E0015]: cannot call non-const operator in constants
+  --> $DIR/fn_trait_refs.rs:74:17
    |
-note: required by a bound in `tester_fn`
-  --> $DIR/fn_trait_refs.rs:14:24
+LL |         assert!(test_two == (2, 2));
+   |                 ^^^^^^^^^^^^^^^^^^
    |
-LL | const fn tester_fn<T>(f: T) -> T::Output
-   |          --------- required by a bound in this function
-LL | where
-LL |     T: ~const Fn<()> + ~const Destruct,
-   |                        ^^^^^^ required by this bound in `tester_fn`
-
-error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:41:23
-   |
-LL |         tester_fn_mut(&f),
-   |         ------------- ^^
-   |         |
-   |         required by a bound introduced by this call
-   |
-note: required by a bound in `tester_fn_mut`
-  --> $DIR/fn_trait_refs.rs:21:27
-   |
-LL | const fn tester_fn_mut<T>(mut f: T) -> T::Output
-   |          ------------- required by a bound in this function
-LL | where
-LL |     T: ~const FnMut<()> + ~const Destruct,
-   |                           ^^^^^^ required by this bound in `tester_fn_mut`
-
-error[E0277]: the trait bound `&mut T: ~const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:53:23
-   |
-LL |         tester_fn_mut(&mut f),
-   |         ------------- ^^^^^^
-   |         |
-   |         required by a bound introduced by this call
-   |
-note: required by a bound in `tester_fn_mut`
-  --> $DIR/fn_trait_refs.rs:21:27
-   |
-LL | const fn tester_fn_mut<T>(mut f: T) -> T::Output
-   |          ------------- required by a bound in this function
-LL | where
-LL |     T: ~const FnMut<()> + ~const Destruct,
-   |                           ^^^^^^ required by this bound in `tester_fn_mut`
+   = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/fn_trait_refs.rs:16:5
@@ -264,7 +195,7 @@ LL |     f()
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 25 previous errors
+error: aborting due to 22 previous errors
 
-Some errors have detailed explanations: E0015, E0277, E0635.
+Some errors have detailed explanations: E0015, E0635.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/promoted_const_call.stderr b/tests/ui/consts/promoted_const_call.stderr
index dd70bb601c4..40c6d083b06 100644
--- a/tests/ui/consts/promoted_const_call.stderr
+++ b/tests/ui/consts/promoted_const_call.stderr
@@ -5,6 +5,10 @@ LL |     let _: &'static _ = &id(&Panic);
    |                              ^^^^^ - value is dropped here
    |                              |
    |                              the destructor for this type cannot be evaluated in constants
+   |
+   = note: see issue #133214 <https://github.com/rust-lang/rust/issues/133214> for more information
+   = help: add `#![feature(const_destruct)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0716]: temporary value dropped while borrowed
   --> $DIR/promoted_const_call.rs:16:26
diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr
index 0f79cefeaec..f4e8a872cec 100644
--- a/tests/ui/impl-trait/normalize-tait-in-const.stderr
+++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr
@@ -17,20 +17,6 @@ note: `Fn` can't be used with `~const` because it isn't annotated with `#[const_
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error[E0277]: the trait bound `for<'a, 'b> fn(&'a foo::Alias<'b>) {foo}: const Destruct` is not satisfied
-  --> $DIR/normalize-tait-in-const.rs:33:19
-   |
-LL |     with_positive(foo);
-   |     ------------- ^^^
-   |     |
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `with_positive`
-  --> $DIR/normalize-tait-in-const.rs:26:62
-   |
-LL | const fn with_positive<F: for<'a> ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
-   |                                                              ^^^^^^ required by this bound in `with_positive`
-
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/normalize-tait-in-const.rs:27:5
    |
@@ -39,7 +25,6 @@ LL |     fun(filter_positive());
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0015, E0277.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/const-drop-bound.rs b/tests/ui/traits/const-traits/const-drop-bound.rs
index 398fb390640..4819da7c3a4 100644
--- a/tests/ui/traits/const-traits/const-drop-bound.rs
+++ b/tests/ui/traits/const-traits/const-drop-bound.rs
@@ -1,5 +1,4 @@
-//@ known-bug: #110395
-// FIXME check-pass
+//@ check-pass
 
 #![feature(const_trait_impl)]
 #![feature(const_precise_live_drops, const_destruct)]
diff --git a/tests/ui/traits/const-traits/const-drop-bound.stderr b/tests/ui/traits/const-traits/const-drop-bound.stderr
deleted file mode 100644
index 78ba0279566..00000000000
--- a/tests/ui/traits/const-traits/const-drop-bound.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0277]: the trait bound `Foo<E>: ~const Destruct` is not satisfied
-  --> $DIR/const-drop-bound.rs:23:9
-   |
-LL |     foo(res)
-   |     --- ^^^
-   |     |
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `foo`
-  --> $DIR/const-drop-bound.rs:9:61
-   |
-LL | const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Destruct {
-   |                                                             ^^^^^^ required by this bound in `foo`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr
index 7b2cafb6124..2b5e66b1a08 100644
--- a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr
@@ -1,9 +1,16 @@
-error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: const Destruct` is not satisfied
+error[E0277]: the trait bound `NonTrivialDrop: const A` is not satisfied
   --> $DIR/const-drop-fail-2.rs:31:23
    |
 LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `const Drop`
+  --> $DIR/const-drop-fail-2.rs:25:25
+   |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+   |         ------          ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
 note: required by a bound in `check`
   --> $DIR/const-drop-fail-2.rs:21:19
    |
diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr
index 7b2cafb6124..2b5e66b1a08 100644
--- a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr
@@ -1,9 +1,16 @@
-error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: const Destruct` is not satisfied
+error[E0277]: the trait bound `NonTrivialDrop: const A` is not satisfied
   --> $DIR/const-drop-fail-2.rs:31:23
    |
 LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `const Drop`
+  --> $DIR/const-drop-fail-2.rs:25:25
+   |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+   |         ------          ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
 note: required by a bound in `check`
   --> $DIR/const-drop-fail-2.rs:21:19
    |
diff --git a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr
index 8b3e777a0b0..682f48fe07a 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:32:5
+  --> $DIR/const-drop-fail.rs:33:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -8,13 +8,13 @@ LL |     NonTrivialDrop,
    |     ^^^^^^^^^^^^^^
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:23:19
+  --> $DIR/const-drop-fail.rs:24:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^ required by this bound in `check`
 
 error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:34:5
+  --> $DIR/const-drop-fail.rs:35:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -23,7 +23,7 @@ LL |     ConstImplWithDropGlue(NonTrivialDrop),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:23:19
+  --> $DIR/const-drop-fail.rs:24:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^ required by this bound in `check`
diff --git a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr
index 8b3e777a0b0..682f48fe07a 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:32:5
+  --> $DIR/const-drop-fail.rs:33:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -8,13 +8,13 @@ LL |     NonTrivialDrop,
    |     ^^^^^^^^^^^^^^
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:23:19
+  --> $DIR/const-drop-fail.rs:24:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^ required by this bound in `check`
 
 error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:34:5
+  --> $DIR/const-drop-fail.rs:35:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -23,7 +23,7 @@ LL |     ConstImplWithDropGlue(NonTrivialDrop),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:23:19
+  --> $DIR/const-drop-fail.rs:24:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^ required by this bound in `check`
diff --git a/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr
new file mode 100644
index 00000000000..682f48fe07a
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr
@@ -0,0 +1,33 @@
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+  --> $DIR/const-drop-fail.rs:33:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     NonTrivialDrop,
+   |     ^^^^^^^^^^^^^^
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:24:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+  --> $DIR/const-drop-fail.rs:35:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:24:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^ required by this bound in `check`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr
new file mode 100644
index 00000000000..682f48fe07a
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr
@@ -0,0 +1,33 @@
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+  --> $DIR/const-drop-fail.rs:33:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     NonTrivialDrop,
+   |     ^^^^^^^^^^^^^^
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:24:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+  --> $DIR/const-drop-fail.rs:35:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:24:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^ required by this bound in `check`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail.rs b/tests/ui/traits/const-traits/const-drop-fail.rs
index 5e05b9db474..a7f3d5654de 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.rs
+++ b/tests/ui/traits/const-traits/const-drop-fail.rs
@@ -1,8 +1,9 @@
-//@ compile-flags: -Znext-solver
-//@ revisions: stock precise
+//@[new_precise] compile-flags: -Znext-solver
+//@[new_stock] compile-flags: -Znext-solver
+//@ revisions: new_stock old_stock new_precise old_precise
 
 #![feature(const_trait_impl, const_destruct)]
-#![cfg_attr(precise, feature(const_precise_live_drops))]
+#![cfg_attr(any(new_precise, old_precise), feature(const_precise_live_drops))]
 
 use std::marker::{Destruct, PhantomData};