about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-01-09 17:52:21 +0100
committerGitHub <noreply@github.com>2024-01-09 17:52:21 +0100
commitf4d06256d8bb3c0cc54eee5f53a7012196ac1d29 (patch)
tree9ddb850d48658d766a12de4a3dd2bc8b39b3b9df
parent3da96aed94aa0f72a3632475ccc9510adbb8f8e0 (diff)
parent760673e97d48e131b87ec738cb7106c5f8abe55e (diff)
downloadrust-f4d06256d8bb3c0cc54eee5f53a7012196ac1d29.tar.gz
rust-f4d06256d8bb3c0cc54eee5f53a7012196ac1d29.zip
Rollup merge of #119721 - compiler-errors:constness-implication, r=fee1-dead
`~const` trait and projection bounds do not imply their non-const counterparts

This PR removes the hack where we install a non-const trait and projection bound for every `const_trait` and `~const` projection bound we have in the AST. It ends up messing up more things than it fixes, see words below.

Fixes #119718

cc `@fmease` `@fee1-dead` `@oli-obk`
r? fee1-dead or one of y'all i don't care

---

My understanding is that this hack was added to support the following code:

```rust
pub trait Owo<X = <Self as Uwu>::T> {}

#[const_trait]
pub trait Uwu: Owo {}
```

Which is concretely lifted from in the `FromResidual` and `Try` traits. Since within the param-env of `trait Uwu`, we only know that `Self: ~const Uwu` and not `Self: Uwu`, the projection `<Self as Uwu>::T` is not satsifyable.

This causes problems such as #119718, since instantiations of `FnDef` types coming from `const fn` really do **only** implement one of `FnOnce` or `const FnOnce`!

---

In the long-term, I believe that such code should really look something more like:

```rust
#[const_trait]
pub trait Owo<X = <Self as ~const Uwu>::T> {}

#[const_trait]
pub trait Uwu: Owo {}
```

... and that we should introduce some sort of `<T as ~const Foo>::Bar` bound syntax, since due to the fact that `~const` bounds can be present in item bounds, e.g.

```rust
#[const_trait] trait Foo { type Bar: ~const Destruct; }
```

It's easy to see that `<T as Foo>::Bar` and `<T as ~const Foo>::Bar` (or `<T as const Foo>::Bar`) can be distinct types with distinct item bounds!

**Admission**: I know I've said before that I don't like `~const` projection syntax, I do at this point believe they're necessary to fully express bounds and types in a maybe-const world.
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs35
-rw-r--r--compiler/rustc_hir_analysis/src/bounds.rs18
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs38
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs2
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr16
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs86
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs2
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr21
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs17
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs9
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr65
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr34
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs2
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr10
14 files changed, 227 insertions, 128 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index eb6a5cc5b21..cdfb4c6389e 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -1032,7 +1032,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             self.trait_defines_associated_item_named(r.def_id(), assoc_kind, assoc_name)
         });
 
