diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6174c922e2d06..2d8ee549f48dd 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -803,6 +803,10 @@ impl<'tcx> PolyTraitPredicate<'tcx> { p }); } + + pub fn is_const(self) -> bool { + self.skip_binder().constness == BoundConstness::ConstIfConst + } } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] @@ -1388,6 +1392,10 @@ impl<'tcx> ParamEnv<'tcx> { self.packed.tag().constness } + pub fn is_const(self) -> bool { + self.packed.tag().constness == hir::Constness::Const + } + /// Construct a trait environment with no where-clauses in scope /// where the values of all `impl Trait` and other hidden types /// are revealed. This is suitable for monomorphized, post-typeck @@ -1503,6 +1511,7 @@ impl<'tcx> PolyTraitRef<'tcx> { polarity: ty::ImplPolarity::Positive, }) } + #[inline] pub fn without_const(self) -> PolyTraitPredicate<'tcx> { self.with_constness(BoundConstness::NotConst) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 37cf41a0ec2e2..081f823f851c6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -439,6 +439,28 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } else { err.span_label(span, explanation); } + + if trait_predicate.is_const() && obligation.param_env.is_const() { + let non_const_predicate = trait_ref.without_const(); + let non_const_obligation = Obligation { + cause: obligation.cause.clone(), + param_env: obligation.param_env.without_const(), + predicate: non_const_predicate.to_predicate(tcx), + recursion_depth: obligation.recursion_depth, + }; + if self.predicate_may_hold(&non_const_obligation) { + err.span_note( + span, + &format!( + "the trait `{}` is implemented for `{}`, \ + but that implementation is not `const`", + non_const_predicate.print_modifiers_and_trait_path(), + trait_ref.skip_binder().self_ty(), + ), + ); + } + } + if let Some((msg, span)) = type_def { err.span_label(span, &msg); } diff --git a/src/test/ui/intrinsics/const-eval-select-bad.stderr b/src/test/ui/intrinsics/const-eval-select-bad.stderr index 083b00645388e..06a7a2f63cf5a 100644 --- a/src/test/ui/intrinsics/const-eval-select-bad.stderr +++ b/src/test/ui/intrinsics/const-eval-select-bad.stderr @@ -7,6 +7,11 @@ LL | const_eval_select((), || {}, || {}); | required by a bound introduced by this call | = help: the trait `~const FnOnce<()>` is not implemented for `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` +note: the trait `FnOnce<()>` is implemented for `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]`, but that implementation is not `const` + --> $DIR/const-eval-select-bad.rs:6:27 + | +LL | const_eval_select((), || {}, || {}); + | ^^^^^ = note: wrap the `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics.rs:LL:COL diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr index 429b9f3364be1..0788b17a1c032 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr @@ -5,6 +5,11 @@ LL | type Bar = NonConstAdd; | ^^^^^^^^^^^ no implementation for `NonConstAdd + NonConstAdd` | = help: the trait `~const Add` is not implemented for `NonConstAdd` +note: the trait `Add` is implemented for `NonConstAdd`, but that implementation is not `const` + --> $DIR/assoc-type.rs:18:16 + | +LL | type Bar = NonConstAdd; + | ^^^^^^^^^^^ note: required by a bound in `Foo::Bar` --> $DIR/assoc-type.rs:14:15 | diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr index 13cffaba91a1d..35b7fe8e401c3 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr @@ -7,6 +7,11 @@ LL | pub const EQ: bool = equals_self(&S); | required by a bound introduced by this call | = help: the trait `~const PartialEq` is not implemented for `S` +note: the trait `PartialEq` is implemented for `S`, but that implementation is not `const` + --> $DIR/call-generic-method-nonconst.rs:19:34 + | +LL | pub const EQ: bool = equals_self(&S); + | ^^ note: required by a bound in `equals_self` --> $DIR/call-generic-method-nonconst.rs:12:25 | 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 index df776908a0365..d280cd2556f06 100644 --- 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 @@ -28,6 +28,11 @@ LL | const _: () = check($exp); LL | ConstImplWithDropGlue(NonTrivialDrop), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Drop` is not implemented for `NonTrivialDrop` | +note: the trait `Drop` is implemented for `NonTrivialDrop`, but that implementation is not `const` + --> $DIR/const-drop-fail.rs:46:5 + | +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required because it appears within the type `ConstImplWithDropGlue` --> $DIR/const-drop-fail.rs:17:8 | 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 index df776908a0365..d280cd2556f06 100644 --- 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 @@ -28,6 +28,11 @@ LL | const _: () = check($exp); LL | ConstImplWithDropGlue(NonTrivialDrop), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Drop` is not implemented for `NonTrivialDrop` | +note: the trait `Drop` is implemented for `NonTrivialDrop`, but that implementation is not `const` + --> $DIR/const-drop-fail.rs:46:5 + | +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required because it appears within the type `ConstImplWithDropGlue` --> $DIR/const-drop-fail.rs:17:8 | diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr index 05a74757b94f1..bc807507fd668 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr @@ -4,6 +4,11 @@ error[E0277]: the trait bound `(): ~const Tr` is not satisfied LL | foo::<()>(); | ^^ the trait `~const Tr` is not implemented for `()` | +note: the trait `Tr` is implemented for `()`, but that implementation is not `const` + --> $DIR/default-method-body-is-const-body-checking.rs:12:15 + | +LL | foo::<()>(); + | ^^ note: required by a bound in `foo` --> $DIR/default-method-body-is-const-body-checking.rs:7:28 | diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr index 903cd924ca55b..f9b5d81c63b85 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr @@ -4,6 +4,11 @@ error[E0277]: the trait bound `T: ~const Bar` is not satisfied LL | T::b(); | ^^^^ the trait `~const Bar` is not implemented for `T` | +note: the trait `Bar` is implemented for `T`, but that implementation is not `const` + --> $DIR/trait-where-clause.rs:14:5 + | +LL | T::b(); + | ^^^^ note: required by a bound in `Foo::b` --> $DIR/trait-where-clause.rs:8:24 | @@ -20,6 +25,11 @@ error[E0277]: the trait bound `T: ~const Bar` is not satisfied LL | T::c::(); | ^^^^^^^^^ the trait `~const Bar` is not implemented for `T` | +note: the trait `Bar` is implemented for `T`, but that implementation is not `const` + --> $DIR/trait-where-clause.rs:16:5 + | +LL | T::c::(); + | ^^^^^^^^^ note: required by a bound in `Foo::c` --> $DIR/trait-where-clause.rs:9:13 |