-        let Some(mut bound) = matching_candidates.next() else {
+        let Some(bound) = matching_candidates.next() else {
             let reported = self.complain_about_assoc_item_not_found(
                 all_candidates,
                 &ty_param_name.to_string(),
@@ -1046,38 +1046,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         };
         debug!(?bound);
 
-        // look for a candidate that is not the same as our first bound, disregarding
-        // whether the bound is const.
-        let mut next_cand = matching_candidates.next();
-        while let Some(mut bound2) = next_cand {
-            debug!(?bound2);
-            if bound2.bound_vars() != bound.bound_vars() {
-                break;
-            }
-
-            let generics = tcx.generics_of(bound.def_id());
-            let Some(host_index) = generics.host_effect_index else { break };
-
-            // always return the bound that contains the host param.
-            if let ty::ConstKind::Param(_) = bound2.skip_binder().args.const_at(host_index).kind() {
-                (bound, bound2) = (bound2, bound);
-            }
-
-            let unconsted_args = bound
-                .skip_binder()
-                .args
-                .iter()
-                .enumerate()
-                .map(|(n, arg)| if host_index == n { tcx.consts.true_.into() } else { arg });
-
-            if unconsted_args.eq(bound2.skip_binder().args.iter()) {
-                next_cand = matching_candidates.next();
-            } else {
-                break;
-            }
-        }
-
-        if let Some(bound2) = next_cand {
+        if let Some(bound2) = matching_candidates.next() {
             debug!(?bound2);
 
             let assoc_kind_str = assoc_kind_str(assoc_kind);
diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
index b6688e0ce29..b69f679880d 100644
--- a/compiler/rustc_hir_analysis/src/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/bounds.rs
@@ -45,24 +45,6 @@ impl<'tcx> Bounds<'tcx> {
         polarity: ty::ImplPolarity,
     ) {
         self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
-
-        // push a non-const (`host = true`) version of the bound if it is `~const`.
-        if tcx.features().effects
-            && let Some(host_effect_idx) = tcx.generics_of(trait_ref.def_id()).host_effect_index
-            && trait_ref.skip_binder().args.const_at(host_effect_idx) != tcx.consts.true_
-        {
-            let generics = tcx.generics_of(trait_ref.def_id());
-            let Some(host_index) = generics.host_effect_index else { return };
-            let trait_ref = trait_ref.map_bound(|mut trait_ref| {
-                trait_ref.args =
-                    tcx.mk_args_from_iter(trait_ref.args.iter().enumerate().map(|(n, arg)| {
-                        if host_index == n { tcx.consts.true_.into() } else { arg }
-                    }));
-                trait_ref
-            });
-
-            self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
-        }
     }
 
     fn push_trait_bound_inner(
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 41520718aa8..ab9ed6ef98d 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -11,7 +11,7 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, ToPredicate};
 use rustc_span::symbol::Ident;
-use rustc_span::{sym, Span, DUMMY_SP};
+use rustc_span::{Span, DUMMY_SP};
 
 /// Returns a list of all type predicates (explicit and implicit) for the definition with
 /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
@@ -38,38 +38,12 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
         // an obligation and instead be skipped. Otherwise we'd use
         // `tcx.def_span(def_id);`
         let span = rustc_span::DUMMY_SP;
-        let non_const_bound = if tcx.features().effects && tcx.has_attr(def_id, sym::const_trait) {
-            // when `Self` is a const trait, also add `Self: Trait<.., true>` as implied bound,
-            // because only implementing `Self: Trait<.., false>` is currently not possible.
-            Some((
-                ty::TraitRef::new(
-                    tcx,
-                    def_id,
-                    ty::GenericArgs::for_item(tcx, def_id, |param, _| {
-                        if param.is_host_effect() {
-                            tcx.consts.true_.into()
-                        } else {
-                            tcx.mk_param_from_def(param)
-                        }
-                    }),
-                )
-                .to_predicate(tcx),
+
+        result.predicates =
+            tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
+                ty::TraitRef::identity(tcx, def_id).to_predicate(tcx),
                 span,
-            ))
-        } else {
-            None
-        };
-        result.predicates = tcx.arena.alloc_from_iter(
-            result
-                .predicates
-                .iter()
-                .copied()
-                .chain(std::iter::once((
-                    ty::TraitRef::identity(tcx, def_id).to_predicate(tcx),
-                    span,
-                )))
-                .chain(non_const_bound),
-        );
+            ))));
     }
     debug!("predicates_of(def_id={:?}) = {:?}", def_id, result);
     result
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs
index f41c1051fce..16b717bc181 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs
@@ -9,7 +9,7 @@ trait Foo {
 }
 
 const fn foo<T: ~const Foo>() {
-    <T as Foo>::Assoc::foo();
+    <T as /* FIXME: ~const */ Foo>::Assoc::foo();
 }
 
 fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr
index 1b88839984f..268e337ee93 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr
@@ -6,15 +6,17 @@ LL |     type Assoc: ~const Foo;
    |
    = note: this item cannot have `~const` trait bounds
 
-error[E0308]: mismatched types
-  --> $DIR/assoc-type-const-bound-usage.rs:12:5
+error[E0277]: the trait bound `T: Foo` is not satisfied
+  --> $DIR/assoc-type-const-bound-usage.rs:12:6
    |
-LL |     <T as Foo>::Assoc::foo();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ expected `host`, found `true`
+LL |     <T as /* FIXME: ~const */ Foo>::Assoc::foo();
+   |      ^ the trait `Foo` is not implemented for `T`
    |
-   = note: expected constant `host`
-              found constant `true`
+help: consider further restricting this bound
+   |
+LL | const fn foo<T: ~const Foo + Foo>() {
+   |                            +++++
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs
new file mode 100644
index 00000000000..f3480fcc9ee
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs
@@ -0,0 +1,86 @@
+// check-pass
+
+#![crate_type = "lib"]
+#![allow(internal_features)]
+#![no_std]
+#![no_core]
+#![feature(
+    auto_traits,
+    const_trait_impl,
+    effects,
+    lang_items,
+    no_core,
+    staged_api,
+    unboxed_closures
+)]
+#![stable(feature = "minicore", since = "1.0.0")]
+
+fn test() {
+    fn is_const_fn<F>(_: F)
+    where
+        F: const FnOnce<()>,
+    {
+    }
+
+    const fn foo() {}
+
+    is_const_fn(foo);
+}
+
+/// ---------------------------------------------------------------------- ///
+/// Const fn trait definitions
+
+#[const_trait]
+#[lang = "fn"]
+#[rustc_paren_sugar]
+trait Fn<Args: Tuple>: ~const FnMut<Args> {
+    extern "rust-call" fn call(&self, args: Args) -> Self::Output;
+}
+
+#[const_trait]
+#[lang = "fn_mut"]
+#[rustc_paren_sugar]
+trait FnMut<Args: Tuple>: ~const FnOnce<Args> {
+    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+}
+
+#[const_trait]
+#[lang = "fn_once"]
+#[rustc_paren_sugar]
+trait FnOnce<Args: Tuple> {
+    #[lang = "fn_once_output"]
+    type Output;
+
+    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+/// ---------------------------------------------------------------------- ///
+/// All this other stuff needed for core. Unrelated to test.
+
+#[lang = "destruct"]
+#[const_trait]
+trait Destruct {}
+
+#[lang = "freeze"]
+unsafe auto trait Freeze {}
+
+#[lang = "drop"]
+#[const_trait]
+trait Drop {
+    fn drop(&mut self);
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+#[lang = "tuple_trait"]
+trait Tuple {}
+
+#[lang = "receiver"]
+trait Receiver {}
+
+impl<T: ?Sized> Receiver for &T {}
+
+impl<T: ?Sized> Receiver for &mut T {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs
index 14d306fc31f..9d579e67a4b 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs
@@ -1,4 +1,6 @@
 // known-bug: #110395
+// Broken until we have `&T: const Deref` impl in stdlib
+
 #![allow(incomplete_features)]
 #![feature(
     associated_type_bounds,
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr
index d0ca1b19ad1..d4be71f2f46 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr
@@ -1,5 +1,5 @@
 error[E0277]: can't compare `()` with `()`
-  --> $DIR/const-impl-trait.rs:35:17
+  --> $DIR/const-impl-trait.rs:37:17
    |
 LL |     assert!(cmp(&()));
    |             --- ^^^ no implementation for `() == ()`
@@ -9,23 +9,20 @@ LL |     assert!(cmp(&()));
    = help: the trait `const PartialEq` is not implemented for `()`
    = help: the trait `PartialEq` is implemented for `()`
 note: required by a bound in `cmp`
-  --> $DIR/const-impl-trait.rs:12:23
+  --> $DIR/const-impl-trait.rs:14:23
    |
 LL | const fn cmp(a: &impl ~const PartialEq) -> bool {
    |                       ^^^^^^^^^^^^^^^^ required by this bound in `cmp`
 
-error[E0277]: can't compare `&impl ~const PartialEq` with `&impl ~const PartialEq`
-  --> $DIR/const-impl-trait.rs:13:7
+error[E0369]: binary operation `==` cannot be applied to type `&impl ~const PartialEq`
+  --> $DIR/const-impl-trait.rs:15:7
    |
 LL |     a == a
-   |       ^^ no implementation for `&impl ~const PartialEq == &impl ~const PartialEq`
-   |
-   = help: the trait `~const PartialEq<&impl ~const PartialEq>` is not implemented for `&impl ~const PartialEq`
-help: consider dereferencing both sides of the expression
-   |
-LL |     *a == *a
-   |     +     +
+   |     - ^^ - &impl ~const PartialEq
+   |     |
+   |     &impl ~const PartialEq
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0277, E0369.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs
index 59fb48e794c..84d9bcd7ac9 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs
@@ -40,7 +40,7 @@ const fn bar() {
 
 #[lang = "Try"]
 #[const_trait]
-trait Try: FromResidual {
+trait Try: FromResidual<Self::Residual> {
     type Output;
     type Residual;
 
@@ -53,7 +53,7 @@ trait Try: FromResidual {
 
 // FIXME
 // #[const_trait]
-trait FromResidual<R = <Self as Try>::Residual> {
+trait FromResidual<R = <Self as /* FIXME: ~const */ Try>::Residual> {
     #[lang = "from_residual"]
     fn from_residual(residual: R) -> Self;
 }
@@ -519,9 +519,14 @@ extern "rust-intrinsic" {
         called_in_const: F,
         called_at_rt: G,
     ) -> RET
-    /* where clauses enforced by built-in method confirmation:
     where
-        F: const FnOnce<Arg, Output = RET>,
-        G: FnOnce<Arg, Output = RET>,
-     */;
+        F: const FnOnce<ARG, Output = RET>,
+        G: FnOnce<ARG, Output = RET>;
+}
+
+fn test_const_eval_select() {
+    const fn const_fn() {}
+    fn rt_fn() {}
+
+    unsafe { const_eval_select((), const_fn, rt_fn); }
 }
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs
index b30d7743edf..e22eed3e0ef 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs
@@ -1,7 +1,12 @@
-// check-pass
+// known-bug: #110395
+// FIXME: effects
+
 #![feature(const_trait_impl, effects)]
 
-pub trait Owo<X = <Self as Uwu>::T> {}
+// This fails because `~const Uwu` doesn't imply (non-const) `Uwu`.
+
+// FIXME: #[const_trait]
+pub trait Owo<X = <Self as /* FIXME: ~const */ Uwu>::T> {}
 
 #[const_trait]
 pub trait Uwu: Owo {
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr
new file mode 100644
index 00000000000..eac3ee9e4e2
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr
@@ -0,0 +1,65 @@
+error[E0277]: the trait bound `Self: Uwu` is not satisfied
+  --> $DIR/project.rs:12:1
+   |
+LL | pub trait Uwu: Owo {
+   | ^^^^^^^^^^^^^^^^^^ the trait `Uwu` is not implemented for `Self`
+   |
+help: consider further restricting `Self`
+   |
+LL | pub trait Uwu: Owo + Uwu {
+   |                    +++++
+
+error[E0277]: the trait bound `Self: Uwu` is not satisfied
+  --> $DIR/project.rs:12:1
+   |
+LL | / pub trait Uwu: Owo {
+LL | |     type T;
+LL | | }
+   | |_^ the trait `Uwu` is not implemented for `Self`
+   |
+help: consider further restricting `Self`
+   |
+LL | pub trait Uwu: Owo + Uwu {
+   |                    +++++
+
+error[E0277]: the trait bound `Self: Uwu` is not satisfied
+  --> $DIR/project.rs:12:16
+   |
+LL | pub trait Uwu: Owo {
+   |                ^^^ the trait `Uwu` is not implemented for `Self`
+   |
+note: required by a bound in `Owo`
+  --> $DIR/project.rs:9:15
+   |
+LL | pub trait Owo<X = <Self as /* FIXME: ~const */ Uwu>::T> {}
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Owo`
+help: consider further restricting `Self`
+   |
+LL | pub trait Uwu: Owo + Uwu {
+   |                    +++++
+
+error[E0277]: the trait bound `Self: Uwu` is not satisfied
+  --> $DIR/project.rs:13:5
+   |
+LL |     type T;
+   |     ^^^^^^ the trait `Uwu` is not implemented for `Self`
+   |
+help: consider further restricting `Self`
+   |
+LL | pub trait Uwu: Owo + Uwu {
+   |                    +++++
+
+error[E0277]: the trait bound `Self: Uwu` is not satisfied
+  --> $DIR/project.rs:13:5
+   |
+LL |     type T;
+   |     ^^^^^^^ the trait `Uwu` is not implemented for `Self`
+   |
+help: consider further restricting `Self`
+   |
+LL | pub trait Uwu: Owo + Uwu {
+   |                    +++++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr
index 2a9647da782..0141dcfb06f 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr
@@ -1,21 +1,35 @@
-error[E0308]: mismatched types
+error[E0277]: the trait bound `T: ~const Bar` is not satisfied
   --> $DIR/trait-where-clause-const.rs:21:5
    |
 LL |     T::b();
-   |     ^^^^^^ expected `host`, found `true`
+   |     ^ the trait `~const Bar` is not implemented for `T`
    |
-   = note: expected constant `host`
-              found constant `true`
+note: required by a bound in `Foo::b`
+  --> $DIR/trait-where-clause-const.rs:15:24
+   |
+LL |     fn b() where Self: ~const Bar;
+   |                        ^^^^^^^^^^ required by this bound in `Foo::b`
+help: consider further restricting this bound
+   |
+LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
+   |                                    ++++++++++++
 
-error[E0308]: mismatched types
-  --> $DIR/trait-where-clause-const.rs:23:5
+error[E0277]: the trait bound `T: ~const Bar` is not satisfied
+  --> $DIR/trait-where-clause-const.rs:23:12
    |
 LL |     T::c::<T>();
-   |     ^^^^^^^^^^^ expected `host`, found `true`
+   |            ^ the trait `~const Bar` is not implemented for `T`
+   |
+note: required by a bound in `Foo::c`
+  --> $DIR/trait-where-clause-const.rs:16:13
+   |
+LL |     fn c<T: ~const Bar>();
+   |             ^^^^^^^^^^ required by this bound in `Foo::c`
+help: consider further restricting this bound
    |
-   = note: expected constant `host`
-              found constant `true`
+LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
+   |                                    ++++++++++++
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs
index 62a7b312378..8f441410c17 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs
@@ -30,4 +30,4 @@ fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
 // FIXME(effects): Instead of suggesting `+ const Trait`, suggest
 //                 changing `~const Trait` to `const Trait`.
 const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
-//~^ ERROR the trait bound `T: const Trait` is not satisfied
+//~^ ERROR mismatched types
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr
index 2fb4fc1aa2b..258f95b5c4a 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr
@@ -7,16 +7,14 @@ LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
    = note: expected constant `false`
               found constant `true`
 
-error[E0277]: the trait bound `T: const Trait` is not satisfied
+error[E0308]: mismatched types
   --> $DIR/unsatisfied-const-trait-bound.rs:32:50
    |
 LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
-   |                                                  ^ the trait `const Trait` is not implemented for `T`
-   |
-help: consider further restricting this bound
+   |                                                  ^^^^^^^^^ expected `false`, found `host`
    |
-LL | const fn accept1<T: ~const Trait + const Trait>(_: Container<{ T::make() }>) {}
-   |                                  +++++++++++++
+   = note: expected constant `false`
+              found constant `host`
 
 error[E0277]: the trait bound `Ty: const Trait` is not satisfied
   --> $DIR/unsatisfied-const-trait-bound.rs:20:15