about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-10-24 17:33:42 +0000
committerbors <bors@rust-lang.org>2024-10-24 17:33:42 +0000
commit1d4a7670d4f37bfbae2d89ec3ec07cd40dbc5a5d (patch)
tree94ee84d3fa4ac9456a3a6213c74cc05938442435
parentf61306d47bc98af8bb9d15f1adf6086785590a8c (diff)
parent0f5a47d0884d9d3966f0f4a54e9e9a02cb5f482d (diff)
downloadrust-1d4a7670d4f37bfbae2d89ec3ec07cd40dbc5a5d.tar.gz
rust-1d4a7670d4f37bfbae2d89ec3ec07cd40dbc5a5d.zip
Auto merge of #131985 - compiler-errors:const-pred, r=fee1-dead
Represent trait constness as a distinct predicate

cc `@rust-lang/project-const-traits`
r? `@ghost` for now

Also mirrored everything that is written below on this hackmd here: https://hackmd.io/`@compiler-errors/r12zoixg1l`

# Tl;dr:

* This PR removes the bulk of the old effect desugaring.
* This PR reimplements most of the effect desugaring as a new predicate and set of a couple queries. I believe it majorly simplifies the implementation and allows us to move forward more easily on its implementation.

I'm putting this up both as a request for comments and a vibe-check, but also as a legitimate implementation that I'd like to see land (though no rush of course on that last part).

## Background

### Early days

Once upon a time, we represented trait constness in the param-env and in `TraitPredicate`. This was very difficult to implement correctly; it had bugs and was also incomplete; I don't think this was anyone's fault though, it was just the limit of experimental knowledge we had at that point.

Dealing with `~const` within predicates themselves meant dealing with constness all throughout the trait solver. This was difficult to keep track of, and afaict was not handled well with all the corners of candidate assembly.

Specifically, we had to (in various places) remap constness according to the param-env constness:

https://github.com/rust-lang/rust/blob/574b64a97f52162f965bc201e47f0af8279ca65d/compiler/rustc_trait_selection/src/traits/select/mod.rs#L1498

This was annoying and manual and also error prone.

### Beginning of the effects desugaring

Later on, #113210 reimplemented a new desugaring for const traits via a `<const HOST: bool>` predicate. This essentially "reified" the const checking and separated it from any of the remapping or separate tracking in param-envs. For example, if I was in a const-if-const environment, but I wanted to call a trait that was non-const, this reification would turn the constness mismatch into a simple *type* mismatch of the effect parameter.

While this was a monumental step towards straightening out const trait checking in the trait system, it had its own issues, since that meant that the constness of a trait (or any item within it, like an associated type) was *early-bound*. This essentially meant that `<T as Trait>::Assoc` was *distinct* from `<T as ~const Trait>::Assoc`, which was bad.

### Associated-type bound based effects desugaring

After this, #120639 implemented a new effects desugaring. This used an associated type to more clearly represent the fact that the constness is not an input parameter of a trait, but a property that could be computed of a impl. The write-up linked in that PR explains it better than I could.

However, I feel like it really reached the limits of what can comfortably be expressed in terms of associated type and trait calculus. Also, `<const HOST: bool>` remains a synthetic const parameter, which is observable in nested items like RPITs and closures, and comes with tons of its own hacks in the astconv and middle layer.

For example, there are pieces of unintuitive code that are needed to represent semantics like elaboration, and eventually will be needed to make error reporting intuitive, and hopefully in the future assist us in implementing built-in traits (eventually we'll want something like `~const Fn` trait bounds!).

elaboration hack: https://github.com/rust-lang/rust/blob/8069f8d17a6c86a8fd881939fcce359a90c57ff2/compiler/rustc_type_ir/src/elaborate.rs#L133-L195

trait bound remapping hack for diagnostics: https://github.com/rust-lang/rust/blob/8069f8d17a6c86a8fd881939fcce359a90c57ff2/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs#L2370-L2413

I want to be clear that I don't think this is a issue of implementation quality or anything like that; I think it's simply a very clear sign that we're using types and traits in a way that they're not fundamentally supposed to be used, especially given that constness deserves to be represented as a first-class concept.

### What now?

This PR implements a new desugaring for const traits. Specifically, it introduces a `HostEffect` predicate to represent the obligation an impl is const, rather than using associated type bounds and the compat trait that exists for effects today.

### `HostEffect` predicate

A `HostEffect` clause has two parts -- the `TraitRef` we're trying to prove, and a `HostPolarity::{Maybe, Const}`.

`HostPolarity::Const` corresponds to `T: const Trait` bounds, which must *always* be proven as const, and which can be written in any context. These are lowered directly into the predicates of an item, since they're not "context-specific".

On the other hand, `HostPolarity::Maybe` corresponds to `T: ~const Trait` bounds which must only exist in a conditionally-const context like a method in a `#[const_trait]`, or a `const fn` free function. We do not lower these immediately into the predicates of an item; instead, we collect them into a new query called the **`const_conditions`**. These are the set of trait refs that we need to prove have const implementations for an item to be const.

Notably, they're represented as bare (poly) trait refs because they are meant to be paired back together with a `HostPolarity` when they're being registered in typeck (see next section).

For example, given:

```rust
const fn foo<T: ~const A + const B>() {}
```

`foo`'s const conditions would contain `T: A`, but not `T: B`. On the flip side, foo's predicates (`predicates_of`) query would contain `HostEffect(T: B, HostPolarity::Const)` but not `HostEffect(T: A, HostPolarity::Maybe)` since we don't need to prove that predicate in a non-const environment (and it's not even the right predicate to prove in an unconditionally const environment).

### Type checking const bodies

When type checking bodies in HIR, when we encounter a call expression, we additionally register the callee item's const conditions with the `HostPolarity` from the body we're typechecking (`Const` for unconditionally const things like `const`/`static` items, and `Maybe` for conditionally const things like const fns; and we don't register `HostPolarity` predicates for non-const bodies).

When type-checking a conditionally const body, we augment its param-env with `HostEffect(..., Maybe)` predicates.

### Checking that const impls are WF

We extend the logic in `compare_method_predicate_entailment` to also check the const-conditions of the impl method, to make sure that we error for:

```rust
#[const_trait] Bar {}
#[const_trait] trait Foo {
    fn method<T: Bar>();
}

impl Foo for () {
    fn method<T: ~const Bar>() {} // stronger assumption!
}
```

We also extend the WF check for impls to register the const conditions of the trait that is being implemented. This is to make sure we error for:

```rust
#[const_trait] trait Bar {}
#[const_trait] trait Foo<T> where T: ~const Bar {}

impl<T> const Foo<T> for () {}
//~^ `T: ~const Bar` is missing!
```

### Proving a `HostEffect` predicate

We have several ways of proving a `HostEffect` predicate:

1. Matching a `HostEffect` predicate from the param-env
2. From an impl - we do impl selection very similar to confirming a trait goal, except we filter for only const impls, and we additionally register the impl's const conditions (i.e. the impl's `~const` where clauses).

Later I expect that we will add more built-in implementations for things like `Fn`.

## What next?

After this PR, I'd like to split out the work more so it can proceed in parallel and probably amongst others that are not me.

* Register `HostEffect` goal for places in HIR typeck that correspond to call terminators, like autoderef.
* Make traits in libstd const again.
    * Probably need to impl host effect preds in old solver.
* Implement built-in `HostEffect` rules for traits like `Fn`.
* Rip out const checking from MIR altogether.

## So what?

This ends up being super convenient basically everywhere in the compiler. Due to the design of the new trait solver, we end up having an almost parallel structure to the existing trait and projection predicates for assembling `HostEffect` predicates; adding new candidates and especially new built-in implementations is now basically trivial, and it's quite straightforward to understand the confirmation logic for these predicates.

Same with diagnostics reporting; since we have predicates which represent the obligation to prove an impl is const, we can simplify and make these diagnostics richer without having to write a ton of logic to intercept and rewrite the existing `Compat` trait errors.

Finally, it gives us a much more straightforward path for supporting the const effect on the old trait solver. I'm personally quite passionate about getting const trait support into the hands of users without having to wait until the new solver lands[^1], so I think after this PR lands we can begin to gauge how difficult it would be to implement constness in the old trait solver too. This PR will not do this yet.

[^1]: Though this is not a prerequisite or by any means the only justification for this PR.
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs205
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs20
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs4
-rw-r--r--compiler/rustc_hir/src/hir.rs1
-rw-r--r--compiler/rustc_hir/src/intravisit.rs2
-rw-r--r--compiler/rustc_hir/src/lang_items.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/bounds.rs154
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs109
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs44
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs33
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs36
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs220
-rw-r--r--compiler/rustc_hir_analysis/src/delegation.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs42
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs59
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/explicit.rs3
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs51
-rw-r--r--compiler/rustc_hir_typeck/src/fallback.rs29
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs26
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs3
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs14
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs10
-rw-r--r--compiler/rustc_infer/src/infer/context.rs21
-rw-r--r--compiler/rustc_infer/src/infer/freshen.rs9
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs74
-rw-r--r--compiler/rustc_infer/src/infer/outlives/mod.rs14
-rw-r--r--compiler/rustc_infer/src/infer/relate/generalize.rs1
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs3
-rw-r--r--compiler/rustc_infer/src/infer/snapshot/fudge.rs27
-rw-r--r--compiler/rustc_infer/src/infer/snapshot/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/snapshot/undo_log.rs5
-rw-r--r--compiler/rustc_lint/src/builtin.rs4
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs6
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs3
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs15
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs3
-rw-r--r--compiler/rustc_middle/src/infer/unify_key.rs67
-rw-r--r--compiler/rustc_middle/src/query/erase.rs1
-rw-r--r--compiler/rustc_middle/src/query/mod.rs24
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs11
-rw-r--r--compiler/rustc_middle/src/ty/context.rs40
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs3
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs10
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs9
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs89
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs1
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs80
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs1
-rw-r--r--compiler/rustc_middle/src/ty/predicate.rs4
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs10
-rw-r--r--compiler/rustc_middle/src/ty/util.rs46
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs1
-rw-r--r--compiler/rustc_next_trait_solver/src/canonicalizer.rs1
-rw-r--r--compiler/rustc_next_trait_solver/src/resolve.rs3
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs8
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/effect_goals.rs296
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs3
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/mod.rs7
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs62
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/trait_goals.rs41
-rw-r--r--compiler/rustc_privacy/src/lib.rs4
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs6
-rw-r--r--compiler/rustc_span/src/symbol.rs9
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs80
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs5
-rw-r--r--compiler/rustc_traits/src/normalize_erasing_regions.rs1
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs139
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs10
-rw-r--r--compiler/rustc_type_ir/src/canonical.rs22
-rw-r--r--compiler/rustc_type_ir/src/const_kind.rs23
-rw-r--r--compiler/rustc_type_ir/src/effects.rs59
-rw-r--r--compiler/rustc_type_ir/src/elaborate.rs75
-rw-r--r--compiler/rustc_type_ir/src/infer_ctxt.rs10
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs8
-rw-r--r--compiler/rustc_type_ir/src/interner.rs11
-rw-r--r--compiler/rustc_type_ir/src/ir_print.rs5
-rw-r--r--compiler/rustc_type_ir/src/lang_items.rs7
-rw-r--r--compiler/rustc_type_ir/src/lib.rs2
-rw-r--r--compiler/rustc_type_ir/src/predicate.rs65
-rw-r--r--compiler/rustc_type_ir/src/predicate_kind.rs7
-rw-r--r--compiler/rustc_type_ir/src/relate/combine.rs28
-rw-r--r--compiler/stable_mir/src/ty.rs1
-rw-r--r--library/core/src/marker.rs44
-rw-r--r--src/librustdoc/clean/auto_trait.rs2
-rw-r--r--src/librustdoc/clean/mod.rs10
-rw-r--r--src/librustdoc/clean/types.rs3
-rw-r--r--src/librustdoc/clean/utils.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs14
-rw-r--r--tests/crashes/118320.rs14
-rw-r--r--tests/crashes/119924-6.rs15
-rw-r--r--tests/ui/const-generics/issues/issue-88119.stderr18
-rw-r--r--tests/ui/consts/const-block-const-bound.stderr10
-rw-r--r--tests/ui/consts/const-try.rs4
-rw-r--r--tests/ui/consts/const-try.stderr9
-rw-r--r--tests/ui/consts/constifconst-call-in-const-position.stderr20
-rw-r--r--tests/ui/consts/fn_trait_refs.stderr74
-rw-r--r--tests/ui/consts/unstable-const-fn-in-libcore.stderr10
-rw-r--r--tests/ui/delegation/ice-issue-124347.rs2
-rw-r--r--tests/ui/delegation/ice-issue-124347.stderr12
-rw-r--r--tests/ui/delegation/unsupported.rs2
-rw-r--r--tests/ui/delegation/unsupported.stderr12
-rw-r--r--tests/ui/impl-trait/normalize-tait-in-const.stderr18
-rw-r--r--tests/ui/specialization/const_trait_impl.stderr62
-rw-r--r--tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs1
-rw-r--r--tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.stderr47
-rw-r--r--tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs2
-rw-r--r--tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.stderr45
-rw-r--r--tests/ui/traits/const-traits/assoc-type.rs5
-rw-r--r--tests/ui/traits/const-traits/assoc-type.stderr16
-rw-r--r--tests/ui/traits/const-traits/call-const-closure.rs22
-rw-r--r--tests/ui/traits/const-traits/call-const-closure.stderr9
-rw-r--r--tests/ui/traits/const-traits/call-const-in-tilde-const.rs14
-rw-r--r--tests/ui/traits/const-traits/call-const-in-tilde-const.stderr18
-rw-r--r--tests/ui/traits/const-traits/call-const-trait-method-fail.stderr15
-rw-r--r--tests/ui/traits/const-traits/call-const-trait-method-pass.stderr14
-rw-r--r--tests/ui/traits/const-traits/call-generic-in-impl.stderr16
-rw-r--r--tests/ui/traits/const-traits/call-generic-method-chain.rs1
-rw-r--r--tests/ui/traits/const-traits/call-generic-method-chain.stderr31
-rw-r--r--tests/ui/traits/const-traits/call-generic-method-dup-bound.rs1
-rw-r--r--tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr31
-rw-r--r--tests/ui/traits/const-traits/call-generic-method-nonconst.stderr16
-rw-r--r--tests/ui/traits/const-traits/call-generic-method-pass.rs1
-rw-r--r--tests/ui/traits/const-traits/call-generic-method-pass.stderr19
-rw-r--r--tests/ui/traits/const-traits/const-bound-in-host.rs15
-rw-r--r--tests/ui/traits/const-traits/const-bound-in-host.stderr11
-rw-r--r--tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs2
-rw-r--r--tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr15
-rw-r--r--tests/ui/traits/const-traits/const-bounds-non-const-trait.rs1
-rw-r--r--tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr12
-rw-r--r--tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs2
-rw-r--r--tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr11
-rw-r--r--tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr18
-rw-r--r--tests/ui/traits/const-traits/const-closure-trait-method.stderr18
-rw-r--r--tests/ui/traits/const-traits/const-closures.stderr34
-rw-r--r--tests/ui/traits/const-traits/const-default-method-bodies.stderr17
-rw-r--r--tests/ui/traits/const-traits/const-drop-bound.stderr26
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail-2.stderr10
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.precise.stderr10
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.stock.stderr10
-rw-r--r--tests/ui/traits/const-traits/const-drop.precise.stderr24
-rw-r--r--tests/ui/traits/const-traits/const-drop.stock.stderr24
-rw-r--r--tests/ui/traits/const-traits/const-fns-are-early-bound.rs50
-rw-r--r--tests/ui/traits/const-traits/const-fns-are-early-bound.stderr20
-rw-r--r--tests/ui/traits/const-traits/const-impl-requires-const-trait.rs7
-rw-r--r--tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr20
-rw-r--r--tests/ui/traits/const-traits/const-impl-trait.rs3
-rw-r--r--tests/ui/traits/const-traits/const-impl-trait.stderr249
-rw-r--r--tests/ui/traits/const-traits/const-in-closure.rs25
-rw-r--r--tests/ui/traits/const-traits/const-in-closure.stderr11
-rw-r--r--tests/ui/traits/const-traits/cross-crate.gatednc.stderr17
-rw-r--r--tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr17
-rw-r--r--tests/ui/traits/const-traits/dont-observe-host-opaque.rs12
-rw-r--r--tests/ui/traits/const-traits/dont-observe-host-opaque.stderr11
-rw-r--r--tests/ui/traits/const-traits/dont-observe-host.rs23
-rw-r--r--tests/ui/traits/const-traits/dont-observe-host.stderr11
-rw-r--r--tests/ui/traits/const-traits/effects/minicore.rs32
-rw-r--r--tests/ui/traits/const-traits/effects/minicore.stderr8
-rw-r--r--tests/ui/traits/const-traits/effects/no-explicit-const-params-cross-crate.stderr16
-rw-r--r--tests/ui/traits/const-traits/effects/no-explicit-const-params.rs1
-rw-r--r--tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr30
-rw-r--r--tests/ui/traits/const-traits/effects/spec-effectvar-ice.rs1
-rw-r--r--tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr14
-rw-r--r--tests/ui/traits/const-traits/fn-ptr-lub.rs20
-rw-r--r--tests/ui/traits/const-traits/fn-ptr-lub.stderr11
-rw-r--r--tests/ui/traits/const-traits/hir-const-check.rs2
-rw-r--r--tests/ui/traits/const-traits/hir-const-check.stderr11
-rw-r--r--tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs1
-rw-r--r--tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr10
-rw-r--r--tests/ui/traits/const-traits/issue-92111.stderr10
-rw-r--r--tests/ui/traits/const-traits/item-bound-entailment-fails.rs31
-rw-r--r--tests/ui/traits/const-traits/item-bound-entailment-fails.stderr36
-rw-r--r--tests/ui/traits/const-traits/item-bound-entailment.rs31
-rw-r--r--tests/ui/traits/const-traits/item-bound-entailment.stderr11
-rw-r--r--tests/ui/traits/const-traits/non-const-op-in-closure-in-const.stderr16
-rw-r--r--tests/ui/traits/const-traits/predicate-entailment-fails.rs43
-rw-r--r--tests/ui/traits/const-traits/predicate-entailment-fails.stderr66
-rw-r--r--tests/ui/traits/const-traits/predicate-entailment-passes.rs39
-rw-r--r--tests/ui/traits/const-traits/predicate-entailment-passes.stderr11
-rw-r--r--tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr32
-rw-r--r--tests/ui/traits/const-traits/specialization/const-default-const-specialized.stderr25
-rw-r--r--tests/ui/traits/const-traits/specialization/default-keyword.rs3
-rw-r--r--tests/ui/traits/const-traits/specialization/default-keyword.stderr12
-rw-r--r--tests/ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.rs3
-rw-r--r--tests/ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.stderr43
-rw-r--r--tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.rs3
-rw-r--r--tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.stderr43
-rw-r--r--tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.stderr25
-rw-r--r--tests/ui/traits/const-traits/specializing-constness-2.stderr25
-rw-r--r--tests/ui/traits/const-traits/specializing-constness.rs2
-rw-r--r--tests/ui/traits/const-traits/specializing-constness.stderr14
-rw-r--r--tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr18
-rw-r--r--tests/ui/traits/const-traits/super-traits-fail-2.rs4
-rw-r--r--tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr17
-rw-r--r--tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr17
-rw-r--r--tests/ui/traits/const-traits/super-traits-fail-3.nn.stderr12
-rw-r--r--tests/ui/traits/const-traits/super-traits-fail-3.ny.stderr18
-rw-r--r--tests/ui/traits/const-traits/super-traits-fail-3.rs5
-rw-r--r--tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr29
-rw-r--r--tests/ui/traits/const-traits/super-traits-fail.rs1
-rw-r--r--tests/ui/traits/const-traits/super-traits-fail.stderr23
-rw-r--r--tests/ui/traits/const-traits/tilde-const-and-const-params.rs2
-rw-r--r--tests/ui/traits/const-traits/tilde-const-and-const-params.stderr25
-rw-r--r--tests/ui/traits/const-traits/tilde-const-in-struct-args.rs21
-rw-r--r--tests/ui/traits/const-traits/tilde-const-in-struct-args.stderr11
-rw-r--r--tests/ui/traits/const-traits/trait-where-clause-const.rs6
-rw-r--r--tests/ui/traits/const-traits/trait-where-clause-const.stderr51
-rw-r--r--tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr25
221 files changed, 2364 insertions, 2749 deletions
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index c43106c6e5f..97fa90d340e 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -57,7 +57,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
         owner: NodeId,
         f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>,
     ) {
-        let mut lctx = LoweringContext::new(self.tcx, self.resolver, self.ast_index);
+        let mut lctx = LoweringContext::new(self.tcx, self.resolver);
         lctx.with_hir_id_owner(owner, |lctx| f(lctx));
 
         for (def_id, info) in lctx.children {
@@ -193,8 +193,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
                 let (generics, (ty, body_id)) = self.lower_generics(
                     generics,
-                    Const::No,
-                    false,
                     id,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                     |this| {
@@ -225,16 +223,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     );
 
                     let itctx = ImplTraitContext::Universal;
-                    let (generics, decl) =
-                        this.lower_generics(generics, header.constness, false, id, itctx, |this| {
-                            this.lower_fn_decl(
-                                decl,
-                                id,
-                                *fn_sig_span,
-                                FnDeclKind::Fn,
-                                coroutine_kind,
-                            )
-                        });
+                    let (generics, decl) = this.lower_generics(generics, id, itctx, |this| {
+                        this.lower_fn_decl(decl, id, *fn_sig_span, FnDeclKind::Fn, coroutine_kind)
+                    });
                     let sig = hir::FnSig {
                         decl,
                         header: this.lower_fn_header(*header, hir::Safety::Safe),
@@ -269,8 +260,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 add_ty_alias_where_clause(&mut generics, *where_clauses, true);
                 let (generics, ty) = self.lower_generics(
                     &generics,
-                    Const::No,
-                    false,
                     id,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                     |this| match ty {
@@ -294,8 +283,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ItemKind::Enum(enum_definition, generics) => {
                 let (generics, variants) = self.lower_generics(
                     generics,
-                    Const::No,
-                    false,
                     id,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                     |this| {
@@ -309,8 +296,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ItemKind::Struct(struct_def, generics) => {
                 let (generics, struct_def) = self.lower_generics(
                     generics,
-                    Const::No,
-                    false,
                     id,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                     |this| this.lower_variant_data(hir_id, struct_def),
@@ -320,8 +305,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ItemKind::Union(vdata, generics) => {
                 let (generics, vdata) = self.lower_generics(
                     generics,
-                    Const::No,
-                    false,
                     id,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                     |this| this.lower_variant_data(hir_id, vdata),
@@ -353,7 +336,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 // parent lifetime.
                 let itctx = ImplTraitContext::Universal;
                 let (generics, (trait_ref, lowered_ty)) =
-                    self.lower_generics(ast_generics, Const::No, false, id, itctx, |this| {
+                    self.lower_generics(ast_generics, id, itctx, |this| {
                         let modifiers = TraitBoundModifiers {
                             constness: BoundConstness::Never,
                             asyncness: BoundAsyncness::Normal,
@@ -405,8 +388,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => {
                 let (generics, (safety, items, bounds)) = self.lower_generics(
                     generics,
-                    Const::No,
-                    false,
                     id,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                     |this| {
@@ -426,8 +407,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ItemKind::TraitAlias(generics, bounds) => {
                 let (generics, bounds) = self.lower_generics(
                     generics,
-                    Const::No,
-                    false,
                     id,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                     |this| {
@@ -604,50 +583,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
         ctxt: AssocCtxt,
         parent_hir: &'hir hir::OwnerInfo<'hir>,
     ) -> hir::OwnerNode<'hir> {
-        // Evaluate with the lifetimes in `params` in-scope.
-        // This is used to track which lifetimes have already been defined,
-        // and which need to be replicated when lowering an async fn.
-
         let parent_item = parent_hir.node().expect_item();
-        let constness = match parent_item.kind {
+        match parent_item.kind {
             hir::ItemKind::Impl(impl_) => {
                 self.is_in_trait_impl = impl_.of_trait.is_some();
-                // N.B. the impl should always lower to methods that have `const host: bool` params if the trait
-                // is const. It doesn't matter whether the `impl` itself is const. Disallowing const fn from
-                // calling non-const impls are done through associated types.
-                if let Some(def_id) = impl_.of_trait.and_then(|tr| tr.trait_def_id()) {
-                    if let Some(local_def) = def_id.as_local() {
-                        match &self.ast_index[local_def] {
-                            AstOwner::Item(ast::Item { attrs, .. }) => attrs
-                                .iter()
-                                .find(|attr| attr.has_name(sym::const_trait))
-                                .map_or(Const::No, |attr| Const::Yes(attr.span)),
-                            _ => Const::No,
-                        }
-                    } else if self.tcx.is_const_trait(def_id) {
-                        // FIXME(effects) span
-                        Const::Yes(self.tcx.def_ident_span(def_id).unwrap())
-                    } else {
-                        Const::No
-                    }
-                } else {
-                    Const::No
-                }
             }
-            hir::ItemKind::Trait(_, _, _, _, _) => parent_hir
-                .attrs
-                .get(parent_item.hir_id().local_id)
-                .iter()
-                .find(|attr| attr.has_name(sym::const_trait))
-                .map_or(Const::No, |attr| Const::Yes(attr.span)),
+            hir::ItemKind::Trait(_, _, _, _, _) => {}
             kind => {
                 span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr())
             }
-        };
+        }
 
+        // Evaluate with the lifetimes in `params` in-scope.
+        // This is used to track which lifetimes have already been defined,
+        // and which need to be replicated when lowering an async fn.
         match ctxt {
-            AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item, constness)),
-            AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item, constness)),
+            AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)),
+            AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)),
         }
     }
 
@@ -663,7 +615,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     let fdec = &sig.decl;
                     let itctx = ImplTraitContext::Universal;
                     let (generics, (decl, fn_args)) =
-                        self.lower_generics(generics, Const::No, false, i.id, itctx, |this| {
+                        self.lower_generics(generics, i.id, itctx, |this| {
                             (
                                 // Disallow `impl Trait` in foreign items.
                                 this.lower_fn_decl(
@@ -775,11 +727,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
     }
 
-    fn lower_trait_item(
-        &mut self,
-        i: &AssocItem,
-        trait_constness: Const,
-    ) -> &'hir hir::TraitItem<'hir> {
+    fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
         let hir_id = self.lower_node_id(i.id);
         self.lower_attrs(hir_id, &i.attrs);
         let trait_item_def_id = hir_id.expect_owner();
@@ -788,8 +736,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
             AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => {
                 let (generics, kind) = self.lower_generics(
                     generics,
-                    Const::No,
-                    false,
                     i.id,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                     |this| {
@@ -810,7 +756,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     i.id,
                     FnDeclKind::Trait,
                     sig.header.coroutine_kind,
-                    trait_constness,
                 );
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
             }
@@ -829,7 +774,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     i.id,
                     FnDeclKind::Trait,
                     sig.header.coroutine_kind,
-                    trait_constness,
                 );
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
             }
@@ -838,8 +782,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 add_ty_alias_where_clause(&mut generics, *where_clauses, false);
                 let (generics, kind) = self.lower_generics(
                     &generics,
-                    Const::No,
-                    false,
                     i.id,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                     |this| {
@@ -912,11 +854,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         self.expr(span, hir::ExprKind::Err(guar))
     }
 
-    fn lower_impl_item(
-        &mut self,
-        i: &AssocItem,
-        constness_of_trait: Const,
-    ) -> &'hir hir::ImplItem<'hir> {
+    fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
         // Since `default impl` is not yet implemented, this is always true in impls.
         let has_value = true;
         let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
@@ -926,8 +864,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let (generics, kind) = match &i.kind {
             AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
                 generics,
-                Const::No,
-                false,
                 i.id,
                 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                 |this| {
@@ -953,7 +889,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     i.id,
                     if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
                     sig.header.coroutine_kind,
-                    constness_of_trait,
                 );
 
                 (generics, hir::ImplItemKind::Fn(sig, body_id))
@@ -963,8 +898,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 add_ty_alias_where_clause(&mut generics, *where_clauses, false);
                 self.lower_generics(
                     &generics,
-                    Const::No,
-                    false,
                     i.id,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                     |this| match ty {
@@ -1370,18 +1303,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
         id: NodeId,
         kind: FnDeclKind,
         coroutine_kind: Option<CoroutineKind>,
-        parent_constness: Const,
     ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
         let header = self.lower_fn_header(sig.header, hir::Safety::Safe);
-        // Don't pass along the user-provided constness of trait associated functions; we don't want to
-        // synthesize a host effect param for them. We reject `const` on them during AST validation.
-        let constness =
-            if kind == FnDeclKind::Inherent { sig.header.constness } else { parent_constness };
         let itctx = ImplTraitContext::Universal;
-        let (generics, decl) =
-            self.lower_generics(generics, constness, kind == FnDeclKind::Impl, id, itctx, |this| {
-                this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
-            });
+        let (generics, decl) = self.lower_generics(generics, id, itctx, |this| {
+            this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
+        });
         (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
     }
 
@@ -1460,8 +1387,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_generics<T>(
         &mut self,
         generics: &Generics,
-        constness: Const,
-        force_append_constness: bool,
         parent_node_id: NodeId,
         itctx: ImplTraitContext,
         f: impl FnOnce(&mut Self) -> T,
@@ -1524,30 +1449,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
         }
 
-        // Desugar `~const` bound in generics into an additional `const host: bool` param
-        // if the effects feature is enabled. This needs to be done before we lower where
-        // clauses since where clauses need to bind to the DefId of the host param
-        let host_param_parts = if let Const::Yes(span) = constness
-            // if this comes from implementing a `const` trait, we must force constness to be appended
-            // to the impl item, no matter whether effects is enabled.
-            && (self.tcx.features().effects() || force_append_constness)
-        {
-            let span = self.lower_span(span);
-            let param_node_id = self.next_node_id();
-            let hir_id = self.next_id();
-            let def_id = self.create_def(
-                self.local_def_id(parent_node_id),
-                param_node_id,
-                sym::host,
-                DefKind::ConstParam,
-                span,
-            );
-            self.host_param_id = Some(def_id);
-            Some((span, hir_id, def_id))
-        } else {
-            None
-        };
-
         let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();
         predicates.extend(generics.params.iter().filter_map(|param| {
             self.lower_generic_bound_predicate(
@@ -1595,74 +1496,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
         predicates.extend(impl_trait_bounds.into_iter());
 
-        if let Some((span, hir_id, def_id)) = host_param_parts {
-            let const_node_id = self.next_node_id();
-            let anon_const_did =
-                self.create_def(def_id, const_node_id, kw::Empty, DefKind::AnonConst, span);
-
-            let const_id = self.next_id();
-            let const_expr_id = self.next_id();
-            let bool_id = self.next_id();
-
-            self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
-            self.children.push((anon_const_did, hir::MaybeOwner::NonOwner(const_id)));
-
-            let const_body = self.lower_body(|this| {
-                (&[], hir::Expr {
-                    hir_id: const_expr_id,
-                    kind: hir::ExprKind::Lit(
-                        this.arena.alloc(hir::Lit { node: LitKind::Bool(true), span }),
-                    ),
-                    span,
-                })
-            });
-
-            let default_ac = self.arena.alloc(hir::AnonConst {
-                def_id: anon_const_did,
-                hir_id: const_id,
-                body: const_body,
-                span,
-            });
-            let default_ct = self.arena.alloc(hir::ConstArg {
-                hir_id: self.next_id(),
-                kind: hir::ConstArgKind::Anon(default_ac),
-                is_desugared_from_effects: false,
-            });
-            let param = hir::GenericParam {
-                def_id,
-                hir_id,
-                name: hir::ParamName::Plain(Ident { name: sym::host, span }),
-                span,
-                kind: hir::GenericParamKind::Const {
-                    ty: self.arena.alloc(self.ty(
-                        span,
-                        hir::TyKind::Path(hir::QPath::Resolved(
-                            None,
-                            self.arena.alloc(hir::Path {
-                                res: Res::PrimTy(hir::PrimTy::Bool),
-                                span,
-                                segments: self.arena.alloc_from_iter([hir::PathSegment {
-                                    ident: Ident { name: sym::bool, span },
-                                    hir_id: bool_id,
-                                    res: Res::PrimTy(hir::PrimTy::Bool),
-                                    args: None,
-                                    infer_args: false,
-                                }]),
-                            }),
-                        )),
-                    )),
-                    default: Some(default_ct),
-                    is_host_effect: true,
-                    synthetic: true,
-                },
-                colon_span: None,
-                pure_wrt_drop: false,
-                source: hir::GenericParamSource::Generics,
-            };
-
-            params.push(param);
-        }
-
         let lowered_generics = self.arena.alloc(hir::Generics {
             params: self.arena.alloc_from_iter(params),
             predicates: self.arena.alloc_from_iter(predicates),
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 7cd0cd1ebcd..34b8137aea8 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -154,17 +154,10 @@ struct LoweringContext<'a, 'hir> {
     /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this
     /// field from the original parameter 'a to the new parameter 'a1.
     generics_def_id_map: Vec<LocalDefIdMap<LocalDefId>>,
-
-    host_param_id: Option<LocalDefId>,
-    ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
 }
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
-    fn new(
-        tcx: TyCtxt<'hir>,
-        resolver: &'a mut ResolverAstLowering,
-        ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
-    ) -> Self {
+    fn new(tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering) -> Self {
         Self {
             // Pseudo-globals.
             tcx,
@@ -204,8 +197,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             // interact with `gen`/`async gen` blocks
             allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),
             generics_def_id_map: Default::default(),
-            host_param_id: None,
-            ast_index,
         }
     }
 
@@ -2054,11 +2045,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         param: &GenericParam,
         source: hir::GenericParamSource,
     ) -> hir::GenericParam<'hir> {
-        let (name, kind) = self.lower_generic_param_kind(
-            param,
-            source,
-            attr::contains_name(&param.attrs, sym::rustc_runtime),
-        );
+        let (name, kind) = self.lower_generic_param_kind(param, source);
 
         let hir_id = self.lower_node_id(param.id);
         self.lower_attrs(hir_id, &param.attrs);
@@ -2078,7 +2065,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         &mut self,
         param: &GenericParam,
         source: hir::GenericParamSource,
-        is_host_effect: bool,
     ) -> (hir::ParamName, hir::GenericParamKind<'hir>) {
         match &param.kind {
             GenericParamKind::Lifetime => {
@@ -2144,7 +2130,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
                 (
                     hir::ParamName::Plain(self.lower_ident(param.ident)),
-                    hir::GenericParamKind::Const { ty, default, is_host_effect, synthetic: false },
+                    hir::GenericParamKind::Const { ty, default, synthetic: false },
                 )
             }
         }
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 753195bf691..5921fbc0fd7 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -838,10 +838,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         rustc_const_panic_str, Normal, template!(Word), WarnFollowing,
         EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
     ),
-    rustc_attr!(
-        rustc_runtime, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::No, INTERNAL_UNSTABLE
-    ),
 
     // ==========================================================================
     // Internal attributes, Layout related:
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 45be04c6db9..1c268c8bbe0 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -580,7 +580,6 @@ pub enum GenericParamKind<'hir> {
         ty: &'hir Ty<'hir>,
         /// Optional default value for the const generic param
         default: Option<&'hir ConstArg<'hir>>,
-        is_host_effect: bool,
         synthetic: bool,
     },
 }
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index ffe519b0e7d..322f8e2a517 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -935,7 +935,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(
     match param.kind {
         GenericParamKind::Lifetime { .. } => {}
         GenericParamKind::Type { ref default, .. } => visit_opt!(visitor, visit_ty, default),
-        GenericParamKind::Const { ref ty, ref default, is_host_effect: _, synthetic: _ } => {
+        GenericParamKind::Const { ref ty, ref default, synthetic: _ } => {
             try_visit!(visitor.visit_ty(ty));
             if let Some(ref default) = default {
                 try_visit!(visitor.visit_const_param_default(param.hir_id, default));
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index ae046c09ebe..7d81f977c22 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -415,14 +415,6 @@ language_item_table! {
 
     String,                  sym::String,              string,                     Target::Struct,         GenericRequirement::None;
     CStr,                    sym::CStr,                c_str,                      Target::Struct,         GenericRequirement::None;
-
-    EffectsRuntime,          sym::EffectsRuntime,      effects_runtime,            Target::Struct,         GenericRequirement::None;
-    EffectsNoRuntime,        sym::EffectsNoRuntime,    effects_no_runtime,         Target::Struct,         GenericRequirement::None;
-    EffectsMaybe,            sym::EffectsMaybe,        effects_maybe,              Target::Struct,         GenericRequirement::None;
-    EffectsIntersection,     sym::EffectsIntersection, effects_intersection,       Target::Trait,          GenericRequirement::None;
-    EffectsIntersectionOutput, sym::EffectsIntersectionOutput, effects_intersection_output, Target::AssocTy, GenericRequirement::None;
-    EffectsCompat,           sym::EffectsCompat,       effects_compat,             Target::Trait,          GenericRequirement::Exact(1);
-    EffectsTyCompat,         sym::EffectsTyCompat,     effects_ty_compat,          Target::Trait,          GenericRequirement::Exact(1);
 }
 
 pub enum GenericRequirement {
diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
index 77df0cb7ef9..1121ca53240 100644
--- a/compiler/rustc_hir_analysis/src/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/bounds.rs
@@ -3,13 +3,8 @@
 
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir::LangItem;
-use rustc_hir::def::DefKind;
-use rustc_middle::ty::fold::FnMutDelegate;
 use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
 use rustc_span::Span;
-use rustc_span::def_id::DefId;
-
-use crate::hir_ty_lowering::PredicateFilter;
 
 /// Collects together a list of type bounds. These lists of bounds occur in many places
 /// in Rust's syntax:
@@ -47,12 +42,9 @@ impl<'tcx> Bounds<'tcx> {
     pub(crate) fn push_trait_bound(
         &mut self,
         tcx: TyCtxt<'tcx>,
-        defining_def_id: DefId,
         bound_trait_ref: ty::PolyTraitRef<'tcx>,
         span: Span,
         polarity: ty::PredicatePolarity,
-        constness: Option<ty::BoundConstness>,
-        predicate_filter: PredicateFilter,
     ) {
         let clause = (
             bound_trait_ref
@@ -68,137 +60,6 @@ impl<'tcx> Bounds<'tcx> {
         } else {
             self.clauses.push(clause);
         }
-
-        // FIXME(effects): Lift this out of `push_trait_bound`, and move it somewhere else.
-        // Perhaps moving this into `lower_poly_trait_ref`, just like we lower associated
-        // type bounds.
-        if !tcx.features().effects() {
-            return;
-        }
-        match predicate_filter {
-            PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => {
-                return;
-            }
-            PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
-                // Ok.
-            }
-        }
-
-        // For `T: ~const Tr` or `T: const Tr`, we need to add an additional bound on the
-        // associated type of `<T as Tr>` and make sure that the effect is compatible.
-        let compat_val = match (tcx.def_kind(defining_def_id), constness) {
-            // FIXME(effects): revisit the correctness of this
-            (_, Some(ty::BoundConstness::Const)) => tcx.consts.false_,
-            // body owners that can have trait bounds
-            (
-                DefKind::Const | DefKind::Fn | DefKind::AssocFn,
-                Some(ty::BoundConstness::ConstIfConst),
-            ) => tcx.expected_host_effect_param_for_body(defining_def_id),
-
-            (_, None) => {
-                if !tcx.is_const_trait(bound_trait_ref.def_id()) {
-                    return;
-                }
-                tcx.consts.true_
-            }
-            (DefKind::Trait, Some(ty::BoundConstness::ConstIfConst)) => {
-                // we are in a trait, where `bound_trait_ref` could be:
-                // (1) a super trait `trait Foo: ~const Bar`.
-                //     - This generates `<Self as Foo>::Effects: TyCompat<<Self as Bar>::Effects>`
-                //
-                // (2) a where clause `where for<..> Something: ~const Bar`.
-                //     - This generates `for<..> <Self as Foo>::Effects: TyCompat<<Something as Bar>::Effects>`
-                let Some(own_fx) = tcx.associated_type_for_effects(defining_def_id) else {
-                    tcx.dcx().span_delayed_bug(span, "should not have allowed `~const` on a trait that doesn't have `#[const_trait]`");
-                    return;
-                };
-                let own_fx_ty = Ty::new_projection(
-                    tcx,
-                    own_fx,
-                    ty::GenericArgs::identity_for_item(tcx, own_fx),
-                );
-                let Some(their_fx) = tcx.associated_type_for_effects(bound_trait_ref.def_id())
-                else {
-                    tcx.dcx().span_delayed_bug(span, "`~const` on trait without Effects assoc");
-                    return;
-                };
-                let their_fx_ty =
-                    Ty::new_projection(tcx, their_fx, bound_trait_ref.skip_binder().args);
-                let compat = tcx.require_lang_item(LangItem::EffectsTyCompat, Some(span));
-                let clause = bound_trait_ref
-                    .map_bound(|_| {
-                        let trait_ref = ty::TraitRef::new(tcx, compat, [own_fx_ty, their_fx_ty]);
-                        ty::ClauseKind::Trait(ty::TraitPredicate {
-                            trait_ref,
-                            polarity: ty::PredicatePolarity::Positive,
-                        })
-                    })
-                    .upcast(tcx);
-
-                self.clauses.push((clause, span));
-                return;
-            }
-
-            (DefKind::Impl { of_trait: true }, Some(ty::BoundConstness::ConstIfConst)) => {
-                // this is a where clause on an impl header.
-                // push `<T as Tr>::Effects` into the set for the `Min` bound.
-                let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
-                    tcx.dcx().span_delayed_bug(span, "`~const` on trait without Effects assoc");
-                    return;
-                };
-
-                let ty = bound_trait_ref
-                    .map_bound(|trait_ref| Ty::new_projection(tcx, assoc, trait_ref.args));
-
-                // When the user has written `for<'a, T> X<'a, T>: ~const Foo`, replace the
-                // binders to dummy ones i.e. `X<'static, ()>` so they can be referenced in
-                // the `Min` associated type properly (which doesn't allow using `for<>`)
-                // This should work for any bound variables as long as they don't have any
-                // bounds e.g. `for<T: Trait>`.
-                // FIXME(effects) reconsider this approach to allow compatibility with `for<T: Tr>`
-                let ty = tcx.replace_bound_vars_uncached(ty, FnMutDelegate {
-                    regions: &mut |_| tcx.lifetimes.re_static,
-                    types: &mut |_| tcx.types.unit,
-                    consts: &mut |_| unimplemented!("`~const` does not support const binders"),
-                });
-
-                self.effects_min_tys.insert(ty, span);
-                return;
-            }
-            // for
-            // ```
-            // trait Foo { type Bar: ~const Trait }
-            // ```
-            // ensure that `<Self::Bar as Trait>::Effects: TyCompat<Self::Effects>`.
-            //
-            // FIXME(effects) this is equality for now, which wouldn't be helpful for a non-const implementor
-            // that uses a `Bar` that implements `Trait` with `Maybe` effects.
-            (DefKind::AssocTy, Some(ty::BoundConstness::ConstIfConst)) => {
-                // FIXME(effects): implement this
-                return;
-            }
-            // probably illegal in this position.
-            (_, Some(ty::BoundConstness::ConstIfConst)) => {
-                tcx.dcx().span_delayed_bug(span, "invalid `~const` encountered");
-                return;
-            }
-        };
-        // create a new projection type `<T as Tr>::Effects`
-        let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
-            tcx.dcx().span_delayed_bug(
-                span,
-                "`~const` trait bound has no effect assoc yet no errors encountered?",
-            );
-            return;
-        };
-        let self_ty = Ty::new_projection(tcx, assoc, bound_trait_ref.skip_binder().args);
-        // make `<T as Tr>::Effects: Compat<runtime>`
-        let new_trait_ref =
-            ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::EffectsCompat, Some(span)), [
-                ty::GenericArg::from(self_ty),
-                compat_val.into(),
-            ]);
-        self.clauses.push((bound_trait_ref.rebind(new_trait_ref).upcast(tcx), span));
     }
 
     pub(crate) fn push_projection_bound(
@@ -220,6 +81,21 @@ impl<'tcx> Bounds<'tcx> {
         self.clauses.insert(0, (trait_ref.upcast(tcx), span));
     }
 
+    /// Push a `const` or `~const` bound as a `HostEffect` predicate.
+    pub(crate) fn push_const_bound(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        bound_trait_ref: ty::PolyTraitRef<'tcx>,
+        host: ty::HostPolarity,
+        span: Span,
+    ) {
+        if tcx.is_const_trait(bound_trait_ref.def_id()) {
+            self.clauses.push((bound_trait_ref.to_host_effect_clause(tcx, host), span));
+        } else {
+            tcx.dcx().span_delayed_bug(span, "tried to lower {host:?} bound for non-const trait");
+        }
+    }
+
     pub(crate) fn clauses(
         &self,
         // FIXME(effects): remove tcx
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 7a56b3784f8..02cf1a502f1 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -181,6 +181,7 @@ fn compare_method_predicate_entailment<'tcx>(
         });
 
     // Create mapping from trait method to impl method.
+    let impl_def_id = impl_m.container_id(tcx);
     let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_m.def_id).rebase_onto(
         tcx,
         impl_m.container_id(tcx),
@@ -204,6 +205,24 @@ fn compare_method_predicate_entailment<'tcx>(
         trait_m_predicates.instantiate_own(tcx, trait_to_impl_args).map(|(predicate, _)| predicate),
     );
 
+    // FIXME(effects): This should be replaced with a more dedicated method.
+    let is_conditionally_const = tcx.is_conditionally_const(impl_def_id);
+    if is_conditionally_const {
+        // Augment the hybrid param-env with the const conditions
+        // of the impl header and the trait method.
+        hybrid_preds.extend(
+            tcx.const_conditions(impl_def_id)
+                .instantiate_identity(tcx)
+                .into_iter()
+                .chain(
+                    tcx.const_conditions(trait_m.def_id).instantiate_own(tcx, trait_to_impl_args),
+                )
+                .map(|(trait_ref, _)| {
+                    trait_ref.to_host_effect_clause(tcx, ty::HostPolarity::Maybe)
+                }),
+        );
+    }
+
     let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);
     let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds), Reveal::UserFacing);
     let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
@@ -230,6 +249,34 @@ fn compare_method_predicate_entailment<'tcx>(
         ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
     }
 
+    // If we're within a const implementation, we need to make sure that the method
+    // does not assume stronger `~const` bounds than the trait definition.
+    //
+    // This registers the `~const` bounds of the impl method, which we will prove
+    // using the hybrid param-env that we earlier augmented with the const conditions
+    // from the impl header and trait method declaration.
+    if is_conditionally_const {
+        for (const_condition, span) in
+            tcx.const_conditions(impl_m.def_id).instantiate_own_identity()
+        {
+            let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id);
+            let const_condition = ocx.normalize(&normalize_cause, param_env, const_condition);
+
+            let cause =
+                ObligationCause::new(span, impl_m_def_id, ObligationCauseCode::CompareImplItem {
+                    impl_item_def_id: impl_m_def_id,
+                    trait_item_def_id: trait_m.def_id,
+                    kind: impl_m.kind,
+                });
+            ocx.register_obligation(traits::Obligation::new(
+                tcx,
+                cause,
+                param_env,
+                const_condition.to_host_effect_clause(tcx, ty::HostPolarity::Maybe),
+            ));
+        }
+    }
+
     // We now need to check that the signature of the impl method is
     // compatible with that of the trait method. We do this by
     // checking that `impl_fty <: trait_fty`.
@@ -1846,9 +1893,10 @@ fn compare_type_predicate_entailment<'tcx>(
     trait_ty: ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
+    let impl_def_id = impl_ty.container_id(tcx);
     let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id).rebase_onto(
         tcx,
-        impl_ty.container_id(tcx),
+        impl_def_id,
         impl_trait_ref.args,
     );
 
@@ -1856,6 +1904,7 @@ fn compare_type_predicate_entailment<'tcx>(
     let trait_ty_predicates = tcx.predicates_of(trait_ty.def_id);
 
     let impl_ty_own_bounds = impl_ty_predicates.instantiate_own_identity();
+    // If there are no bounds, then there are no const conditions, so no need to check that here.
     if impl_ty_own_bounds.len() == 0 {
         // Nothing to check.
         return Ok(());
@@ -1881,6 +1930,23 @@ fn compare_type_predicate_entailment<'tcx>(
     let impl_ty_span = tcx.def_span(impl_ty_def_id);
     let normalize_cause = ObligationCause::misc(impl_ty_span, impl_ty_def_id);
 
+    let is_conditionally_const = tcx.is_conditionally_const(impl_ty.def_id);
+    if is_conditionally_const {
+        // Augment the hybrid param-env with the const conditions
+        // of the impl header and the trait assoc type.
+        hybrid_preds.extend(
+            tcx.const_conditions(impl_ty_predicates.parent.unwrap())
+                .instantiate_identity(tcx)
+                .into_iter()
+                .chain(
+                    tcx.const_conditions(trait_ty.def_id).instantiate_own(tcx, trait_to_impl_args),
+                )
+                .map(|(trait_ref, _)| {
+                    trait_ref.to_host_effect_clause(tcx, ty::HostPolarity::Maybe)
+                }),
+        );
+    }
+
     let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds), Reveal::UserFacing);
     let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
     debug!(caller_bounds=?param_env.caller_bounds());
@@ -1901,6 +1967,29 @@ fn compare_type_predicate_entailment<'tcx>(
         ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
     }
 
+    if is_conditionally_const {
+        // Validate the const conditions of the impl associated type.
+        let impl_ty_own_const_conditions =
+            tcx.const_conditions(impl_ty.def_id).instantiate_own_identity();
+        for (const_condition, span) in impl_ty_own_const_conditions {
+            let normalize_cause = traits::ObligationCause::misc(span, impl_ty_def_id);
+            let const_condition = ocx.normalize(&normalize_cause, param_env, const_condition);
+
+            let cause =
+                ObligationCause::new(span, impl_ty_def_id, ObligationCauseCode::CompareImplItem {
+                    impl_item_def_id: impl_ty_def_id,
+                    trait_item_def_id: trait_ty.def_id,
+                    kind: impl_ty.kind,
+                });
+            ocx.register_obligation(traits::Obligation::new(
+                tcx,
+                cause,
+                param_env,
+                const_condition.to_host_effect_clause(tcx, ty::HostPolarity::Maybe),
+            ));
+        }
+    }
+
     // Check that all obligations are satisfied by the implementation's
     // version.
     let errors = ocx.select_all_or_error();
@@ -1983,7 +2072,7 @@ pub(super) fn check_type_bounds<'tcx>(
         ObligationCause::new(impl_ty_span, impl_ty_def_id, code)
     };
 
-    let obligations: Vec<_> = tcx
+    let mut obligations: Vec<_> = tcx
         .explicit_item_bounds(trait_ty.def_id)
         .iter_instantiated_copied(tcx, rebased_args)
         .map(|(concrete_ty_bound, span)| {
@@ -1991,6 +2080,22 @@ pub(super) fn check_type_bounds<'tcx>(
             traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
         })
         .collect();
+
+    // Only in a const implementation do we need to check that the `~const` item bounds hold.
+    if tcx.is_conditionally_const(impl_ty_def_id) {
+        obligations.extend(
+            tcx.implied_const_bounds(trait_ty.def_id)
+                .iter_instantiated_copied(tcx, rebased_args)
+                .map(|(c, span)| {
+                    traits::Obligation::new(
+                        tcx,
+                        mk_cause(span),
+                        param_env,
+                        c.to_host_effect_clause(tcx, ty::HostPolarity::Maybe),
+                    )
+                }),
+        );
+    }
     debug!(item_bounds=?obligations);
 
     // Normalize predicates with the assumption that the GAT may always normalize
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 06317a3b304..c75bdcec388 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -58,15 +58,9 @@ fn equate_intrinsic_type<'tcx>(
 
     // the host effect param should be invisible as it shouldn't matter
     // whether effects is enabled for the intrinsic provider crate.
-    let consts_count = if generics.host_effect_index.is_some() {
-        own_counts.consts - 1
-    } else {
-        own_counts.consts
-    };
-
     if gen_count_ok(own_counts.lifetimes, n_lts, "lifetime")
         && gen_count_ok(own_counts.types, n_tps, "type")
-        && gen_count_ok(consts_count, n_cts, "const")
+        && gen_count_ok(own_counts.consts, n_cts, "const")
     {
         let _ = check_function_signature(
             tcx,
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index d70e8673c52..499e42d31c9 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -32,7 +32,8 @@ use rustc_trait_selection::traits::misc::{
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::{
-    self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
+    self, FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt,
+    WellFormedLoc,
 };
 use rustc_type_ir::TypeFlags;
 use rustc_type_ir::solve::NoSolution;
@@ -86,7 +87,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
             self.body_def_id,
             ObligationCauseCode::WellFormed(loc),
         );
-        self.ocx.register_obligation(traits::Obligation::new(
+        self.ocx.register_obligation(Obligation::new(
             self.tcx(),
             cause,
             self.param_env,
@@ -913,12 +914,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
         hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => Ok(()),
 
         // Const parameters are well formed if their type is structural match.
-        hir::GenericParamKind::Const {
-            ty: hir_ty,
-            default: _,
-            is_host_effect: _,
-            synthetic: _,
-        } => {
+        hir::GenericParamKind::Const { ty: hir_ty, default: _, synthetic: _ } => {
             let ty = tcx.type_of(param.def_id).instantiate_identity();
 
             if tcx.features().unsized_const_params() {
@@ -1178,7 +1174,7 @@ fn check_type_defn<'tcx>(
                     wfcx.body_def_id,
                     ObligationCauseCode::Misc,
                 );
-                wfcx.register_obligation(traits::Obligation::new(
+                wfcx.register_obligation(Obligation::new(
                     tcx,
                     cause,
                     wfcx.param_env,
@@ -1374,6 +1370,30 @@ fn check_impl<'tcx>(
                         obligation.cause.span = hir_self_ty.span;
                     }
                 }
+
+                // Ensure that the `~const` where clauses of the trait hold for the impl.
+                if tcx.is_conditionally_const(item.owner_id.def_id) {
+                    for (bound, _) in
+                        tcx.const_conditions(trait_ref.def_id).instantiate(tcx, trait_ref.args)
+                    {
+                        let bound = wfcx.normalize(
+                            item.span,
+                            Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
+                            bound,
+                        );
+                        wfcx.register_obligation(Obligation::new(
+                            tcx,
+                            ObligationCause::new(
+                                hir_self_ty.span,
+                                wfcx.body_def_id,
+                                ObligationCauseCode::WellFormed(None),
+                            ),
+                            wfcx.param_env,
+                            bound.to_host_effect_clause(tcx, ty::HostPolarity::Maybe),
+                        ))
+                    }
+                }
+
                 debug!(?obligations);
                 wfcx.register_obligations(obligations);
             }
@@ -1566,7 +1586,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
                 wfcx.body_def_id,
                 ObligationCauseCode::WhereClause(def_id.to_def_id(), DUMMY_SP),
             );
-            traits::Obligation::new(tcx, cause, wfcx.param_env, pred)
+            Obligation::new(tcx, cause, wfcx.param_env, pred)
         });
 
     let predicates = predicates.instantiate_identity(tcx);
@@ -1857,7 +1877,7 @@ fn receiver_is_implemented<'tcx>(
     let tcx = wfcx.tcx();
     let trait_ref = ty::TraitRef::new(tcx, receiver_trait_def_id, [receiver_ty]);
 
-    let obligation = traits::Obligation::new(tcx, cause, wfcx.param_env, trait_ref);
+    let obligation = Obligation::new(tcx, cause, wfcx.param_env, trait_ref);
 
     if wfcx.infcx.predicate_must_hold_modulo_regions(&obligation) {
         true
@@ -2193,7 +2213,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
                         .unwrap_or(obligation_span);
                 }
 
-                let obligation = traits::Obligation::new(
+                let obligation = Obligation::new(
                     tcx,
                     traits::ObligationCause::new(
                         span,
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index acc21d0994b..f46b7a8bc9c 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -77,6 +77,8 @@ pub fn provide(providers: &mut Providers) {
         explicit_supertraits_containing_assoc_item:
             predicates_of::explicit_supertraits_containing_assoc_item,
         trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
+        const_conditions: predicates_of::const_conditions,
+        implied_const_bounds: predicates_of::implied_const_bounds,
         type_param_predicates: predicates_of::type_param_predicates,
         trait_def,
         adt_def,
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 348b2260d26..3eec0e12665 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -53,7 +53,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
             param_def_id_to_index,
             has_self: opaque_ty_generics.has_self,
             has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
-            host_effect_index: parent_generics.host_effect_index,
         };
     }
 
@@ -161,7 +160,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                         param_def_id_to_index,
                         has_self: generics.has_self,
                         has_late_bound_regions: generics.has_late_bound_regions,
-                        host_effect_index: None,
                     };
                 } else {
                     // HACK(eddyb) this provides the correct generics when
@@ -292,12 +290,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
     let has_self = opt_self.is_some();
     let mut parent_has_self = false;
     let mut own_start = has_self as u32;
-    let mut host_effect_index = None;
     let parent_count = parent_def_id.map_or(0, |def_id| {
         let generics = tcx.generics_of(def_id);
         assert!(!has_self);
         parent_has_self = generics.has_self;
-        host_effect_index = generics.host_effect_index;
         own_start = generics.count() as u32;
         generics.parent_count + generics.own_params.len()
     });
@@ -361,12 +357,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                 kind,
             })
         }
-        GenericParamKind::Const { ty: _, default, is_host_effect, synthetic } => {
-            if !matches!(allow_defaults, Defaults::Allowed)
-                && default.is_some()
-                // `host` effect params are allowed to have defaults.
-                && !is_host_effect
-            {
+        GenericParamKind::Const { ty: _, default, synthetic } => {
+            if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() {
                 tcx.dcx().span_err(
                     param.span,
                     "defaults for const parameters are only allowed in \
@@ -376,27 +368,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
 
             let index = next_index();
 
-            if is_host_effect {
-                if let Some(idx) = host_effect_index {
-                    tcx.dcx().span_delayed_bug(
-                        param.span,
-                        format!("parent also has host effect param? index: {idx}, def: {def_id:?}"),
-                    );
-                }
-
-                host_effect_index = Some(index as usize);
-            }
-
             Some(ty::GenericParamDef {
                 index,
                 name: param.name.ident().name,
                 def_id: param.def_id.to_def_id(),
                 pure_wrt_drop: param.pure_wrt_drop,
-                kind: ty::GenericParamDefKind::Const {
-                    has_default: default.is_some(),
-                    is_host_effect,
-                    synthetic,
-                },
+                kind: ty::GenericParamDefKind::Const { has_default: default.is_some(), synthetic },
             })
         }
     }));
@@ -459,7 +436,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
         param_def_id_to_index,
         has_self: has_self || parent_has_self,
         has_late_bound_regions: has_late_bound_regions(tcx, node),
-        host_effect_index,
     }
 }
 
@@ -540,8 +516,7 @@ impl<'v> Visitor<'v> for AnonConstInParamTyDetector {
     type Result = ControlFlow<()>;
 
     fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) -> Self::Result {
-        if let GenericParamKind::Const { ty, default: _, is_host_effect: _, synthetic: _ } = p.kind
-        {
+        if let GenericParamKind::Const { ty, default: _, synthetic: _ } = p.kind {
             let prev = self.in_param_ty;
             self.in_param_ty = true;
             let res = self.visit_ty(ty);
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 69ebd3a928a..075faea3d2a 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -40,7 +40,16 @@ fn associated_type_bounds<'tcx>(
     let mut bounds = Bounds::default();
     icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
     // Associated types are implicitly sized unless a `?Sized` bound is found
-    icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
+    match filter {
+        PredicateFilter::All
+        | PredicateFilter::SelfOnly
+        | PredicateFilter::SelfThatDefines(_)
+        | PredicateFilter::SelfAndAssociatedTypeBounds => {
+            icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
+        }
+        // `ConstIfConst` is only interested in `~const` bounds.
+        PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
+    }
 
     let trait_def_id = tcx.local_parent(assoc_item_def_id);
     let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id);
@@ -109,10 +118,19 @@ fn remap_gat_vars_and_recurse_into_nested_projections<'tcx>(
             } else {
                 // Only collect *self* type bounds if the filter is for self.
                 match filter {
-                    PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => {
+                    PredicateFilter::All => {}
+                    PredicateFilter::SelfOnly => {
                         return None;
                     }
-                    PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {}
+                    PredicateFilter::SelfThatDefines(_)
+                    | PredicateFilter::SelfConstIfConst
+                    | PredicateFilter::SelfAndAssociatedTypeBounds
+                    | PredicateFilter::ConstIfConst => {
+                        unreachable!(
+                            "invalid predicate filter for \
+                            `remap_gat_vars_and_recurse_into_nested_projections`"
+                        )
+                    }
                 }
 
                 clause_ty = alias_ty.self_ty();
@@ -308,7 +326,17 @@ fn opaque_type_bounds<'tcx>(
         let mut bounds = Bounds::default();
         icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
         // Opaque types are implicitly sized unless a `?Sized` bound is found
-        icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
+        match filter {
+            PredicateFilter::All
+            | PredicateFilter::SelfOnly
+            | PredicateFilter::SelfThatDefines(_)
+            | PredicateFilter::SelfAndAssociatedTypeBounds => {
+                // Associated types are implicitly sized unless a `?Sized` bound is found
+                icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
+            }
+            //`ConstIfConst` is only interested in `~const` bounds.
+            PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
+        }
         debug!(?bounds);
 
         tcx.arena.alloc_from_iter(bounds.clauses(tcx))
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 097a1fbc393..61dc4b1677c 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -12,6 +12,7 @@ use rustc_span::symbol::Ident;
 use rustc_span::{DUMMY_SP, Span};
 use tracing::{debug, instrument, trace};
 
+use super::item_bounds::explicit_item_bounds_with_filter;
 use crate::bounds::Bounds;
 use crate::collect::ItemCtxt;
 use crate::constrained_generic_params as cgp;
@@ -78,7 +79,6 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
 #[instrument(level = "trace", skip(tcx), ret)]
 fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
     use rustc_hir::*;
-    use rustc_middle::ty::Ty;
 
     match tcx.opt_rpitit_info(def_id.to_def_id()) {
         Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) => {
@@ -345,26 +345,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
         debug!(?predicates);
     }
 
-    // add `Self::Effects: Compat<HOST>` to ensure non-const impls don't get called
-    // in const contexts.
-    if let Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), .. }) = node
-        && let Some(host_effect_index) = generics.host_effect_index
-    {
-        let parent = generics.parent.unwrap();
-        let Some(assoc_def_id) = tcx.associated_type_for_effects(parent) else {
-            bug!("associated_type_for_effects returned None when there is host effect in generics");
-        };
-        let effects =
-            Ty::new_projection(tcx, assoc_def_id, ty::GenericArgs::identity_for_item(tcx, parent));
-        let param = generics.param_at(host_effect_index, tcx);
-        let span = tcx.def_span(param.def_id);
-        let host = ty::Const::new_param(tcx, ty::ParamConst::for_def(param));
-        let compat = tcx.require_lang_item(LangItem::EffectsCompat, Some(span));
-        let trait_ref =
-            ty::TraitRef::new(tcx, compat, [ty::GenericArg::from(effects), host.into()]);
-        predicates.push((ty::Binder::dummy(trait_ref).upcast(tcx), span));
-    }
-
     ty::GenericPredicates {
         parent: generics.parent,
         predicates: tcx.arena.alloc_from_iter(predicates),
@@ -706,29 +686,76 @@ pub(super) fn assert_only_contains_predicates_from<'tcx>(
                         assert_eq!(
                             trait_predicate.self_ty(),
                             ty,
-                            "expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
+                            "expected `Self` predicate when computing \
+                            `{filter:?}` implied bounds: {clause:?}"
                         );
                     }
                     ty::ClauseKind::Projection(projection_predicate) => {
                         assert_eq!(
                             projection_predicate.self_ty(),
                             ty,
-                            "expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
+                            "expected `Self` predicate when computing \
+                            `{filter:?}` implied bounds: {clause:?}"
                         );
                     }
                     ty::ClauseKind::TypeOutlives(outlives_predicate) => {
                         assert_eq!(
                             outlives_predicate.0, ty,
-                            "expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
+                            "expected `Self` predicate when computing \
+                            `{filter:?}` implied bounds: {clause:?}"
                         );
                     }
 
                     ty::ClauseKind::RegionOutlives(_)
                     | ty::ClauseKind::ConstArgHasType(_, _)
                     | ty::ClauseKind::WellFormed(_)
-                    | ty::ClauseKind::ConstEvaluatable(_) => {
+                    | ty::ClauseKind::ConstEvaluatable(_)
+                    | ty::ClauseKind::HostEffect(..) => {
+                        bug!(
+                            "unexpected non-`Self` predicate when computing \
+                            `{filter:?}` implied bounds: {clause:?}"
+                        );
+                    }
+                }
+            }
+        }
+        PredicateFilter::ConstIfConst => {
+            for (clause, _) in bounds {
+                match clause.kind().skip_binder() {
+                    ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
+                        trait_ref: _,
+                        host: ty::HostPolarity::Maybe,
+                    }) => {}
+                    _ => {
+                        bug!(
+                            "unexpected non-`HostEffect` predicate when computing \
+                            `{filter:?}` implied bounds: {clause:?}"
+                        );
+                    }
+                }
+            }
+        }
+        PredicateFilter::SelfConstIfConst => {
+            for (clause, _) in bounds {
+                match clause.kind().skip_binder() {
+                    ty::ClauseKind::HostEffect(pred) => {
+                        assert_eq!(
+                            pred.host,
+                            ty::HostPolarity::Maybe,
+                            "expected `~const` predicate when computing `{filter:?}` \
+                            implied bounds: {clause:?}",
+                        );
+                        assert_eq!(
+                            pred.trait_ref.self_ty(),
+                            ty,
+                            "expected `Self` predicate when computing `{filter:?}` \
+                            implied bounds: {clause:?}"
+                        );
+                    }
+                    _ => {
                         bug!(
-                            "unexpected non-`Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
+                            "unexpected non-`HostEffect` predicate when computing \
+                            `{filter:?}` implied bounds: {clause:?}"
                         );
                     }
                 }
@@ -850,3 +877,144 @@ impl<'tcx> ItemCtxt<'tcx> {
         bounds.clauses(self.tcx).collect()
     }
 }
+
+/// Compute the conditions that need to hold for a conditionally-const item to be const.
+/// That is, compute the set of `~const` where clauses for a given item.
+///
+/// This query also computes the `~const` where clauses for associated types, which are
+/// not "const", but which have item bounds which may be `~const`. These must hold for
+/// the `~const` item bound to hold.
+pub(super) fn const_conditions<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: LocalDefId,
+) -> ty::ConstConditions<'tcx> {
+    if !tcx.is_conditionally_const(def_id) {
+        bug!("const_conditions invoked for item that is not conditionally const: {def_id:?}");
+    }
+
+    let (generics, trait_def_id_and_supertraits, has_parent) = match tcx.hir_node_by_def_id(def_id)
+    {
+        Node::Item(item) => match item.kind {
+            hir::ItemKind::Impl(impl_) => (impl_.generics, None, false),
+            hir::ItemKind::Fn(_, generics, _) => (generics, None, false),
+            hir::ItemKind::Trait(_, _, generics, supertraits, _) => {
+                (generics, Some((item.owner_id.def_id, supertraits)), false)
+            }
+            _ => bug!("const_conditions called on wrong item: {def_id:?}"),
+        },
+        // While associated types are not really const, we do allow them to have `~const`
+        // bounds and where clauses. `const_conditions` is responsible for gathering
+        // these up so we can check them in `compare_type_predicate_entailment`, and
+        // in `HostEffect` goal computation.
+        Node::TraitItem(item) => match item.kind {
+            hir::TraitItemKind::Fn(_, _) | hir::TraitItemKind::Type(_, _) => {
+                (item.generics, None, true)
+            }
+            _ => bug!("const_conditions called on wrong item: {def_id:?}"),
+        },
+        Node::ImplItem(item) => match item.kind {
+            hir::ImplItemKind::Fn(_, _) | hir::ImplItemKind::Type(_) => {
+                (item.generics, None, tcx.is_conditionally_const(tcx.local_parent(def_id)))
+            }
+            _ => bug!("const_conditions called on wrong item: {def_id:?}"),
+        },
+        Node::ForeignItem(item) => match item.kind {
+            hir::ForeignItemKind::Fn(_, _, generics) => (generics, None, false),
+            _ => bug!("const_conditions called on wrong item: {def_id:?}"),
+        },
+        // N.B. Tuple ctors are unconditionally constant.
+        Node::Ctor(hir::VariantData::Tuple { .. }) => return Default::default(),
+        _ => bug!("const_conditions called on wrong item: {def_id:?}"),
+    };
+
+    let icx = ItemCtxt::new(tcx, def_id);
+    let mut bounds = Bounds::default();
+
+    for pred in generics.predicates {
+        match pred {
+            hir::WherePredicate::BoundPredicate(bound_pred) => {
+                let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
+                let bound_vars = tcx.late_bound_vars(bound_pred.hir_id);
+                icx.lowerer().lower_bounds(
+                    ty,
+                    bound_pred.bounds.iter(),
+                    &mut bounds,
+                    bound_vars,
+                    PredicateFilter::ConstIfConst,
+                );
+            }
+            _ => {}
+        }
+    }
+
+    if let Some((def_id, supertraits)) = trait_def_id_and_supertraits {
+        bounds.push_const_bound(
+            tcx,
+            ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id())),
+            ty::HostPolarity::Maybe,
+            DUMMY_SP,
+        );
+
+        icx.lowerer().lower_bounds(
+            tcx.types.self_param,
+            supertraits.into_iter(),
+            &mut bounds,
+            ty::List::empty(),
+            PredicateFilter::ConstIfConst,
+        );
+    }
+
+    ty::ConstConditions {
+        parent: has_parent.then(|| tcx.local_parent(def_id).to_def_id()),
+        predicates: tcx.arena.alloc_from_iter(bounds.clauses(tcx).map(|(clause, span)| {
+            (
+                clause.kind().map_bound(|clause| match clause {
+                    ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
+                        trait_ref,
+                        host: ty::HostPolarity::Maybe,
+                    }) => trait_ref,
+                    _ => bug!("converted {clause:?}"),
+                }),
+                span,
+            )
+        })),
+    }
+}
+
+pub(super) fn implied_const_bounds<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: LocalDefId,
+) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> {
+    if !tcx.is_conditionally_const(def_id) {
+        bug!("const_conditions invoked for item that is not conditionally const: {def_id:?}");
+    }
+
+    let bounds = match tcx.hir_node_by_def_id(def_id) {
+        Node::Item(hir::Item { kind: hir::ItemKind::Trait(..), .. }) => {
+            implied_predicates_with_filter(
+                tcx,
+                def_id.to_def_id(),
+                PredicateFilter::SelfConstIfConst,
+            )
+        }
+        Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. }) => {
+            explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
+        }
+        _ => bug!("implied_const_bounds called on wrong item: {def_id:?}"),
+    };
+
+    bounds.map_bound(|bounds| {
+        &*tcx.arena.alloc_from_iter(bounds.iter().copied().map(|(clause, span)| {
+            (
+                clause.kind().map_bound(|clause| match clause {
+                    ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
+                        trait_ref,
+                        host: ty::HostPolarity::Maybe,
+                    }) => trait_ref,
+                    _ => bug!("converted {clause:?}"),
+                }),
+                span,
+            )
+        }))
+    })
+}
diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs
index 1ccb7faaf30..4d3595965c9 100644
--- a/compiler/rustc_hir_analysis/src/delegation.rs
+++ b/compiler/rustc_hir_analysis/src/delegation.rs
@@ -186,7 +186,6 @@ impl<'tcx> GenericsBuilder<'tcx> {
             param_def_id_to_index,
             has_self,
             has_late_bound_regions: sig_generics.has_late_bound_regions,
-            host_effect_index: sig_generics.host_effect_index,
         }
     }
 }
@@ -472,10 +471,6 @@ fn check_constraints<'tcx>(
         }));
     };
 
-    if tcx.has_host_param(sig_id) {
-        emit("delegation to a function with effect parameter is not supported yet");
-    }
-
     if let Some(local_sig_id) = sig_id.as_local()
         && tcx.hir().opt_delegation_sig_id(local_sig_id).is_some()
     {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index 2b0e1350108..c902e85c267 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -154,7 +154,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         for hir_bound in hir_bounds {
             // In order to avoid cycles, when we're lowering `SelfThatDefines`,
             // we skip over any traits that don't define the given associated type.
-
             if let PredicateFilter::SelfThatDefines(assoc_name) = predicate_filter {
                 if let Some(trait_ref) = hir_bound.trait_ref()
                     && let Some(trait_did) = trait_ref.trait_def_id()
@@ -193,6 +192,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     );
                 }
                 hir::GenericBound::Outlives(lifetime) => {
+                    // `ConstIfConst` is only interested in `~const` bounds.
+                    if matches!(
+                        predicate_filter,
+                        PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst
+                    ) {
+                        continue;
+                    }
+
                     let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
                     bounds.push_region_bound(
                         self.tcx(),
@@ -392,21 +399,31 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     },
                 );
 
-                bounds.push_projection_bound(
-                    tcx,
-                    projection_term.map_bound(|projection_term| ty::ProjectionPredicate {
-                        projection_term,
-                        term,
-                    }),
-                    constraint.span,
-                );
+                match predicate_filter {
+                    PredicateFilter::All
+                    | PredicateFilter::SelfOnly
+                    | PredicateFilter::SelfThatDefines(_)
+                    | PredicateFilter::SelfAndAssociatedTypeBounds => {
+                        bounds.push_projection_bound(
+                            tcx,
+                            projection_term.map_bound(|projection_term| ty::ProjectionPredicate {
+                                projection_term,
+                                term,
+                            }),
+                            constraint.span,
+                        );
+                    }
+                    // `ConstIfConst` is only interested in `~const` bounds.
+                    PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
+                }
             }
             // Lower a constraint like `Item: Debug` as found in HIR bound `T: Iterator<Item: Debug>`
             // to a bound involving a projection: `<T as Iterator>::Item: Debug`.
             hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
                 match predicate_filter {
-                    PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => {}
-                    PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
+                    PredicateFilter::All
+                    | PredicateFilter::SelfAndAssociatedTypeBounds
+                    | PredicateFilter::ConstIfConst => {
                         let projection_ty = projection_term
                             .map_bound(|projection_term| projection_term.expect_ty(self.tcx()));
                         // Calling `skip_binder` is okay, because `lower_bounds` expects the `param_ty`
@@ -421,6 +438,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                             predicate_filter,
                         );
                     }
+                    PredicateFilter::SelfOnly
+                    | PredicateFilter::SelfThatDefines(_)
+                    | PredicateFilter::SelfConstIfConst => {}
                 }
             }
         }
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
index 2cee7c77aa5..3449270564a 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
@@ -78,7 +78,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 ty::ClauseKind::RegionOutlives(_)
                 | ty::ClauseKind::ConstArgHasType(..)
                 | ty::ClauseKind::WellFormed(_)
-                | ty::ClauseKind::ConstEvaluatable(_) => {
+                | ty::ClauseKind::ConstEvaluatable(_)
+                | ty::ClauseKind::HostEffect(..) => {
                     span_bug!(span, "did not expect {pred} clause in object bounds");
                 }
             }
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index a73a2f925cd..863c077a9e0 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -81,6 +81,12 @@ pub enum PredicateFilter {
     /// For example, given `Self: Tr<A: B>`, this would expand to `Self: Tr`
     /// and `<Self as Tr>::A: B`.
     SelfAndAssociatedTypeBounds,
+
+    /// Filter only the `~const` bounds, which are lowered into `HostEffect` clauses.
+    ConstIfConst,
+
+    /// Filter only the `~const` bounds which are *also* in the supertrait position.
+    SelfConstIfConst,
 }
 
 #[derive(Debug)]
@@ -693,16 +699,49 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             bound_vars,
         );
 
-        debug!(?poly_trait_ref);
-        bounds.push_trait_bound(
-            tcx,
-            self.item_def_id().to_def_id(),
-            poly_trait_ref,
-            span,
-            polarity,
-            constness,
-            predicate_filter,
-        );
+        match predicate_filter {
+            PredicateFilter::All
+            | PredicateFilter::SelfOnly
+            | PredicateFilter::SelfThatDefines(..)
+            | PredicateFilter::SelfAndAssociatedTypeBounds => {
+                debug!(?poly_trait_ref);
+                bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
+
+                match constness {
+                    Some(ty::BoundConstness::Const) => {
+                        if polarity == ty::PredicatePolarity::Positive {
+                            bounds.push_const_bound(
+                                tcx,
+                                poly_trait_ref,
+                                ty::HostPolarity::Const,
+                                span,
+                            );
+                        }
+                    }
+                    Some(ty::BoundConstness::ConstIfConst) => {
+                        // We don't emit a const bound here, since that would mean that we
+                        // unconditionally need to prove a `HostEffect` predicate, even when
+                        // the predicates are being instantiated in a non-const context. This
+                        // is instead handled in the `const_conditions` query.
+                    }
+                    None => {}
+                }
+            }
+            // On the flip side, when filtering `ConstIfConst` bounds, we only need to convert
+            // `~const` bounds. All other predicates are handled in their respective queries.
+            //
+            // Note that like `PredicateFilter::SelfOnly`, we don't need to do any filtering
+            // here because we only call this on self bounds, and deal with the recursive case
+            // in `lower_assoc_item_constraint`.
+            PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => match constness {
+                Some(ty::BoundConstness::ConstIfConst) => {
+                    if polarity == ty::PredicatePolarity::Positive {
+                        bounds.push_const_bound(tcx, poly_trait_ref, ty::HostPolarity::Maybe, span);
+                    }
+                }
+                None | Some(ty::BoundConstness::Const) => {}
+            },
+        }
 
         let mut dup_constraints = FxIndexMap::default();
         for constraint in trait_segment.args().constraints {
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index 0355adfcb11..a394fc2fbb1 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -530,6 +530,7 @@ fn trait_specialization_kind<'tcx>(
         | ty::ClauseKind::Projection(_)
         | ty::ClauseKind::ConstArgHasType(..)
         | ty::ClauseKind::WellFormed(_)
-        | ty::ClauseKind::ConstEvaluatable(..) => None,
+        | ty::ClauseKind::ConstEvaluatable(..)
+        | ty::ClauseKind::HostEffect(..) => None,
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
index f576499ecac..2c1d443f951 100644
--- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
@@ -53,7 +53,8 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
                     | ty::ClauseKind::Projection(_)
                     | ty::ClauseKind::ConstArgHasType(_, _)
                     | ty::ClauseKind::WellFormed(_)
-                    | ty::ClauseKind::ConstEvaluatable(_) => {}
+                    | ty::ClauseKind::ConstEvaluatable(_)
+                    | ty::ClauseKind::HostEffect(..) => {}
                 }
             }
 
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 3ba9c76bcee..61214b99215 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -2134,7 +2134,7 @@ impl<'a> State<'a> {
                     self.print_type(default);
                 }
             }
-            GenericParamKind::Const { ty, ref default, is_host_effect: _, synthetic: _ } => {
+            GenericParamKind::Const { ty, ref default, synthetic: _ } => {
                 self.word_space(":");
                 self.print_type(ty);
                 if let Some(default) = default {
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 06e2a5e3493..190e405282c 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -20,7 +20,7 @@ use rustc_target::spec::abi;
 use rustc_trait_selection::error_reporting::traits::DefIdOrName;
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
-use tracing::{debug, instrument, trace};
+use tracing::{debug, instrument};
 
 use super::method::MethodCallee;
 use super::method::probe::ProbeScope;
@@ -843,29 +843,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         callee_did: DefId,
         callee_args: GenericArgsRef<'tcx>,
     ) {
-        let tcx = self.tcx;
-
-        // fast-reject if callee doesn't have the host effect param (non-const)
-        let generics = tcx.generics_of(callee_did);
-        let Some(host_effect_index) = generics.host_effect_index else { return };
-
-        let effect = tcx.expected_host_effect_param_for_body(self.body_id);
-
-        trace!(?effect, ?generics, ?callee_args);
+        // FIXME(effects): We should be enforcing these effects unconditionally.
+        // This can be done as soon as we convert the standard library back to
+        // using const traits, since if we were to enforce these conditions now,
+        // we'd fail on basically every builtin trait call (i.e. `1 + 2`).
+        if !self.tcx.features().effects() {
+            return;
+        }
 
-        let param = callee_args.const_at(host_effect_index);
-        let cause = self.misc(span);
-        // We know the type of `effect` to be `bool`, there will be no opaque type inference.
-        match self.at(&cause, self.param_env).eq(infer::DefineOpaqueTypes::Yes, effect, param) {
-            Ok(infer::InferOk { obligations, value: () }) => {
-                self.register_predicates(obligations);
+        let host = match self.tcx.hir().body_const_context(self.body_id) {
+            Some(hir::ConstContext::Const { .. } | hir::ConstContext::Static(_)) => {
+                ty::HostPolarity::Const
             }
-            Err(e) => {
-                // FIXME(effects): better diagnostic
-                self.err_ctxt()
-                    .report_mismatched_consts(&cause, self.param_env, effect, param, e)
-                    .emit();
+            Some(hir::ConstContext::ConstFn) => ty::HostPolarity::Maybe,
+            None => return,
+        };
+
+        // FIXME(effects): Should this be `is_const_fn_raw`? It depends on if we move
+        // const stability checking here too, I guess.
+        if self.tcx.is_conditionally_const(callee_did) {
+            let q = self.tcx.const_conditions(callee_did);
+            // FIXME(effects): Use this span with a better cause code.
+            for (cond, _) in q.instantiate(self.tcx, callee_args) {
+                self.register_predicate(Obligation::new(
+                    self.tcx,
+                    self.misc(span),
+                    self.param_env,
+                    cond.to_host_effect_clause(self.tcx, host),
+                ));
             }
+        } else {
+            // FIXME(effects): This should eventually be caught here.
+            // For now, though, we defer some const checking to MIR.
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index 4fd508ab896..68776c52555 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -7,8 +7,6 @@ use rustc_data_structures::unord::{UnordBag, UnordMap, UnordSet};
 use rustc_hir as hir;
 use rustc_hir::HirId;
 use rustc_hir::intravisit::Visitor;
-use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
-use rustc_middle::bug;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
 use rustc_session::lint;
 use rustc_span::def_id::LocalDefId;
@@ -48,7 +46,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
             self.fulfillment_cx.borrow_mut().pending_obligations()
         );
 
-        let fallback_occurred = self.fallback_types() | self.fallback_effects();
+        let fallback_occurred = self.fallback_types();
 
         if !fallback_occurred {
             return;
@@ -103,31 +101,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         fallback_occurred
     }
 
-    fn fallback_effects(&self) -> bool {
-        let unsolved_effects = self.unsolved_effects();
-
-        if unsolved_effects.is_empty() {
-            return false;
-        }
-
-        // not setting the `fallback_has_occurred` field here because
-        // that field is only used for type fallback diagnostics.
-        for effect in unsolved_effects {
-            let expected = self.tcx.consts.true_;
-            let cause = self.misc(DUMMY_SP);
-            match self.at(&cause, self.param_env).eq(DefineOpaqueTypes::Yes, expected, effect) {
-                Ok(InferOk { obligations, value: () }) => {
-                    self.register_predicates(obligations);
-                }
-                Err(e) => {
-                    bug!("cannot eq unsolved effect: {e:?}")
-                }
-            }
-        }
-
-        true
-    }
-
     // Tries to apply a fallback to `ty` if it is an unsolved variable.
     //
     // - Unconstrained ints are replaced with `i32`.
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index d2d311ef565..0fc566c58f7 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1262,15 +1262,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
                         self.fcx.ty_infer(Some(param), inf.span).into()
                     }
-                    (
-                        &GenericParamDefKind::Const { has_default, is_host_effect, .. },
-                        GenericArg::Infer(inf),
-                    ) => {
-                        if has_default && is_host_effect {
-                            self.fcx.var_for_effect(param)
-                        } else {
-                            self.fcx.ct_infer(Some(param), inf.span).into()
-                        }
+                    (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
+                        self.fcx.ct_infer(Some(param), inf.span).into()
                     }
                     _ => unreachable!(),
                 }
@@ -1305,20 +1298,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             self.fcx.var_for_def(self.span, param)
                         }
                     }
-                    GenericParamDefKind::Const { has_default, is_host_effect, .. } => {
+                    GenericParamDefKind::Const { has_default, .. } => {
                         if has_default {
-                            // N.B. this is a bit of a hack. `infer_args` is passed depending on
-                            // whether the user has provided generic args. E.g. for `Vec::new`
-                            // we would have to infer the generic types. However, for `Vec::<T>::new`
-                            // where the allocator param `A` has a default we will *not* infer. But
-                            // for effect params this is a different story: if the user has not written
-                            // anything explicit for the effect param, we always need to try to infer
-                            // it before falling back to default, such that a `const fn` such as
-                            // `needs_drop::<()>` can still be called in const contexts. (if we defaulted
-                            // instead of inferred, typeck would error)
-                            if is_host_effect {
-                                return self.fcx.var_for_effect(param);
-                            } else if !infer_args {
+                            if !infer_args {
                                 return tcx
                                     .const_param_default(param.def_id)
                                     .instantiate(tcx, preceding_args)
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
index 693cb4465cc..eb5fe3a86e4 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
@@ -52,6 +52,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             | ty::PredicateKind::AliasRelate(..)
             | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
             | ty::PredicateKind::ConstEquate(..)
+            | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..))
             | ty::PredicateKind::Ambiguous => false,
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 4123feebb40..3940d138deb 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -247,12 +247,6 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
     fn ct_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
         // FIXME ideally this shouldn't use unwrap
         match param {
-            Some(
-                param @ ty::GenericParamDef {
-                    kind: ty::GenericParamDefKind::Const { is_host_effect: true, .. },
-                    ..
-                },
-            ) => self.var_for_effect(param).as_const().unwrap(),
             Some(param) => self.var_for_def(span, param).as_const().unwrap(),
             None => self.next_const_var(span),
         }
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index 69b9be00276..e20a0cb67c3 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -369,17 +369,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
         let (obligation, args) =
             self.obligation_for_method(cause, trait_def_id, self_ty, opt_input_types);
-        // FIXME(effects) find a better way to do this
-        // Operators don't have generic methods, but making them `#[const_trait]` gives them
-        // `const host: bool`.
-        let args = if self.tcx.is_const_trait(trait_def_id) {
-            self.tcx.mk_args_from_iter(
-                args.iter()
-                    .chain([self.tcx.expected_host_effect_param_for_body(self.body_id).into()]),
-            )
-        } else {
-            args
-        };
         self.construct_obligation_for_trait(m_name, trait_def_id, obligation, args)
     }
 
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index b60fa8bbfa1..569fdea11ce 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -813,7 +813,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 | ty::ClauseKind::Projection(_)
                 | ty::ClauseKind::ConstArgHasType(_, _)
                 | ty::ClauseKind::WellFormed(_)
-                | ty::ClauseKind::ConstEvaluatable(_) => None,
+                | ty::ClauseKind::ConstEvaluatable(_)
+                | ty::ClauseKind::HostEffect(..) => None,
             }
         });
 
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index e3519dfb028..90d07964fda 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -489,17 +489,6 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
                     }
                 }
             }
-            ty::ConstKind::Infer(InferConst::EffectVar(vid)) => {
-                match self.infcx.unwrap().probe_effect_var(vid) {
-                    Some(value) => return self.fold_const(value),
-                    None => {
-                        return self.canonicalize_const_var(
-                            CanonicalVarInfo { kind: CanonicalVarKind::Effect },
-                            ct,
-                        );
-                    }
-                }
-            }
             ty::ConstKind::Infer(InferConst::Fresh(_)) => {
                 bug!("encountered a fresh const during canonicalization")
             }
@@ -700,8 +689,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
             .iter()
             .map(|v| CanonicalVarInfo {
                 kind: match v.kind {
-                    CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float)
-                    | CanonicalVarKind::Effect => {
+                    CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => {
                         return *v;
                     }
                     CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => {
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index 8caedcd4053..fb5fc3a53fe 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -24,7 +24,6 @@
 pub use instantiate::CanonicalExt;
 use rustc_index::IndexVec;
 pub use rustc_middle::infer::canonical::*;
-use rustc_middle::infer::unify_key::EffectVarValue;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{self, GenericArg, List, Ty, TyCtxt};
 use rustc_span::Span;
@@ -145,15 +144,6 @@ impl<'tcx> InferCtxt<'tcx> {
             CanonicalVarKind::Const(ui) => {
                 self.next_const_var_in_universe(span, universe_map(ui)).into()
             }
-            CanonicalVarKind::Effect => {
-                let vid = self
-                    .inner
-                    .borrow_mut()
-                    .effect_unification_table()
-                    .new_key(EffectVarValue::Unknown)
-                    .vid;
-                ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(vid)).into()
-            }
             CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }) => {
                 let universe_mapped = universe_map(universe);
                 let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, bound };
diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs
index 57007752cad..0c151a11ad4 100644
--- a/compiler/rustc_infer/src/infer/context.rs
+++ b/compiler/rustc_infer/src/infer/context.rs
@@ -1,6 +1,5 @@
 ///! Definition of `InferCtxtLike` from the librarified type layer.
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::infer::unify_key::EffectVarValue;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::traits::solve::SolverMode;
 use rustc_middle::ty::fold::TypeFoldable;
@@ -88,15 +87,6 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
         }
     }
 
-    fn opportunistic_resolve_effect_var(&self, vid: ty::EffectVid) -> ty::Const<'tcx> {
-        match self.probe_effect_var(vid) {
-            Some(ct) => ct,
-            None => {
-                ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(self.root_effect_var(vid)))
-            }
-        }
-    }
-
     fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> {
         self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
     }
@@ -152,10 +142,6 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
         self.inner.borrow_mut().const_unification_table().union(a, b);
     }
 
-    fn equate_effect_vids_raw(&self, a: rustc_type_ir::EffectVid, b: rustc_type_ir::EffectVid) {
-        self.inner.borrow_mut().effect_unification_table().union(a, b);
-    }
-
     fn instantiate_ty_var_raw<R: PredicateEmittingRelation<Self>>(
         &self,
         relation: &mut R,
@@ -189,13 +175,6 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
         self.inner.borrow_mut().float_unification_table().union_value(vid, value);
     }
 
-    fn instantiate_effect_var_raw(&self, vid: rustc_type_ir::EffectVid, value: ty::Const<'tcx>) {
-        self.inner
-            .borrow_mut()
-            .effect_unification_table()
-            .union_value(vid, EffectVarValue::Known(value));
-    }
-
     fn instantiate_const_var_raw<R: PredicateEmittingRelation<Self>>(
         &self,
         relation: &mut R,
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index c4294111ebe..28eac5b7496 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -153,15 +153,6 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
                 drop(inner);
                 self.freshen_const(input, ty::InferConst::Fresh)
             }
-            ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => {
-                let mut inner = self.infcx.inner.borrow_mut();
-                let input =
-                    inner.effect_unification_table().probe_value(v).known().ok_or_else(|| {
-                        ty::InferConst::EffectVar(inner.effect_unification_table().find(v).vid)
-                    });
-                drop(inner);
-                self.freshen_const(input, ty::InferConst::Fresh)
-            }
             ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => {
                 if i >= self.const_freshen_count {
                     bug!(
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 5afdf3c2454..be43cba97f0 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -26,9 +26,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_macros::extension;
 pub use rustc_macros::{TypeFoldable, TypeVisitable};
 use rustc_middle::infer::canonical::{CanonicalQueryInput, CanonicalVarValues};
-use rustc_middle::infer::unify_key::{
-    ConstVariableOrigin, ConstVariableValue, ConstVidKey, EffectVarValue, EffectVidKey,
-};
+use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey};
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
 use rustc_middle::traits::select;
@@ -39,7 +37,7 @@ use rustc_middle::ty::fold::{
 };
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{
-    self, ConstVid, EffectVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef,
+    self, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef,
     GenericParamDefKind, InferConst, IntVid, Ty, TyCtxt, TyVid,
 };
 use rustc_middle::{bug, span_bug};
@@ -117,9 +115,6 @@ pub struct InferCtxtInner<'tcx> {
     /// Map from floating variable to the kind of float it represents.
     float_unification_storage: ut::UnificationTableStorage<ty::FloatVid>,
 
-    /// Map from effect variable to the effect param it represents.
-    effect_unification_storage: ut::UnificationTableStorage<EffectVidKey<'tcx>>,
-
     /// Tracks the set of region variables and the constraints between them.
     ///
     /// This is initially `Some(_)` but when
@@ -176,7 +171,6 @@ impl<'tcx> InferCtxtInner<'tcx> {
             const_unification_storage: Default::default(),
             int_unification_storage: Default::default(),
             float_unification_storage: Default::default(),
-            effect_unification_storage: Default::default(),
             region_constraint_storage: Some(Default::default()),
             region_obligations: vec![],
             opaque_type_storage: Default::default(),
@@ -228,10 +222,6 @@ impl<'tcx> InferCtxtInner<'tcx> {
         self.const_unification_storage.with_log(&mut self.undo_log)
     }
 
-    fn effect_unification_table(&mut self) -> UnificationTable<'_, 'tcx, EffectVidKey<'tcx>> {
-        self.effect_unification_storage.with_log(&mut self.undo_log)
-    }
-
     #[inline]
     pub fn unwrap_region_constraints(&mut self) -> RegionConstraintCollector<'_, 'tcx> {
         self.region_constraint_storage
@@ -524,7 +514,6 @@ impl fmt::Display for FixupError {
             ),
             Ty(_) => write!(f, "unconstrained type"),
             Const(_) => write!(f, "unconstrained const value"),
-            Effect(_) => write!(f, "unconstrained effect value"),
         }
     }
 }
@@ -726,17 +715,6 @@ impl<'tcx> InferCtxt<'tcx> {
         vars
     }
 
-    pub fn unsolved_effects(&self) -> Vec<ty::Const<'tcx>> {
-        let mut inner = self.inner.borrow_mut();
-        let mut table = inner.effect_unification_table();
-
-        (0..table.len())
-            .map(|i| ty::EffectVid::from_usize(i))
-            .filter(|&vid| table.probe_value(vid).is_unknown())
-            .map(|v| ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(v)))
-            .collect()
-    }
-
     #[instrument(skip(self), level = "debug")]
     pub fn sub_regions(
         &self,
@@ -899,13 +877,6 @@ impl<'tcx> InferCtxt<'tcx> {
         ty::Const::new_var(self.tcx, vid)
     }
 
-    fn next_effect_var(&self) -> ty::Const<'tcx> {
-        let effect_vid =
-            self.inner.borrow_mut().effect_unification_table().new_key(EffectVarValue::Unknown).vid;
-
-        ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(effect_vid))
-    }
-
     pub fn next_int_var(&self) -> Ty<'tcx> {
         let next_int_var_id =
             self.inner.borrow_mut().int_unification_table().new_key(ty::IntVarValue::Unknown);
@@ -991,10 +962,7 @@ impl<'tcx> InferCtxt<'tcx> {
 
                 Ty::new_var(self.tcx, ty_var_id).into()
             }
-            GenericParamDefKind::Const { is_host_effect, .. } => {
-                if is_host_effect {
-                    return self.var_for_effect(param);
-                }
+            GenericParamDefKind::Const { .. } => {
                 let origin = ConstVariableOrigin { param_def_id: Some(param.def_id), span };
                 let const_var_id = self
                     .inner
@@ -1007,16 +975,6 @@ impl<'tcx> InferCtxt<'tcx> {
         }
     }
 
-    pub fn var_for_effect(&self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
-        let ty = self
-            .tcx
-            .type_of(param.def_id)
-            .no_bound_vars()
-            .expect("const parameter types cannot be generic");
-        debug_assert_eq!(self.tcx.types.bool, ty);
-        self.next_effect_var().into()
-    }
-
     /// Given a set of generics defined on a type or impl, returns the generic parameters mapping
     /// each type/region parameter to a fresh inference variable.
     pub fn fresh_args_for_item(&self, span: Span, def_id: DefId) -> GenericArgsRef<'tcx> {
@@ -1142,13 +1100,6 @@ impl<'tcx> InferCtxt<'tcx> {
                     .probe_value(vid)
                     .known()
                     .unwrap_or(ct),
-                InferConst::EffectVar(vid) => self
-                    .inner
-                    .borrow_mut()
-                    .effect_unification_table()
-                    .probe_value(vid)
-                    .known()
-                    .unwrap_or(ct),
                 InferConst::Fresh(_) => ct,
             },
             ty::ConstKind::Param(_)
@@ -1169,10 +1120,6 @@ impl<'tcx> InferCtxt<'tcx> {
         self.inner.borrow_mut().const_unification_table().find(var).vid
     }
 
-    pub fn root_effect_var(&self, var: ty::EffectVid) -> ty::EffectVid {
-        self.inner.borrow_mut().effect_unification_table().find(var).vid
-    }
-
     /// Resolves an int var to a rigid int type, if it was constrained to one,
     /// or else the root int var in the unification table.
     pub fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> {
@@ -1238,10 +1185,6 @@ impl<'tcx> InferCtxt<'tcx> {
         }
     }
 
-    pub fn probe_effect_var(&self, vid: EffectVid) -> Option<ty::Const<'tcx>> {
-        self.inner.borrow_mut().effect_unification_table().probe_value(vid).known()
-    }
-
     /// Attempts to resolve all type/region/const variables in
     /// `value`. Region inference must have been run already (e.g.,
     /// by calling `resolve_regions_and_report_errors`). If some
@@ -1511,14 +1454,6 @@ impl<'tcx> InferCtxt<'tcx> {
                     ConstVariableValue::Known { .. } => true,
                 }
             }
-
-            TyOrConstInferVar::Effect(v) => {
-                // If `probe_value` returns `Some`, it never equals
-                // `ty::ConstKind::Infer(ty::InferConst::Effect(v))`.
-                //
-                // Not `inlined_probe_value(v)` because this call site is colder.
-                self.probe_effect_var(v).is_some()
-            }
         }
     }
 
@@ -1545,8 +1480,6 @@ pub enum TyOrConstInferVar {
 
     /// Equivalent to `ty::ConstKind::Infer(ty::InferConst::Var(_))`.
     Const(ConstVid),
-    /// Equivalent to `ty::ConstKind::Infer(ty::InferConst::EffectVar(_))`.
-    Effect(EffectVid),
 }
 
 impl<'tcx> TyOrConstInferVar {
@@ -1577,7 +1510,6 @@ impl<'tcx> TyOrConstInferVar {
     fn maybe_from_const(ct: ty::Const<'tcx>) -> Option<Self> {
         match ct.kind() {
             ty::ConstKind::Infer(InferConst::Var(v)) => Some(TyOrConstInferVar::Const(v)),
-            ty::ConstKind::Infer(InferConst::EffectVar(v)) => Some(TyOrConstInferVar::Effect(v)),
             _ => None,
         }
     }
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index e23bb1aaa56..1afe50e336d 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -24,19 +24,9 @@ pub fn explicit_outlives_bounds<'tcx>(
     param_env
         .caller_bounds()
         .into_iter()
-        .map(ty::Clause::kind)
+        .filter_map(ty::Clause::as_region_outlives_clause)
         .filter_map(ty::Binder::no_bound_vars)
-        .filter_map(move |kind| match kind {
-            ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
-                Some(OutlivesBound::RegionSubRegion(r_b, r_a))
-            }
-            ty::ClauseKind::Trait(_)
-            | ty::ClauseKind::TypeOutlives(_)
-            | ty::ClauseKind::Projection(_)
-            | ty::ClauseKind::ConstArgHasType(_, _)
-            | ty::ClauseKind::WellFormed(_)
-            | ty::ClauseKind::ConstEvaluatable(_) => None,
-        })
+        .map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a))
 }
 
 impl<'tcx> InferCtxt<'tcx> {
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index 7049444db9b..32817dbcb21 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -660,7 +660,6 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
                     }
                 }
             }
-            ty::ConstKind::Infer(InferConst::EffectVar(_)) => Ok(c),
             // FIXME: Unevaluated constants are also not rigid, so the current
             // approach of always relating them structurally is incomplete.
             //
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index 64cc76f827e..6ec2e0152f0 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -176,9 +176,6 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
                 ty::ConstKind::Infer(InferConst::Fresh(_)) => {
                     bug!("Unexpected const in full const resolver: {:?}", c);
                 }
-                ty::ConstKind::Infer(InferConst::EffectVar(evid)) => {
-                    return Err(FixupError { unresolved: super::TyOrConstInferVar::Effect(evid) });
-                }
                 _ => {}
             }
             c.try_super_fold_with(self)
diff --git a/compiler/rustc_infer/src/infer/snapshot/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs
index 613cebc266d..394e07a81e7 100644
--- a/compiler/rustc_infer/src/infer/snapshot/fudge.rs
+++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs
@@ -4,7 +4,6 @@ use rustc_data_structures::{snapshot_vec as sv, unify as ut};
 use rustc_middle::infer::unify_key::{ConstVariableValue, ConstVidKey};
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid};
-use rustc_type_ir::EffectVid;
 use rustc_type_ir::visit::TypeVisitableExt;
 use tracing::instrument;
 use ut::UnifyKey;
@@ -129,7 +128,6 @@ struct SnapshotVarData {
     int_vars: Range<IntVid>,
     float_vars: Range<FloatVid>,
     const_vars: (Range<ConstVid>, Vec<ConstVariableOrigin>),
-    effect_vars: Range<EffectVid>,
 }
 
 impl SnapshotVarData {
@@ -148,30 +146,16 @@ impl SnapshotVarData {
             &mut inner.const_unification_table(),
             vars_pre_snapshot.const_var_len,
         );
-        let effect_vars = vars_since_snapshot(
-            &inner.effect_unification_table(),
-            vars_pre_snapshot.effect_var_len,
-        );
-        let effect_vars = effect_vars.start.vid..effect_vars.end.vid;
-
-        SnapshotVarData { region_vars, type_vars, int_vars, float_vars, const_vars, effect_vars }
+        SnapshotVarData { region_vars, type_vars, int_vars, float_vars, const_vars }
     }
 
     fn is_empty(&self) -> bool {
-        let SnapshotVarData {
-            region_vars,
-            type_vars,
-            int_vars,
-            float_vars,
-            const_vars,
-            effect_vars,
-        } = self;
+        let SnapshotVarData { region_vars, type_vars, int_vars, float_vars, const_vars } = self;
         region_vars.0.is_empty()
             && type_vars.0.is_empty()
             && int_vars.is_empty()
             && float_vars.is_empty()
             && const_vars.0.is_empty()
-            && effect_vars.is_empty()
     }
 }
 
@@ -258,13 +242,6 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceFudger<'a, 'tcx> {
                         ct
                     }
                 }
-                ty::InferConst::EffectVar(vid) => {
-                    if self.snapshot_vars.effect_vars.contains(&vid) {
-                        self.infcx.next_effect_var()
-                    } else {
-                        ct
-                    }
-                }
                 ty::InferConst::Fresh(_) => {
                     unreachable!("unexpected fresh infcx var")
                 }
diff --git a/compiler/rustc_infer/src/infer/snapshot/mod.rs b/compiler/rustc_infer/src/infer/snapshot/mod.rs
index fa813500c54..b16c80cf201 100644
--- a/compiler/rustc_infer/src/infer/snapshot/mod.rs
+++ b/compiler/rustc_infer/src/infer/snapshot/mod.rs
@@ -23,7 +23,6 @@ struct VariableLengths {
     int_var_len: usize,
     float_var_len: usize,
     const_var_len: usize,
-    effect_var_len: usize,
 }
 
 impl<'tcx> InferCtxt<'tcx> {
@@ -35,7 +34,6 @@ impl<'tcx> InferCtxt<'tcx> {
             int_var_len: inner.int_unification_table().len(),
             float_var_len: inner.float_unification_table().len(),
             const_var_len: inner.const_unification_table().len(),
-            effect_var_len: inner.effect_unification_table().len(),
         }
     }
 
diff --git a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs
index 79ea0915c9c..713389f4618 100644
--- a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs
+++ b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs
@@ -2,7 +2,7 @@ use std::marker::PhantomData;
 
 use rustc_data_structures::undo_log::{Rollback, UndoLogs};
 use rustc_data_structures::{snapshot_vec as sv, unify as ut};
-use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey, RegionVidKey};
+use rustc_middle::infer::unify_key::{ConstVidKey, RegionVidKey};
 use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey};
 use tracing::debug;
 
@@ -22,7 +22,6 @@ pub(crate) enum UndoLog<'tcx> {
     ConstUnificationTable(sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>),
     IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
     FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
-    EffectUnificationTable(sv::UndoLog<ut::Delegate<EffectVidKey<'tcx>>>),
     RegionConstraintCollector(region_constraints::UndoLog<'tcx>),
     RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
     ProjectionCache(traits::UndoLog<'tcx>),
@@ -50,7 +49,6 @@ impl_from! {
     FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
 
     ConstUnificationTable(sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>),
-    EffectUnificationTable(sv::UndoLog<ut::Delegate<EffectVidKey<'tcx>>>),
 
     RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
     ProjectionCache(traits::UndoLog<'tcx>),
@@ -65,7 +63,6 @@ impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
             UndoLog::ConstUnificationTable(undo) => self.const_unification_storage.reverse(undo),
             UndoLog::IntUnificationTable(undo) => self.int_unification_storage.reverse(undo),
             UndoLog::FloatUnificationTable(undo) => self.float_unification_storage.reverse(undo),
-            UndoLog::EffectUnificationTable(undo) => self.effect_unification_storage.reverse(undo),
             UndoLog::RegionConstraintCollector(undo) => {
                 self.region_constraint_storage.as_mut().unwrap().reverse(undo)
             }
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 5c5cd99345e..a1e4bc75c21 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1554,7 +1554,9 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
                     // Ignore bounds that a user can't type
                     | ClauseKind::WellFormed(..)
                     // FIXME(generic_const_exprs): `ConstEvaluatable` can be written
-                    | ClauseKind::ConstEvaluatable(..)  => continue,
+                    | ClauseKind::ConstEvaluatable(..)
+                    // Users don't write this directly, only via another trait ref.
+                    | ty::ClauseKind::HostEffect(..) => continue,
                 };
                 if predicate.is_global() {
                     cx.emit_span_lint(TRIVIAL_BOUNDS, span, BuiltinTrivialBounds {
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 83a8ca4307e..1c27e1daa90 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -542,11 +542,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
     }
 
     fn check_generic_param(&mut self, cx: &LateContext<'_>, param: &hir::GenericParam<'_>) {
-        if let GenericParamKind::Const { is_host_effect, .. } = param.kind {
-            // `host` params are explicitly allowed to be lowercase.
-            if is_host_effect {
-                return;
-            }
+        if let GenericParamKind::Const { .. } = param.kind {
             NonUpperCaseGlobals::check_upper_case(cx, "const parameter", &param.name.ident());
         }
     }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 7bb40996d58..71c7231a788 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -275,6 +275,8 @@ provide! { tcx, def_id, other, cdata,
     impl_parent => { table }
     defaultness => { table_direct }
     constness => { table_direct }
+    const_conditions => { table }
+    implied_const_bounds => { table_defaulted_array }
     coerce_unsized_info => {
         Ok(cdata
             .root
@@ -330,7 +332,6 @@ provide! { tcx, def_id, other, cdata,
             .process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys")))
     }
 
-    associated_type_for_effects => { table }
     associated_types_for_impl_traits_in_associated_fn => { table_defaulted_array }
 
     visibility => { cdata.get_visibility(def_id.index) }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index ec678c7515b..e06c86ae4c0 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1433,6 +1433,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     }
                 }
             }
+            if tcx.is_conditionally_const(def_id) {
+                record!(self.tables.const_conditions[def_id] <- self.tcx.const_conditions(def_id));
+            }
             if should_encode_type(tcx, local_id, def_kind) {
                 record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id));
             }
@@ -1456,10 +1459,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     self.tcx.explicit_super_predicates_of(def_id).skip_binder());
                 record_defaulted_array!(self.tables.explicit_implied_predicates_of[def_id] <-
                     self.tcx.explicit_implied_predicates_of(def_id).skip_binder());
-
                 let module_children = self.tcx.module_children_local(local_id);
                 record_array!(self.tables.module_children_non_reexports[def_id] <-
                     module_children.iter().map(|child| child.res.def_id().index));
+                if self.tcx.is_const_trait(def_id) {
+                    record_defaulted_array!(self.tables.implied_const_bounds[def_id]
+                        <- self.tcx.implied_const_bounds(def_id).skip_binder());
+                }
             }
             if let DefKind::TraitAlias = def_kind {
                 record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id));
@@ -1479,9 +1485,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 for &def_id in associated_item_def_ids {
                     self.encode_info_for_assoc_item(def_id);
                 }
-                if let Some(assoc_def_id) = self.tcx.associated_type_for_effects(def_id) {
-                    record!(self.tables.associated_type_for_effects[def_id] <- assoc_def_id);
-                }
             }
             if let DefKind::Closure | DefKind::SyntheticCoroutineBody = def_kind
                 && let Some(coroutine_kind) = self.tcx.coroutine_kind(def_id)
@@ -1652,6 +1655,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 if let ty::AssocKind::Type = item.kind {
                     self.encode_explicit_item_bounds(def_id);
                     self.encode_explicit_item_super_predicates(def_id);
+                    if tcx.is_conditionally_const(def_id) {
+                        record_defaulted_array!(self.tables.implied_const_bounds[def_id]
+                            <- self.tcx.implied_const_bounds(def_id).skip_binder());
+                    }
                 }
             }
             AssocItemContainer::ImplContainer => {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 79bd1c13b12..a00ca27aacc 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -392,9 +392,9 @@ define_tables! {
     inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
     explicit_super_predicates_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
     explicit_implied_predicates_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
+    implied_const_bounds: Table<DefIndex, LazyArray<(ty::PolyTraitRef<'static>, Span)>>,
     inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
     associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>,
-    associated_type_for_effects: Table<DefIndex, Option<LazyValue<DefId>>>,
     opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>,
     is_effects_desugaring: Table<DefIndex, bool>,
     unused_generic_params: Table<DefIndex, UnusedGenericParams>,
@@ -436,6 +436,7 @@ define_tables! {
     thir_abstract_const: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, ty::Const<'static>>>>,
     impl_parent: Table<DefIndex, RawDefId>,
     constness: Table<DefIndex, hir::Constness>,
+    const_conditions: Table<DefIndex, LazyValue<ty::ConstConditions<'static>>>,
     defaultness: Table<DefIndex, hir::Defaultness>,
     // FIXME(eddyb) perhaps compute this on the fly if cheap enough?
     coerce_unsized_info: Table<DefIndex, LazyValue<ty::adjustment::CoerceUnsizedInfo>>,
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index cf692b145b8..7f9211043d6 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -172,70 +172,3 @@ impl<'tcx> UnifyValue for ConstVariableValue<'tcx> {
         }
     }
 }
-
-/// values for the effect inference variable
-#[derive(Clone, Copy, Debug)]
-pub enum EffectVarValue<'tcx> {
-    Unknown,
-    Known(ty::Const<'tcx>),
-}
-
-impl<'tcx> EffectVarValue<'tcx> {
-    pub fn known(self) -> Option<ty::Const<'tcx>> {
-        match self {
-            EffectVarValue::Unknown => None,
-            EffectVarValue::Known(value) => Some(value),
-        }
-    }
-
-    pub fn is_unknown(self) -> bool {
-        match self {
-            EffectVarValue::Unknown => true,
-            EffectVarValue::Known(_) => false,
-        }
-    }
-}
-
-impl<'tcx> UnifyValue for EffectVarValue<'tcx> {
-    type Error = NoError;
-
-    fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
-        match (*value1, *value2) {
-            (EffectVarValue::Unknown, EffectVarValue::Unknown) => Ok(EffectVarValue::Unknown),
-            (EffectVarValue::Unknown, EffectVarValue::Known(val))
-            | (EffectVarValue::Known(val), EffectVarValue::Unknown) => {
-                Ok(EffectVarValue::Known(val))
-            }
-            (EffectVarValue::Known(_), EffectVarValue::Known(_)) => {
-                bug!("equating known inference variables: {value1:?} {value2:?}")
-            }
-        }
-    }
-}
-
-#[derive(PartialEq, Copy, Clone, Debug)]
-pub struct EffectVidKey<'tcx> {
-    pub vid: ty::EffectVid,
-    pub phantom: PhantomData<ty::Const<'tcx>>,
-}
-
-impl<'tcx> From<ty::EffectVid> for EffectVidKey<'tcx> {
-    fn from(vid: ty::EffectVid) -> Self {
-        EffectVidKey { vid, phantom: PhantomData }
-    }
-}
-
-impl<'tcx> UnifyKey for EffectVidKey<'tcx> {
-    type Value = EffectVarValue<'tcx>;
-    #[inline]
-    fn index(&self) -> u32 {
-        self.vid.as_u32()
-    }
-    #[inline]
-    fn from_index(i: u32) -> Self {
-        EffectVidKey::from(ty::EffectVid::from_u32(i))
-    }
-    fn tag() -> &'static str {
-        "EffectVidKey"
-    }
-}
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 48bf4ffced0..5f8427bd707 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -370,6 +370,7 @@ tcx_lifetime! {
     rustc_middle::ty::FnSig,
     rustc_middle::ty::GenericArg,
     rustc_middle::ty::GenericPredicates,
+    rustc_middle::ty::ConstConditions,
     rustc_middle::ty::inhabitedness::InhabitedPredicate,
     rustc_middle::ty::Instance,
     rustc_middle::ty::InstanceKind,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index f8ba606e087..d03fc39c9ad 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -683,6 +683,24 @@ rustc_queries! {
         }
     }
 
+    query const_conditions(
+        key: DefId
+    ) -> ty::ConstConditions<'tcx> {
+        desc { |tcx| "computing the conditions for `{}` to be considered const",
+            tcx.def_path_str(key)
+        }
+        separate_provide_extern
+    }
+
+    query implied_const_bounds(
+        key: DefId
+    ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> {
+        desc { |tcx| "computing the implied `~const` bounds for `{}`",
+            tcx.def_path_str(key)
+        }
+        separate_provide_extern
+    }
+
     /// To avoid cycles within the predicates of a single item we compute
     /// per-type-parameter predicates for resolving `T::AssocTy`.
     query type_param_predicates(
@@ -854,12 +872,6 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    query associated_type_for_effects(def_id: DefId) -> Option<DefId> {
-        desc { |tcx| "creating associated items for effects in `{}`", tcx.def_path_str(def_id) }
-        cache_on_disk_if { def_id.is_local() }
-        separate_provide_extern
-    }
-
     /// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding
     /// associated item.
     query associated_type_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId {
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 7e533bc4291..ef9dfdd2f96 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -387,6 +387,17 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [(ty::Claus
 }
 
 impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
+    for [(ty::PolyTraitRef<'tcx>, Span)]
+{
+    fn decode(decoder: &mut D) -> &'tcx Self {
+        decoder
+            .interner()
+            .arena
+            .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder)))
+    }
+}
+
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
     for ty::List<ty::BoundVariableKind>
 {
     fn decode(decoder: &mut D) -> &'tcx Self {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index b682524ae39..eab106a4403 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -78,10 +78,10 @@ use crate::traits::solve::{
 use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
 use crate::ty::{
     self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, GenericArg, GenericArgs,
-    GenericArgsRef, GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, ParamConst,
-    ParamTy, Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind,
-    PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid,
-    Visibility,
+    GenericArgsRef, GenericParamDefKind, HostPolarity, ImplPolarity, List, ListWithCachedTypeInfo,
+    ParamConst, ParamTy, Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate,
+    PredicateKind, PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty,
+    TyKind, TyVid, Visibility,
 };
 
 #[allow(rustc::usage_of_ty_tykind)]
@@ -383,6 +383,28 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         self.explicit_implied_predicates_of(def_id).map_bound(|preds| preds.into_iter().copied())
     }
 
+    fn is_const_impl(self, def_id: DefId) -> bool {
+        self.is_conditionally_const(def_id)
+    }
+
+    fn const_conditions(
+        self,
+        def_id: DefId,
+    ) -> ty::EarlyBinder<'tcx, impl IntoIterator<Item = ty::Binder<'tcx, ty::TraitRef<'tcx>>>> {
+        ty::EarlyBinder::bind(
+            self.const_conditions(def_id).instantiate_identity(self).into_iter().map(|(c, _)| c),
+        )
+    }
+
+    fn implied_const_bounds(
+        self,
+        def_id: DefId,
+    ) -> ty::EarlyBinder<'tcx, impl IntoIterator<Item = ty::Binder<'tcx, ty::TraitRef<'tcx>>>> {
+        ty::EarlyBinder::bind(
+            self.implied_const_bounds(def_id).iter_identity_copied().map(|(c, _)| c),
+        )
+    }
+
     fn has_target_features(self, def_id: DefId) -> bool {
         !self.codegen_fn_attrs(def_id).target_features.is_empty()
     }
@@ -646,13 +668,6 @@ bidirectional_lang_item_map! {
     Destruct,
     DiscriminantKind,
     DynMetadata,
-    EffectsCompat,
-    EffectsIntersection,
-    EffectsIntersectionOutput,
-    EffectsMaybe,
-    EffectsNoRuntime,
-    EffectsRuntime,
-    EffectsTyCompat,
     Fn,
     FnMut,
     FnOnce,
@@ -2196,7 +2211,7 @@ macro_rules! nop_slice_lift {
 nop_slice_lift! {ty::ValTree<'a> => ty::ValTree<'tcx>}
 
 TrivialLiftImpls! {
-    ImplPolarity, PredicatePolarity, Promoted
+    ImplPolarity, PredicatePolarity, Promoted, HostPolarity,
 }
 
 macro_rules! sty_debug_print {
@@ -3125,6 +3140,7 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
+    // FIXME(effects): Please remove this. It's a footgun.
     /// Whether the trait impl is marked const. This does not consider stability or feature gates.
     pub fn is_const_trait_impl_raw(self, def_id: DefId) -> bool {
         let Some(local_def_id) = def_id.as_local() else { return false };
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 8bd2ae9128f..64405d18c7d 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -592,9 +592,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> {
         match c.kind() {
             ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => {}
 
-            // effect variables are always suggestable, because they are not visible
-            ConstKind::Infer(InferConst::EffectVar(_)) => {}
-
             ConstKind::Infer(..)
             | ConstKind::Bound(..)
             | ConstKind::Placeholder(..)
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 92a975c028e..704a197aa49 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -265,6 +265,12 @@ impl FlagComputation {
             ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
                 self.add_args(trait_pred.trait_ref.args);
             }
+            ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
+                trait_ref,
+                host: _,
+            })) => {
+                self.add_args(trait_ref.args);
+            }
             ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
                 a,
                 b,
@@ -354,9 +360,7 @@ impl FlagComputation {
                 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
                 match infer {
                     InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH),
-                    InferConst::Var(_) | InferConst::EffectVar(_) => {
-                        self.add_flags(TypeFlags::HAS_CT_INFER)
-                    }
+                    InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER),
                 }
             }
             ty::ConstKind::Bound(debruijn, _) => {
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index daf1362e25c..56111ee063e 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -501,12 +501,11 @@ impl<'tcx> GenericArgs<'tcx> {
     #[inline]
     pub fn non_erasable_generics(
         &'tcx self,
-        tcx: TyCtxt<'tcx>,
-        def_id: DefId,
+        // FIXME(effects): Remove these
+        _tcx: TyCtxt<'tcx>,
+        _def_id: DefId,
     ) -> impl DoubleEndedIterator<Item = GenericArgKind<'tcx>> + 'tcx {
-        let generics = tcx.generics_of(def_id);
-        self.iter().enumerate().filter_map(|(i, k)| match k.unpack() {
-            _ if Some(i) == generics.host_effect_index => None,
+        self.iter().filter_map(|k| match k.unpack() {
             ty::GenericArgKind::Lifetime(_) => None,
             generic => Some(generic),
         })
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 63534a3d017..ab1b8fa6a73 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -14,7 +14,7 @@ use crate::ty::{EarlyBinder, GenericArgsRef};
 pub enum GenericParamDefKind {
     Lifetime,
     Type { has_default: bool, synthetic: bool },
-    Const { has_default: bool, is_host_effect: bool, synthetic: bool },
+    Const { has_default: bool, synthetic: bool },
 }
 
 impl GenericParamDefKind {
@@ -81,10 +81,6 @@ impl GenericParamDef {
         }
     }
 
-    pub fn is_host_effect(&self) -> bool {
-        matches!(self.kind, GenericParamDefKind::Const { is_host_effect: true, .. })
-    }
-
     pub fn default_value<'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
@@ -133,9 +129,6 @@ pub struct Generics {
 
     pub has_self: bool,
     pub has_late_bound_regions: Option<Span>,
-
-    // The index of the host effect when instantiated. (i.e. might be index to parent args)
-    pub host_effect_index: Option<usize>,
 }
 
 impl<'tcx> rustc_type_ir::inherent::GenericsOf<TyCtxt<'tcx>> for &'tcx Generics {
@@ -216,12 +209,10 @@ impl<'tcx> Generics {
     pub fn own_requires_monomorphization(&self) -> bool {
         for param in &self.own_params {
             match param.kind {
-                GenericParamDefKind::Type { .. }
-                | GenericParamDefKind::Const { is_host_effect: false, .. } => {
+                GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
                     return true;
                 }
-                GenericParamDefKind::Lifetime
-                | GenericParamDefKind::Const { is_host_effect: true, .. } => {}
+                GenericParamDefKind::Lifetime => {}
             }
         }
         false
@@ -300,8 +291,6 @@ impl<'tcx> Generics {
             own_params.start = 1;
         }
 
-        let verbose = tcx.sess.verbose_internals();
-
         // Filter the default arguments.
         //
         // This currently uses structural equality instead
@@ -316,8 +305,6 @@ impl<'tcx> Generics {
                 param.default_value(tcx).is_some_and(|default| {
                     default.instantiate(tcx, args) == args[param.index as usize]
                 })
-                // filter out trailing effect params, if we're not in `-Zverbose-internals`.
-                || (!verbose && matches!(param.kind, GenericParamDefKind::Const { is_host_effect: true, .. }))
             })
             .count();
 
@@ -435,3 +422,73 @@ impl<'tcx> GenericPredicates<'tcx> {
         instantiated.spans.extend(self.predicates.iter().map(|(_, s)| s));
     }
 }
+
+/// `~const` bounds for a given item. This is represented using a struct much like
+/// `GenericPredicates`, where you can either choose to only instantiate the "own"
+/// bounds or all of the bounds including those from the parent. This distinction
+/// is necessary for code like `compare_method_predicate_entailment`.
+#[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)]
+pub struct ConstConditions<'tcx> {
+    pub parent: Option<DefId>,
+    pub predicates: &'tcx [(ty::PolyTraitRef<'tcx>, Span)],
+}
+
+impl<'tcx> ConstConditions<'tcx> {
+    pub fn instantiate(
+        self,
+        tcx: TyCtxt<'tcx>,
+        args: GenericArgsRef<'tcx>,
+    ) -> Vec<(ty::PolyTraitRef<'tcx>, Span)> {
+        let mut instantiated = vec![];
+        self.instantiate_into(tcx, &mut instantiated, args);
+        instantiated
+    }
+
+    pub fn instantiate_own(
+        self,
+        tcx: TyCtxt<'tcx>,
+        args: GenericArgsRef<'tcx>,
+    ) -> impl Iterator<Item = (ty::PolyTraitRef<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator
+    {
+        EarlyBinder::bind(self.predicates).iter_instantiated_copied(tcx, args)
+    }
+
+    pub fn instantiate_own_identity(
+        self,
+    ) -> impl Iterator<Item = (ty::PolyTraitRef<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator
+    {
+        EarlyBinder::bind(self.predicates).iter_identity_copied()
+    }
+
+    #[instrument(level = "debug", skip(self, tcx))]
+    fn instantiate_into(
+        self,
+        tcx: TyCtxt<'tcx>,
+        instantiated: &mut Vec<(ty::PolyTraitRef<'tcx>, Span)>,
+        args: GenericArgsRef<'tcx>,
+    ) {
+        if let Some(def_id) = self.parent {
+            tcx.const_conditions(def_id).instantiate_into(tcx, instantiated, args);
+        }
+        instantiated.extend(
+            self.predicates.iter().map(|&(p, s)| (EarlyBinder::bind(p).instantiate(tcx, args), s)),
+        );
+    }
+
+    pub fn instantiate_identity(self, tcx: TyCtxt<'tcx>) -> Vec<(ty::PolyTraitRef<'tcx>, Span)> {
+        let mut instantiated = vec![];
+        self.instantiate_identity_into(tcx, &mut instantiated);
+        instantiated
+    }
+
+    fn instantiate_identity_into(
+        self,
+        tcx: TyCtxt<'tcx>,
+        instantiated: &mut Vec<(ty::PolyTraitRef<'tcx>, Span)>,
+    ) {
+        if let Some(def_id) = self.parent {
+            tcx.const_conditions(def_id).instantiate_identity_into(tcx, instantiated);
+        }
+        instantiated.extend(self.predicates.iter().copied());
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index b1c5ff50fdc..61cb4322501 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -476,7 +476,6 @@ impl<'tcx> Instance<'tcx> {
     pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
         let args = GenericArgs::for_item(tcx, def_id, |param, _| match param.kind {
             ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
-            ty::GenericParamDefKind::Const { is_host_effect: true, .. } => tcx.consts.true_.into(),
             ty::GenericParamDefKind::Type { .. } => {
                 bug!("Instance::mono: {:?} has type parameters", def_id)
             }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index ed24fcc7eb8..85414764817 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -84,12 +84,13 @@ pub use self::parameterized::ParameterizedOverTcx;
 pub use self::pattern::{Pattern, PatternKind};
 pub use self::predicate::{
     AliasTerm, Clause, ClauseKind, CoercePredicate, ExistentialPredicate,
-    ExistentialPredicateStableCmpExt, ExistentialProjection, ExistentialTraitRef, NormalizesTo,
-    OutlivesPredicate, PolyCoercePredicate, PolyExistentialPredicate, PolyExistentialProjection,
-    PolyExistentialTraitRef, PolyProjectionPredicate, PolyRegionOutlivesPredicate,
-    PolySubtypePredicate, PolyTraitPredicate, PolyTraitRef, PolyTypeOutlivesPredicate, Predicate,
-    PredicateKind, ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef,
-    TraitPredicate, TraitRef, TypeOutlivesPredicate,
+    ExistentialPredicateStableCmpExt, ExistentialProjection, ExistentialTraitRef,
+    HostEffectPredicate, NormalizesTo, OutlivesPredicate, PolyCoercePredicate,
+    PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef,
+    PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
+    PolyTraitRef, PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
+    RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef, TraitPredicate, TraitRef,
+    TypeOutlivesPredicate,
 };
 pub use self::region::BoundRegionKind::*;
 pub use self::region::{
@@ -1998,10 +1999,75 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn is_const_fn_raw(self, def_id: DefId) -> bool {
         matches!(
             self.def_kind(def_id),
-            DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::Closure
+            DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Closure
         ) && self.constness(def_id) == hir::Constness::Const
     }
 
+    /// Whether this item is conditionally constant for the purposes of the
+    /// effects implementation.
+    ///
+    /// This roughly corresponds to all const functions and other callable
+    /// items, along with const impls and traits, and associated types within
+    /// those impls and traits.
+    pub fn is_conditionally_const(self, def_id: impl Into<DefId>) -> bool {
+        let def_id: DefId = def_id.into();
+        match self.def_kind(def_id) {
+            DefKind::Impl { of_trait: true } => {
+                self.constness(def_id) == hir::Constness::Const
+                    && self.is_const_trait(
+                        self.trait_id_of_impl(def_id)
+                            .expect("expected trait for trait implementation"),
+                    )
+            }
+            DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) => {
+                self.constness(def_id) == hir::Constness::Const
+            }
+            DefKind::Trait => self.is_const_trait(def_id),
+            DefKind::AssocTy | DefKind::AssocFn => {
+                let parent_def_id = self.parent(def_id);
+                match self.def_kind(parent_def_id) {
+                    DefKind::Impl { of_trait: false } => {
+                        self.constness(def_id) == hir::Constness::Const
+                    }
+                    DefKind::Impl { of_trait: true } | DefKind::Trait => {
+                        self.is_conditionally_const(parent_def_id)
+                    }
+                    _ => bug!("unexpected parent item of associated item: {parent_def_id:?}"),
+                }
+            }
+            DefKind::Closure | DefKind::OpaqueTy => {
+                // Closures and RPITs will eventually have const conditions
+                // for `~const` bounds.
+                false
+            }
+            DefKind::Ctor(_, CtorKind::Const)
+            | DefKind::Impl { of_trait: false }
+            | DefKind::Mod
+            | DefKind::Struct
+            | DefKind::Union
+            | DefKind::Enum
+            | DefKind::Variant
+            | DefKind::TyAlias
+            | DefKind::ForeignTy
+            | DefKind::TraitAlias
+            | DefKind::TyParam
+            | DefKind::Const
+            | DefKind::ConstParam
+            | DefKind::Static { .. }
+            | DefKind::AssocConst
+            | DefKind::Macro(_)
+            | DefKind::ExternCrate
+            | DefKind::Use
+            | DefKind::ForeignMod
+            | DefKind::AnonConst
+            | DefKind::InlineConst
+            | DefKind::Field
+            | DefKind::LifetimeParam
+            | DefKind::GlobalAsm
+            | DefKind::SyntheticCoroutineBody => false,
+        }
+    }
+
     #[inline]
     pub fn is_const_trait(self, def_id: DefId) -> bool {
         self.trait_def(def_id).constness == hir::Constness::Const
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 7e1255f606c..43bdce5b576 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -132,6 +132,7 @@ parameterized_over_tcx! {
     ty::Ty,
     ty::FnSig,
     ty::GenericPredicates,
+    ty::ConstConditions,
     ty::TraitRef,
     ty::Const,
     ty::Predicate,
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index d20cb368278..3ecaa3e22d3 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -19,6 +19,7 @@ pub type ExistentialPredicate<'tcx> = ir::ExistentialPredicate<TyCtxt<'tcx>>;
 pub type ExistentialTraitRef<'tcx> = ir::ExistentialTraitRef<TyCtxt<'tcx>>;
 pub type ExistentialProjection<'tcx> = ir::ExistentialProjection<TyCtxt<'tcx>>;
 pub type TraitPredicate<'tcx> = ir::TraitPredicate<TyCtxt<'tcx>>;
+pub type HostEffectPredicate<'tcx> = ir::HostEffectPredicate<TyCtxt<'tcx>>;
 pub type ClauseKind<'tcx> = ir::ClauseKind<TyCtxt<'tcx>>;
 pub type PredicateKind<'tcx> = ir::PredicateKind<TyCtxt<'tcx>>;
 pub type NormalizesTo<'tcx> = ir::NormalizesTo<TyCtxt<'tcx>>;
@@ -143,6 +144,7 @@ impl<'tcx> Predicate<'tcx> {
             | PredicateKind::AliasRelate(..)
             | PredicateKind::NormalizesTo(..) => false,
             PredicateKind::Clause(ClauseKind::Trait(_))
+            | PredicateKind::Clause(ClauseKind::HostEffect(..))
             | PredicateKind::Clause(ClauseKind::RegionOutlives(_))
             | PredicateKind::Clause(ClauseKind::TypeOutlives(_))
             | PredicateKind::Clause(ClauseKind::Projection(_))
@@ -644,6 +646,7 @@ impl<'tcx> Predicate<'tcx> {
         match predicate.skip_binder() {
             PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
             PredicateKind::Clause(ClauseKind::Projection(..))
+            | PredicateKind::Clause(ClauseKind::HostEffect(..))
             | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
             | PredicateKind::NormalizesTo(..)
             | PredicateKind::AliasRelate(..)
@@ -664,6 +667,7 @@ impl<'tcx> Predicate<'tcx> {
         match predicate.skip_binder() {
             PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
             PredicateKind::Clause(ClauseKind::Trait(..))
+            | PredicateKind::Clause(ClauseKind::HostEffect(..))
             | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
             | PredicateKind::NormalizesTo(..)
             | PredicateKind::AliasRelate(..)
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 10c3522eb0e..0248aad53e2 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -3075,6 +3075,15 @@ define_print! {
         p!(print(self.trait_ref.print_trait_sugared()))
     }
 
+    ty::HostEffectPredicate<'tcx> {
+        let constness = match self.host {
+            ty::HostPolarity::Const => { "const" }
+            ty::HostPolarity::Maybe => { "~const" }
+        };
+        p!(print(self.trait_ref.self_ty()), ": {constness} ");
+        p!(print(self.trait_ref.print_trait_sugared()))
+    }
+
     ty::TypeAndMut<'tcx> {
         p!(write("{}", self.mutbl.prefix_str()), print(self.ty))
     }
@@ -3087,6 +3096,7 @@ define_print! {
             ty::ClauseKind::RegionOutlives(predicate) => p!(print(predicate)),
             ty::ClauseKind::TypeOutlives(predicate) => p!(print(predicate)),
             ty::ClauseKind::Projection(predicate) => p!(print(predicate)),
+            ty::ClauseKind::HostEffect(predicate) => p!(print(predicate)),
             ty::ClauseKind::ConstArgHasType(ct, ty) => {
                 p!("the constant `", print(ct), "` has type `", print(ty), "`")
             },
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 06cbb6c9f1d..7fd7e463acf 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -17,10 +17,10 @@ use rustc_span::sym;
 use rustc_target::abi::{Float, Integer, IntegerType, Size};
 use rustc_target::spec::abi::Abi;
 use smallvec::{SmallVec, smallvec};
-use tracing::{debug, instrument, trace};
+use tracing::{debug, instrument};
 
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use crate::query::{IntoQueryParam, Providers};
+use crate::query::Providers;
 use crate::ty::layout::{FloatExt, IntegerExt};
 use crate::ty::{
     self, Asyncness, FallibleTypeFolder, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeFoldable,
@@ -865,48 +865,6 @@ impl<'tcx> TyCtxt<'tcx> {
             || self.extern_crate(key).is_some_and(|e| e.is_direct())
     }
 
-    /// Whether the item has a host effect param. This is different from `TyCtxt::is_const`,
-    /// because the item must also be "maybe const", and the crate where the item is
-    /// defined must also have the effects feature enabled.
-    pub fn has_host_param(self, def_id: impl IntoQueryParam<DefId>) -> bool {
-        self.generics_of(def_id).host_effect_index.is_some()
-    }
-
-    pub fn expected_host_effect_param_for_body(self, def_id: impl Into<DefId>) -> ty::Const<'tcx> {
-        let def_id = def_id.into();
-        // FIXME(effects): This is suspicious and should probably not be done,
-        // especially now that we enforce host effects and then properly handle
-        // effect vars during fallback.
-        let mut host_always_on = !self.features().effects()
-            || self.sess.opts.unstable_opts.unleash_the_miri_inside_of_you;
-
-        // Compute the constness required by the context.
-        let const_context = self.hir().body_const_context(def_id);
-
-        let kind = self.def_kind(def_id);
-        debug_assert_ne!(kind, DefKind::ConstParam);
-
-        if self.has_attr(def_id, sym::rustc_do_not_const_check) {
-            trace!("do not const check this context");
-            host_always_on = true;
-        }
-
-        match const_context {
-            _ if host_always_on => self.consts.true_,
-            Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { .. }) => {
-                self.consts.false_
-            }
-            Some(hir::ConstContext::ConstFn) => {
-                let host_idx = self
-                    .generics_of(def_id)
-                    .host_effect_index
-                    .expect("ConstContext::Maybe must have host effect param");
-                ty::GenericArgs::identity_for_item(self, def_id).const_at(host_idx)
-            }
-            None => self.consts.true_,
-        }
-    }
-
     /// Expand any [weak alias types][weak] contained within the given `value`.
     ///
     /// This should be used over other normalization routines in situations where
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index b4d084d4dff..e5c59d60822 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1522,7 +1522,6 @@ fn create_mono_items_for_default_impls<'tcx>(
     // it, to validate whether or not the impl is legal to instantiate at all.
     let only_region_params = |param: &ty::GenericParamDef, _: &_| match param.kind {
         GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
-        GenericParamDefKind::Const { is_host_effect: true, .. } => tcx.consts.true_.into(),
         GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
             unreachable!(
                 "`own_requires_monomorphization` check means that \
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index 23634d35c07..63608f9e856 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -431,7 +431,6 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
                     );
                     CanonicalVarKind::Const(self.delegate.universe_of_ct(vid).unwrap())
                 }
-                ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect,
                 ty::InferConst::Fresh(_) => todo!(),
             },
             ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs
index f2654f7534e..71c87714745 100644
--- a/compiler/rustc_next_trait_solver/src/resolve.rs
+++ b/compiler/rustc_next_trait_solver/src/resolve.rs
@@ -76,9 +76,6 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for EagerResolv
                     resolved
                 }
             }
-            ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => {
-                self.delegate.opportunistic_resolve_effect_var(vid)
-            }
             _ => {
                 if c.has_infer() {
                     c.super_fold_with(self)
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
index c9c0d6391fc..5e604a5d74f 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
@@ -270,11 +270,6 @@ where
         ecx: &mut EvalCtxt<'_, D>,
         goal: Goal<I, Self>,
     ) -> Vec<Candidate<I>>;
-
-    fn consider_builtin_effects_intersection_candidate(
-        ecx: &mut EvalCtxt<'_, D>,
-        goal: Goal<I, Self>,
-    ) -> Result<Candidate<I>, NoSolution>;
 }
 
 impl<D, I> EvalCtxt<'_, D>
@@ -481,9 +476,6 @@ where
                 Some(TraitSolverLangItem::TransmuteTrait) => {
                     G::consider_builtin_transmute_candidate(self, goal)
                 }
-                Some(TraitSolverLangItem::EffectsIntersection) => {
-                    G::consider_builtin_effects_intersection_candidate(self, goal)
-                }
                 _ => Err(NoSolution),
             }
         };
diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
new file mode 100644
index 00000000000..62b4bb0004c
--- /dev/null
+++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
@@ -0,0 +1,296 @@
+//! Dealing with host effect goals, i.e. enforcing the constness in
+//! `T: const Trait` or `T: ~const Trait`.
+
+use rustc_type_ir::fast_reject::DeepRejectCtxt;
+use rustc_type_ir::inherent::*;
+use rustc_type_ir::{self as ty, Interner};
+use tracing::instrument;
+
+use super::assembly::Candidate;
+use crate::delegate::SolverDelegate;
+use crate::solve::assembly::{self};
+use crate::solve::{
+    BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, NoSolution,
+    QueryResult,
+};
+
+impl<D, I> assembly::GoalKind<D> for ty::HostEffectPredicate<I>
+where
+    D: SolverDelegate<Interner = I>,
+    I: Interner,
+{
+    fn self_ty(self) -> I::Ty {
+        self.self_ty()
+    }
+
+    fn trait_ref(self, _: I) -> ty::TraitRef<I> {
+        self.trait_ref
+    }
+
+    fn with_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
+        self.with_self_ty(cx, self_ty)
+    }
+
+    fn trait_def_id(self, _: I) -> I::DefId {
+        self.def_id()
+    }
+
+    fn probe_and_match_goal_against_assumption(
+        ecx: &mut EvalCtxt<'_, D>,
+        source: rustc_type_ir::solve::CandidateSource<I>,
+        goal: Goal<I, Self>,
+        assumption: <I as Interner>::Clause,
+        then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        if let Some(host_clause) = assumption.as_host_effect_clause() {
+            if host_clause.def_id() == goal.predicate.def_id()
+                && host_clause.host().satisfies(goal.predicate.host)
+            {
+                if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
+                    goal.predicate.trait_ref.args,
+                    host_clause.skip_binder().trait_ref.args,
+                ) {
+                    return Err(NoSolution);
+                }
+
+                ecx.probe_trait_candidate(source).enter(|ecx| {
+                    let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause);
+                    ecx.eq(
+                        goal.param_env,
+                        goal.predicate.trait_ref,
+                        assumption_trait_pred.trait_ref,
+                    )?;
+                    then(ecx)
+                })
+            } else {
+                Err(NoSolution)
+            }
+        } else {
+            Err(NoSolution)
+        }
+    }
+
+    fn consider_impl_candidate(
+        ecx: &mut EvalCtxt<'_, D>,
+        goal: Goal<I, Self>,
+        impl_def_id: <I as Interner>::DefId,
+    ) -> Result<Candidate<I>, NoSolution> {
+        let cx = ecx.cx();
+
+        let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
+        if !DeepRejectCtxt::relate_rigid_infer(ecx.cx())
+            .args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
+        {
+            return Err(NoSolution);
+        }
+
+        let impl_polarity = cx.impl_polarity(impl_def_id);
+        match impl_polarity {
+            ty::ImplPolarity::Negative => return Err(NoSolution),
+            ty::ImplPolarity::Reservation => {
+                unimplemented!("reservation impl for const trait: {:?}", goal)
+            }
+            ty::ImplPolarity::Positive => {}
+        };
+
+        if !cx.is_const_impl(impl_def_id) {
+            return Err(NoSolution);
+        }
+
+        ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
+            let impl_args = ecx.fresh_args_for_item(impl_def_id);
+            ecx.record_impl_args(impl_args);
+            let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args);
+
+            ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
+            let where_clause_bounds = cx
+                .predicates_of(impl_def_id)
+                .iter_instantiated(cx, impl_args)
+                .map(|pred| goal.with(cx, pred));
+            ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
+
+            // For this impl to be `const`, we need to check its `~const` bounds too.
+            let const_conditions = cx
+                .const_conditions(impl_def_id)
+                .iter_instantiated(cx, impl_args)
+                .map(|bound_trait_ref| {
+                    goal.with(cx, bound_trait_ref.to_host_effect_clause(cx, goal.predicate.host))
+                });
+            ecx.add_goals(GoalSource::ImplWhereBound, const_conditions);
+
+            ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+        })
+    }
+
+    fn consider_error_guaranteed_candidate(
+        ecx: &mut EvalCtxt<'_, D>,
+        _guar: <I as Interner>::ErrorGuaranteed,
+    ) -> Result<Candidate<I>, NoSolution> {
+        ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
+            .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
+    }
+
+    fn consider_auto_trait_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        unreachable!("auto traits are never const")
+    }
+
+    fn consider_trait_alias_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        unreachable!("trait aliases are never const")
+    }
+
+    fn consider_builtin_sized_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        unreachable!("Sized is never const")
+    }
+
+    fn consider_builtin_copy_clone_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        todo!("Copy/Clone is not yet const")
+    }
+
+    fn consider_builtin_pointer_like_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        unreachable!("PointerLike is not const")
+    }
+
+    fn consider_builtin_fn_ptr_trait_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        todo!("Fn* are not yet const")
+    }
+
+    fn consider_builtin_fn_trait_candidates(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+        _kind: rustc_type_ir::ClosureKind,
+    ) -> Result<Candidate<I>, NoSolution> {
+        todo!("Fn* are not yet const")
+    }
+
+    fn consider_builtin_async_fn_trait_candidates(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+        _kind: rustc_type_ir::ClosureKind,
+    ) -> Result<Candidate<I>, NoSolution> {
+        todo!("AsyncFn* are not yet const")
+    }
+
+    fn consider_builtin_async_fn_kind_helper_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        unreachable!("AsyncFnKindHelper is not const")
+    }
+
+    fn consider_builtin_tuple_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        unreachable!("Tuple trait is not const")
+    }
+
+    fn consider_builtin_pointee_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        unreachable!("Pointee is not const")
+    }
+
+    fn consider_builtin_future_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        unreachable!("Future is not const")
+    }
+
+    fn consider_builtin_iterator_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        todo!("Iterator is not yet const")
+    }
+
+    fn consider_builtin_fused_iterator_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        unreachable!("FusedIterator is not const")
+    }
+
+    fn consider_builtin_async_iterator_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        unreachable!("AsyncIterator is not const")
+    }
+
+    fn consider_builtin_coroutine_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        unreachable!("Coroutine is not const")
+    }
+
+    fn consider_builtin_discriminant_kind_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        unreachable!("DiscriminantKind is not const")
+    }
+
+    fn consider_builtin_async_destruct_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        unreachable!("AsyncDestruct is not const")
+    }
+
+    fn consider_builtin_destruct_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        unreachable!("Destruct is not const")
+    }
+
+    fn consider_builtin_transmute_candidate(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Result<Candidate<I>, NoSolution> {
+        unreachable!("TransmuteFrom is not const")
+    }
+
+    fn consider_structural_builtin_unsize_candidates(
+        _ecx: &mut EvalCtxt<'_, D>,
+        _goal: Goal<I, Self>,
+    ) -> Vec<Candidate<I>> {
+        unreachable!("Unsize is not const")
+    }
+}
+
+impl<D, I> EvalCtxt<'_, D>
+where
+    D: SolverDelegate<Interner = I>,
+    I: Interner,
+{
+    #[instrument(level = "trace", skip(self))]
+    pub(super) fn compute_host_effect_goal(
+        &mut self,
+        goal: Goal<I, ty::HostEffectPredicate<I>>,
+    ) -> QueryResult<I> {
+        let candidates = self.assemble_and_evaluate_candidates(goal);
+        self.merge_candidates(candidates)
+    }
+}
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index 250174e033e..7608253882a 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -443,6 +443,9 @@ where
                 ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
                     self.compute_trait_goal(Goal { param_env, predicate })
                 }
+                ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
+                    self.compute_host_effect_goal(Goal { param_env, predicate })
+                }
                 ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) => {
                     self.compute_projection_goal(Goal { param_env, predicate })
                 }
diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs
index a475a58e483..6793779b205 100644
--- a/compiler/rustc_next_trait_solver/src/solve/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs
@@ -13,6 +13,7 @@
 
 mod alias_relate;
 mod assembly;
+mod effect_goals;
 mod eval_ctxt;
 pub mod inspect;
 mod normalizes_to;
@@ -182,12 +183,6 @@ where
         let (ct, ty) = goal.predicate;
 
         let ct_ty = match ct.kind() {
-            // FIXME: Ignore effect vars because canonicalization doesn't handle them correctly
-            // and if we stall on the var then we wind up creating ambiguity errors in a probe
-            // for this goal which contains an effect var. Which then ends up ICEing.
-            ty::ConstKind::Infer(ty::InferConst::EffectVar(_)) => {
-                return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
-            }
             ty::ConstKind::Infer(_) => {
                 return self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
             }
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
index 4d8b193ee49..c98fd853551 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
@@ -911,68 +911,6 @@ where
     ) -> Result<Candidate<I>, NoSolution> {
         panic!("`TransmuteFrom` does not have an associated type: {:?}", goal)
     }
-
-    fn consider_builtin_effects_intersection_candidate(
-        ecx: &mut EvalCtxt<'_, D>,
-        goal: Goal<I, Self>,
-    ) -> Result<Candidate<I>, NoSolution> {
-        let ty::Tuple(types) = goal.predicate.self_ty().kind() else {
-            return Err(NoSolution);
-        };
-
-        let cx = ecx.cx();
-
-        let mut first_non_maybe = None;
-        let mut non_maybe_count = 0;
-        for ty in types.iter() {
-            if !matches!(ty::EffectKind::try_from_ty(cx, ty), Some(ty::EffectKind::Maybe)) {
-                first_non_maybe.get_or_insert(ty);
-                non_maybe_count += 1;
-            }
-        }
-
-        match non_maybe_count {
-            0 => {
-                let ty = ty::EffectKind::Maybe.to_ty(cx);
-                ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
-                    ecx.instantiate_normalizes_to_term(goal, ty.into());
-                    ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
-                })
-            }
-            1 => {
-                let ty = first_non_maybe.unwrap();
-                ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
-                    ecx.instantiate_normalizes_to_term(goal, ty.into());
-                    ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
-                })
-            }
-            _ => {
-                let mut min = ty::EffectKind::Maybe;
-
-                for ty in types.iter() {
-                    // We can't find the intersection if the types used are generic.
-                    //
-                    // FIXME(effects): do we want to look at where clauses to get some
-                    // clue for the case where generic types are being used?
-                    let Some(kind) = ty::EffectKind::try_from_ty(cx, ty) else {
-                        return Err(NoSolution);
-                    };
-
-                    let Some(result) = ty::EffectKind::intersection(min, kind) else {
-                        return Err(NoSolution);
-                    };
-
-                    min = result;
-                }
-
-                let ty = min.to_ty(cx);
-                ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
-                    ecx.instantiate_normalizes_to_term(goal, ty.into());
-                    ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
-                })
-            }
-        }
-    }
 }
 
 impl<D, I> EvalCtxt<'_, D>
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index a8d6536baad..6b26f960286 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -719,47 +719,6 @@ where
             }
         })
     }
-
-    fn consider_builtin_effects_intersection_candidate(
-        ecx: &mut EvalCtxt<'_, D>,
-        goal: Goal<I, Self>,
-    ) -> Result<Candidate<I>, NoSolution> {
-        if goal.predicate.polarity != ty::PredicatePolarity::Positive {
-            return Err(NoSolution);
-        }
-
-        let ty::Tuple(types) = goal.predicate.self_ty().kind() else {
-            return Err(NoSolution);
-        };
-
-        let cx = ecx.cx();
-        let maybe_count = types
-            .iter()
-            .filter_map(|ty| ty::EffectKind::try_from_ty(cx, ty))
-            .filter(|&ty| ty == ty::EffectKind::Maybe)
-            .count();
-
-        // Don't do concrete type check unless there are more than one type that will influence the result.
-        // This would allow `(Maybe, T): Min` pass even if we know nothing about `T`.
-        if types.len() - maybe_count > 1 {
-            let mut min = ty::EffectKind::Maybe;
-
-            for ty in types.iter() {
-                let Some(kind) = ty::EffectKind::try_from_ty(ecx.cx(), ty) else {
-                    return Err(NoSolution);
-                };
-
-                let Some(result) = ty::EffectKind::intersection(min, kind) else {
-                    return Err(NoSolution);
-                };
-
-                min = result;
-            }
-        }
-
-        ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
-            .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
-    }
 }
 
 impl<D, I> EvalCtxt<'_, D>
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 7827975d3ca..05954143aee 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -137,6 +137,10 @@ where
             ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
                 self.visit_trait(trait_ref)
             }
+            ty::ClauseKind::HostEffect(pred) => {
+                try_visit!(self.visit_trait(pred.trait_ref));
+                pred.host.visit_with(self)
+            }
             ty::ClauseKind::Projection(ty::ProjectionPredicate {
                 projection_term: projection_ty,
                 term,
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index ef2ee9a166a..8f05f859c07 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -588,7 +588,6 @@ impl<'tcx> Stable<'tcx> for ty::Generics {
                 .has_late_bound_regions
                 .as_ref()
                 .map(|late_bound_regions| late_bound_regions.stable(tables)),
-            host_effect_index: self.host_effect_index,
         }
     }
 }
@@ -603,7 +602,7 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind {
             ty::GenericParamDefKind::Type { has_default, synthetic } => {
                 GenericParamDefKind::Type { has_default: *has_default, synthetic: *synthetic }
             }
-            ty::GenericParamDefKind::Const { has_default, is_host_effect: _, synthetic: _ } => {
+            ty::GenericParamDefKind::Const { has_default, synthetic: _ } => {
                 GenericParamDefKind::Const { has_default: *has_default }
             }
         }
@@ -690,6 +689,9 @@ impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> {
             ClauseKind::ConstEvaluatable(const_) => {
                 stable_mir::ty::ClauseKind::ConstEvaluatable(const_.stable(tables))
             }
+            ClauseKind::HostEffect(..) => {
+                todo!()
+            }
         }
     }
 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index aa05b88ea0c..bf5f948fe91 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -195,14 +195,6 @@ symbols! {
         Display,
         DoubleEndedIterator,
         Duration,
-        EffectsCompat,
-        EffectsIntersection,
-        EffectsIntersectionOutput,
-        EffectsMaybe,
-        EffectsNoRuntime,
-        EffectsRuntime,
-        EffectsTyCompat,
-        Effects__,
         Encodable,
         Encoder,
         Enumerate,
@@ -1737,7 +1729,6 @@ symbols! {
         rustc_reallocator,
         rustc_regions,
         rustc_reservation_impl,
-        rustc_runtime,
         rustc_safe_intrinsic,
         rustc_serialize,
         rustc_skip_during_method_dispatch,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 6ef64c3ed80..b7e2ed391cd 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -156,8 +156,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             (leaf_trait_predicate, &obligation)
                         };
 
-                        let (main_trait_predicate, leaf_trait_predicate, predicate_constness) = self.get_effects_trait_pred_override(main_trait_predicate, leaf_trait_predicate, span);
-
                         let main_trait_ref = main_trait_predicate.to_poly_trait_ref();
                         let leaf_trait_ref = leaf_trait_predicate.to_poly_trait_ref();
 
@@ -228,7 +226,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         let err_msg = self.get_standard_error_message(
                             main_trait_predicate,
                             message,
-                            predicate_constness,
+                            None,
                             append_const_msg,
                             post_message,
                         );
@@ -289,13 +287,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             );
                         }
 
-                        if tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Drop)
-                            && matches!(predicate_constness, Some(ty::BoundConstness::ConstIfConst | ty::BoundConstness::Const))
-                        {
-                            err.note("`~const Drop` was renamed to `~const Destruct`");
-                            err.note("See <https://github.com/rust-lang/rust/pull/94901> for more details");
-                        }
-
                         let explanation = get_explanation_based_on_obligation(
                             self.tcx,
                             &obligation,
@@ -541,6 +532,29 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         err
                     }
 
+                    ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
+                        // FIXME(effects): We should recompute the predicate with `~const`
+                        // if it's `const`, and if it holds, explain that this bound only
+                        // *conditionally* holds. If that fails, we should also do selection
+                        // to drill this down to an impl or built-in source, so we can
+                        // point at it and explain that while the trait *is* implemented,
+                        // that implementation is not const.
+                        let err_msg = self.get_standard_error_message(
+                            bound_predicate.rebind(ty::TraitPredicate {
+                                trait_ref: predicate.trait_ref,
+                                polarity: ty::PredicatePolarity::Positive,
+                            }),
+                            None,
+                            Some(match predicate.host {
+                                ty::HostPolarity::Maybe => ty::BoundConstness::ConstIfConst,
+                                ty::HostPolarity::Const => ty::BoundConstness::Const,
+                            }),
+                            None,
+                            String::new(),
+                        );
+                        struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg)
+                    }
+
                     ty::PredicateKind::Subtype(predicate) => {
                         // Errors for Subtype predicates show up as
                         // `FulfillmentErrorCode::SubtypeError`,
@@ -2374,52 +2388,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         })
     }
 
-    /// For effects predicates such as `<u32 as Add>::Effects: Compat<host>`, pretend that the
-    /// predicate that failed was `u32: Add`. Return the constness of such predicate to later
-    /// print as `u32: ~const Add`.
-    fn get_effects_trait_pred_override(
-        &self,
-        p: ty::PolyTraitPredicate<'tcx>,
-        leaf: ty::PolyTraitPredicate<'tcx>,
-        span: Span,
-    ) -> (ty::PolyTraitPredicate<'tcx>, ty::PolyTraitPredicate<'tcx>, Option<ty::BoundConstness>)
-    {
-        let trait_ref = p.to_poly_trait_ref();
-        if !self.tcx.is_lang_item(trait_ref.def_id(), LangItem::EffectsCompat) {
-            return (p, leaf, None);
-        }
-
-        let Some(ty::Alias(ty::AliasTyKind::Projection, projection)) =
-            trait_ref.self_ty().no_bound_vars().map(Ty::kind)
-        else {
-            return (p, leaf, None);
-        };
-
-        let constness = trait_ref.skip_binder().args.const_at(1);
-
-        let constness = if constness == self.tcx.consts.true_ || constness.is_ct_infer() {
-            None
-        } else if constness == self.tcx.consts.false_ {
-            Some(ty::BoundConstness::Const)
-        } else if matches!(constness.kind(), ty::ConstKind::Param(_)) {
-            Some(ty::BoundConstness::ConstIfConst)
-        } else {
-            self.dcx().span_bug(span, format!("Unknown constness argument: {constness:?}"));
-        };
-
-        let new_pred = p.map_bound(|mut trait_pred| {
-            trait_pred.trait_ref = projection.trait_ref(self.tcx);
-            trait_pred
-        });
-
-        let new_leaf = leaf.map_bound(|mut trait_pred| {
-            trait_pred.trait_ref = projection.trait_ref(self.tcx);
-            trait_pred
-        });
-
-        (new_pred, new_leaf, constness)
-    }
-
     fn add_tuple_trait_message(
         &self,
         obligation_cause_code: &ObligationCauseCode<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 12aeee0d02f..934fe9ec47c 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -806,7 +806,8 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                 | ty::PredicateKind::Subtype(..)
                 // FIXME(generic_const_exprs): you can absolutely add this as a where clauses
                 | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
-                | ty::PredicateKind::Coerce(..) => {}
+                | ty::PredicateKind::Coerce(..)
+                | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) => {}
                 ty::PredicateKind::Ambiguous => return false,
             };
         }
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index cc0450e0b05..a068f25fe35 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -245,6 +245,7 @@ fn predicate_references_self<'tcx>(
         | ty::ClauseKind::RegionOutlives(..)
         // FIXME(generic_const_exprs): this can mention `Self`
         | ty::ClauseKind::ConstEvaluatable(..)
+        | ty::ClauseKind::HostEffect(..)
          => None,
     }
 }
@@ -284,7 +285,8 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
         | ty::ClauseKind::Projection(_)
         | ty::ClauseKind::ConstArgHasType(_, _)
         | ty::ClauseKind::WellFormed(_)
-        | ty::ClauseKind::ConstEvaluatable(_) => false,
+        | ty::ClauseKind::ConstEvaluatable(_)
+        | ty::ClauseKind::HostEffect(..) => false,
     })
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 2bdeb00bdac..1754418156d 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -372,7 +372,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                 | ty::PredicateKind::Subtype(_)
                 | ty::PredicateKind::Coerce(_)
                 | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
-                | ty::PredicateKind::ConstEquate(..) => {
+                | ty::PredicateKind::ConstEquate(..)
+                // FIXME(effects): We may need to do this using the higher-ranked
+                // pred instead of just instantiating it with placeholders b/c of
+                // higher-ranked implied bound issues in the old solver.
+                | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) => {
                     let pred = ty::Binder::dummy(infcx.enter_forall_and_leak_universe(binder));
                     let mut obligations = PredicateObligations::with_capacity(1);
                     obligations.push(obligation.with(infcx.tcx, pred));
@@ -398,6 +402,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                     )
                 }
 
+                ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) => {
+                    ProcessResult::Changed(Default::default())
+                }
+
                 ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(data)) => {
                     if infcx.considering_regions {
                         infcx.region_outlives_predicate(&obligation.cause, Binder::dummy(data));
@@ -450,7 +458,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         ty::ConstKind::Infer(var) => {
                             let var = match var {
                                 ty::InferConst::Var(vid) => TyOrConstInferVar::Const(vid),
-                                ty::InferConst::EffectVar(vid) => TyOrConstInferVar::Effect(vid),
                                 ty::InferConst::Fresh(_) => {
                                     bug!("encountered fresh const in fulfill")
                                 }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index dfd0cab6905..c6e41e57f0c 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -96,6 +96,7 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
                 // FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
                 // if we ever support that
                 ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
+                | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..))
                 | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
                 | ty::PredicateKind::Subtype(..)
                 | ty::PredicateKind::Coerce(..)
@@ -200,6 +201,7 @@ pub fn compute_implied_outlives_bounds_compat_inner<'tcx>(
                 // FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
                 // if we ever support that
                 ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
+                | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..))
                 | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
                 | ty::PredicateKind::Subtype(..)
                 | ty::PredicateKind::Coerce(..)
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index c0122d3d552..47601b0c18d 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -546,7 +546,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
             }
             // Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396).
-            ty::FnDef(def_id, _args) => {
+            ty::FnDef(def_id, _) => {
                 let tcx = self.tcx();
                 if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
                     && tcx.codegen_fn_attrs(def_id).target_features.is_empty()
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index d5b1c5a97da..ec4114fd9d7 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -645,6 +645,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     self.evaluate_trait_predicate_recursively(previous_stack, obligation)
                 }
 
+                ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) => {
+                    // FIXME(effects): It should be relatively straightforward to implement
+                    // old trait solver support for `HostEffect` bounds; or at least basic
+                    // support for them.
+                    todo!()
+                }
+
                 ty::PredicateKind::Subtype(p) => {
                     let p = bound_predicate.rebind(p);
                     // Does this code ever run?
@@ -1821,8 +1828,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             |cand: ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_bound_vars();
 
         // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
-        // `DiscriminantKindCandidate`, `ConstDestructCandidate`
-        // to anything else.
+        // or `DiscriminantKindCandidate` to anything else.
         //
         // This is a fix for #53123 and prevents winnowing from accidentally extending the
         // lifetime of a variable.
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 8904a9a6858..437343b569c 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -170,6 +170,10 @@ pub fn clause_obligations<'tcx>(
         ty::ClauseKind::Trait(t) => {
             wf.compute_trait_pred(t, Elaborate::None);
         }
+        ty::ClauseKind::HostEffect(..) => {
+            // Technically the well-formedness of this predicate is implied by
+            // the corresponding trait predicate it should've been generated beside.
+        }
         ty::ClauseKind::RegionOutlives(..) => {}
         ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
             wf.compute(ty.into());
@@ -1021,6 +1025,7 @@ pub(crate) fn required_region_bounds<'tcx>(
                     }
                 }
                 ty::ClauseKind::Trait(_)
+                | ty::ClauseKind::HostEffect(..)
                 | ty::ClauseKind::RegionOutlives(_)
                 | ty::ClauseKind::Projection(_)
                 | ty::ClauseKind::ConstArgHasType(_, _)
diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs
index f01a12b0a00..3e2794f6489 100644
--- a/compiler/rustc_traits/src/normalize_erasing_regions.rs
+++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs
@@ -55,6 +55,7 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool {
         | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) => false,
         ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
         | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
+        | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..))
         | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
         | ty::PredicateKind::NormalizesTo(..)
         | ty::PredicateKind::AliasRelate(..)
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index a3210dd80d7..16fd28201c2 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -4,9 +4,8 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, ImplTraitInTraitData, Ty, TyCtxt};
+use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt};
 use rustc_middle::{bug, span_bug};
-use rustc_span::sym;
 use rustc_span::symbol::kw;
 
 pub(crate) fn provide(providers: &mut Providers) {
@@ -15,7 +14,6 @@ pub(crate) fn provide(providers: &mut Providers) {
         associated_item_def_ids,
         associated_items,
         associated_types_for_impl_traits_in_associated_fn,
-        associated_type_for_effects,
         associated_type_for_impl_trait_in_trait,
         impl_item_implementor_ids,
         ..*providers
@@ -46,8 +44,7 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] {
                                 )
                             })
                             .copied(),
-                    )
-                    .chain(tcx.associated_type_for_effects(def_id)),
+                    ),
             )
         }
         hir::ItemKind::Impl(impl_) => {
@@ -73,8 +70,7 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] {
                                 )
                             })
                             .copied()
-                    }))
-                    .chain(tcx.associated_type_for_effects(def_id)),
+                    })),
             )
         }
         _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
@@ -171,134 +167,6 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A
     }
 }
 
-/// Given an `def_id` of a trait or a trait impl:
-///
-/// If `def_id` is a trait that has `#[const_trait]`, then it synthesizes
-/// a new def id corresponding to a new associated type for the effects.
-///
-/// If `def_id` is an impl, then synthesize the associated type according
-/// to the constness of the impl.
-fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
-    // don't synthesize the associated type even if the user has written `const_trait`
-    // if the effects feature is disabled.
-    if !tcx.features().effects() {
-        return None;
-    }
-    let (feed, parent_did) = match tcx.def_kind(def_id) {
-        DefKind::Trait => {
-            let trait_def_id = def_id;
-            let attr = tcx.get_attr(def_id, sym::const_trait)?;
-
-            let span = attr.span;
-            let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, kw::Empty, DefKind::AssocTy);
-
-            let local_def_id = trait_assoc_ty.def_id();
-            let def_id = local_def_id.to_def_id();
-
-            // Copy span of the attribute.
-            trait_assoc_ty.def_ident_span(Some(span));
-
-            trait_assoc_ty.associated_item(ty::AssocItem {
-                name: kw::Empty,
-                kind: ty::AssocKind::Type,
-                def_id,
-                trait_item_def_id: None,
-                container: ty::TraitContainer,
-                fn_has_self_parameter: false,
-                opt_rpitit_info: None,
-                is_effects_desugaring: true,
-            });
-
-            // No default type
-            trait_assoc_ty.defaultness(hir::Defaultness::Default { has_value: false });
-
-            trait_assoc_ty.is_type_alias_impl_trait(false);
-
-            (trait_assoc_ty, trait_def_id)
-        }
-        DefKind::Impl { .. } => {
-            let impl_def_id = def_id;
-            let trait_id = tcx.trait_id_of_impl(def_id.to_def_id())?;
-
-            // first get the DefId of the assoc type on the trait, if there is not,
-            // then we don't need to generate it on the impl.
-            let trait_assoc_id = tcx.associated_type_for_effects(trait_id)?;
-
-            // FIXME(effects): span
-            let span = tcx.def_ident_span(def_id).unwrap();
-
-            let impl_assoc_ty = tcx.at(span).create_def(def_id, kw::Empty, DefKind::AssocTy);
-
-            let local_def_id = impl_assoc_ty.def_id();
-            let def_id = local_def_id.to_def_id();
-
-            impl_assoc_ty.def_ident_span(Some(span));
-
-            impl_assoc_ty.associated_item(ty::AssocItem {
-                name: kw::Empty,
-                kind: ty::AssocKind::Type,
-                def_id,
-                trait_item_def_id: Some(trait_assoc_id),
-                container: ty::ImplContainer,
-                fn_has_self_parameter: false,
-                opt_rpitit_info: None,
-                is_effects_desugaring: true,
-            });
-
-            // no default value.
-            impl_assoc_ty.defaultness(hir::Defaultness::Final);
-
-            // set the type of the associated type! If this is a const impl,
-            // we set to Maybe, otherwise we set to `Runtime`.
-            let type_def_id = if tcx.is_const_trait_impl_raw(impl_def_id.to_def_id()) {
-                tcx.require_lang_item(hir::LangItem::EffectsMaybe, Some(span))
-            } else {
-                tcx.require_lang_item(hir::LangItem::EffectsRuntime, Some(span))
-            };
-            // FIXME(effects): make impls use `Min` for their effect types
-            impl_assoc_ty.type_of(ty::EarlyBinder::bind(Ty::new_adt(
-                tcx,
-                tcx.adt_def(type_def_id),
-                ty::GenericArgs::empty(),
-            )));
-
-            (impl_assoc_ty, impl_def_id)
-        }
-        def_kind => bug!(
-            "associated_type_for_effects: {:?} should be Trait or Impl but is {:?}",
-            def_id,
-            def_kind
-        ),
-    };
-
-    feed.feed_hir();
-
-    // visibility is public.
-    feed.visibility(ty::Visibility::Public);
-
-    // Copy generics_of of the trait/impl, making the trait/impl as parent.
-    feed.generics_of({
-        let parent_generics = tcx.generics_of(parent_did);
-        let parent_count = parent_generics.parent_count + parent_generics.own_params.len();
-
-        ty::Generics {
-            parent: Some(parent_did.to_def_id()),
-            parent_count,
-            own_params: vec![],
-            param_def_id_to_index: parent_generics.param_def_id_to_index.clone(),
-            has_self: false,
-            has_late_bound_regions: None,
-            host_effect_index: parent_generics.host_effect_index,
-        }
-    });
-    feed.explicit_item_super_predicates(ty::EarlyBinder::bind(&[]));
-
-    // There are no inferred outlives for the synthesized associated type.
-    feed.inferred_outlives_of(&[]);
-
-    Some(feed.def_id().to_def_id())
-}
-
 /// Given an `fn_def_id` of a trait or a trait implementation:
 ///
 /// if `fn_def_id` is a function defined inside a trait, then it synthesizes
@@ -494,7 +362,6 @@ fn associated_type_for_impl_trait_in_impl(
             param_def_id_to_index,
             has_self: false,
             has_late_bound_regions: trait_assoc_generics.has_late_bound_regions,
-            host_effect_index: parent_generics.host_effect_index,
         }
     });
 
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 28a81b1b062..aa499995bcb 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -150,6 +150,16 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
         });
     }
 
+    // We extend the param-env of our item with the const conditions of the item,
+    // since we're allowed to assume `~const` bounds hold within the item itself.
+    if tcx.is_conditionally_const(def_id) {
+        predicates.extend(
+            tcx.const_conditions(def_id).instantiate_identity(tcx).into_iter().map(
+                |(trait_ref, _)| trait_ref.to_host_effect_clause(tcx, ty::HostPolarity::Maybe),
+            ),
+        );
+    }
+
     let local_did = def_id.as_local();
 
     let unnormalized_env =
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index 07cb8b037ec..3fb7d87bcc4 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -108,7 +108,6 @@ impl<I: Interner> CanonicalVarInfo<I> {
             CanonicalVarKind::PlaceholderRegion(..) => false,
             CanonicalVarKind::Const(_) => true,
             CanonicalVarKind::PlaceholderConst(_) => false,
-            CanonicalVarKind::Effect => true,
         }
     }
 
@@ -118,17 +117,15 @@ impl<I: Interner> CanonicalVarInfo<I> {
             CanonicalVarKind::Ty(_)
             | CanonicalVarKind::PlaceholderTy(_)
             | CanonicalVarKind::Const(_)
-            | CanonicalVarKind::PlaceholderConst(_)
-            | CanonicalVarKind::Effect => false,
+            | CanonicalVarKind::PlaceholderConst(_) => false,
         }
     }
 
     pub fn expect_placeholder_index(self) -> usize {
         match self.kind {
-            CanonicalVarKind::Ty(_)
-            | CanonicalVarKind::Region(_)
-            | CanonicalVarKind::Const(_)
-            | CanonicalVarKind::Effect => panic!("expected placeholder: {self:?}"),
+            CanonicalVarKind::Ty(_) | CanonicalVarKind::Region(_) | CanonicalVarKind::Const(_) => {
+                panic!("expected placeholder: {self:?}")
+            }
 
             CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.var().as_usize(),
             CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.var().as_usize(),
@@ -161,9 +158,6 @@ pub enum CanonicalVarKind<I: Interner> {
     /// Some kind of const inference variable.
     Const(UniverseIndex),
 
-    /// Effect variable `'?E`.
-    Effect,
-
     /// A "placeholder" that represents "any const".
     PlaceholderConst(I::PlaceholderConst),
 }
@@ -180,7 +174,6 @@ impl<I: Interner> CanonicalVarKind<I> {
             CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => {
                 UniverseIndex::ROOT
             }
-            CanonicalVarKind::Effect => UniverseIndex::ROOT,
         }
     }
 
@@ -205,8 +198,7 @@ impl<I: Interner> CanonicalVarKind<I> {
             CanonicalVarKind::PlaceholderConst(placeholder) => {
                 CanonicalVarKind::PlaceholderConst(placeholder.with_updated_universe(ui))
             }
-            CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float)
-            | CanonicalVarKind::Effect => {
+            CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => {
                 assert_eq!(ui, UniverseIndex::ROOT);
                 self
             }
@@ -311,10 +303,6 @@ impl<I: Interner> CanonicalVarValues<I> {
                             Region::new_anon_bound(cx, ty::INNERMOST, ty::BoundVar::from_usize(i))
                                 .into()
                         }
-                        CanonicalVarKind::Effect => {
-                            Const::new_anon_bound(cx, ty::INNERMOST, ty::BoundVar::from_usize(i))
-                                .into()
-                        }
                         CanonicalVarKind::Const(_) | CanonicalVarKind::PlaceholderConst(_) => {
                             Const::new_anon_bound(cx, ty::INNERMOST, ty::BoundVar::from_usize(i))
                                 .into()
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index 7a8c612057f..03dfe547ced 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -84,32 +84,12 @@ rustc_index::newtype_index! {
     pub struct ConstVid {}
 }
 
-rustc_index::newtype_index! {
-    /// An **effect** **v**ariable **ID**.
-    ///
-    /// Handling effect infer variables happens separately from const infer variables
-    /// because we do not want to reuse any of the const infer machinery. If we try to
-    /// relate an effect variable with a normal one, we would ICE, which can catch bugs
-    /// where we are not correctly using the effect var for an effect param. Fallback
-    /// is also implemented on top of having separate effect and normal const variables.
-    #[encodable]
-    #[orderable]
-    #[debug_format = "?{}e"]
-    #[gate_rustc_only]
-    pub struct EffectVid {}
-}
-
 /// An inference variable for a const, for use in const generics.
 #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
 #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
 pub enum InferConst {
     /// Infer the value of the const.
     Var(ConstVid),
-    /// Infer the value of the effect.
-    ///
-    /// For why this is separate from the `Var` variant above, see the
-    /// documentation on `EffectVid`.
-    EffectVar(EffectVid),
     /// A fresh const variable. See `infer::freshen` for more details.
     Fresh(u32),
 }
@@ -118,7 +98,6 @@ impl fmt::Debug for InferConst {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             InferConst::Var(var) => write!(f, "{var:?}"),
-            InferConst::EffectVar(var) => write!(f, "{var:?}"),
             InferConst::Fresh(var) => write!(f, "Fresh({var:?})"),
         }
     }
@@ -128,7 +107,7 @@ impl fmt::Debug for InferConst {
 impl<CTX> HashStable<CTX> for InferConst {
     fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
         match self {
-            InferConst::Var(_) | InferConst::EffectVar(_) => {
+            InferConst::Var(_) => {
                 panic!("const variables should not be hashed: {self:?}")
             }
             InferConst::Fresh(i) => i.hash_stable(hcx, hasher),
diff --git a/compiler/rustc_type_ir/src/effects.rs b/compiler/rustc_type_ir/src/effects.rs
deleted file mode 100644
index ab43533dd86..00000000000
--- a/compiler/rustc_type_ir/src/effects.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-use crate::Interner;
-use crate::inherent::*;
-use crate::lang_items::TraitSolverLangItem::{EffectsMaybe, EffectsNoRuntime, EffectsRuntime};
-
-#[derive(Clone, Copy, PartialEq, Eq)]
-pub enum EffectKind {
-    Maybe,
-    Runtime,
-    NoRuntime,
-}
-
-impl EffectKind {
-    pub fn try_from_def_id<I: Interner>(cx: I, def_id: I::DefId) -> Option<EffectKind> {
-        if cx.is_lang_item(def_id, EffectsMaybe) {
-            Some(EffectKind::Maybe)
-        } else if cx.is_lang_item(def_id, EffectsRuntime) {
-            Some(EffectKind::Runtime)
-        } else if cx.is_lang_item(def_id, EffectsNoRuntime) {
-            Some(EffectKind::NoRuntime)
-        } else {
-            None
-        }
-    }
-
-    pub fn to_def_id<I: Interner>(self, cx: I) -> I::DefId {
-        let lang_item = match self {
-            EffectKind::Maybe => EffectsMaybe,
-            EffectKind::NoRuntime => EffectsNoRuntime,
-            EffectKind::Runtime => EffectsRuntime,
-        };
-
-        cx.require_lang_item(lang_item)
-    }
-
-    pub fn try_from_ty<I: Interner>(cx: I, ty: I::Ty) -> Option<EffectKind> {
-        if let crate::Adt(def, _) = ty.kind() {
-            Self::try_from_def_id(cx, def.def_id())
-        } else {
-            None
-        }
-    }
-
-    pub fn to_ty<I: Interner>(self, cx: I) -> I::Ty {
-        I::Ty::new_adt(cx, cx.adt_def(self.to_def_id(cx)), Default::default())
-    }
-
-    /// Returns an intersection between two effect kinds. If one effect kind
-    /// is more permissive than the other (e.g. `Maybe` vs `Runtime`), this
-    /// returns the less permissive effect kind (`Runtime`).
-    pub fn intersection(a: Self, b: Self) -> Option<Self> {
-        use EffectKind::*;
-        match (a, b) {
-            (Maybe, x) | (x, Maybe) => Some(x),
-            (Runtime, Runtime) => Some(Runtime),
-            (NoRuntime, NoRuntime) => Some(NoRuntime),
-            (Runtime, NoRuntime) | (NoRuntime, Runtime) => None,
-        }
-    }
-}
diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs
index dac45ff2aba..72d392ecd7b 100644
--- a/compiler/rustc_type_ir/src/elaborate.rs
+++ b/compiler/rustc_type_ir/src/elaborate.rs
@@ -4,7 +4,6 @@ use smallvec::smallvec;
 
 use crate::data_structures::HashSet;
 use crate::inherent::*;
-use crate::lang_items::TraitSolverLangItem;
 use crate::outlives::{Component, push_outlives_components};
 use crate::{self as ty, Interner, Upcast as _};
 
@@ -130,70 +129,6 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
                     return;
                 }
 
-                // HACK(effects): The following code is required to get implied bounds for effects associated
-                // types to work with super traits.
-                //
-                // Suppose `data` is a trait predicate with the form `<T as Tr>::Fx: EffectsCompat<somebool>`
-                // and we know that `trait Tr: ~const SuperTr`, we need to elaborate this predicate into
-                // `<T as SuperTr>::Fx: EffectsCompat<somebool>`.
-                //
-                // Since the semantics for elaborating bounds about effects is equivalent to elaborating
-                // bounds about super traits (elaborate `T: Tr` into `T: SuperTr`), we place effects elaboration
-                // next to super trait elaboration.
-                if cx.is_lang_item(data.def_id(), TraitSolverLangItem::EffectsCompat)
-                    && matches!(self.mode, Filter::All)
-                {
-                    // first, ensure that the predicate we've got looks like a `<T as Tr>::Fx: EffectsCompat<somebool>`.
-                    if let ty::Alias(ty::AliasTyKind::Projection, alias_ty) = data.self_ty().kind()
-                    {
-                        // look for effects-level bounds that look like `<Self as Tr>::Fx: TyCompat<<Self as SuperTr>::Fx>`
-                        // on the trait, which is proof to us that `Tr: ~const SuperTr`. We're looking for bounds on the
-                        // associated trait, so we use `explicit_implied_predicates_of` since it gives us more than just
-                        // `Self: SuperTr` bounds.
-                        let bounds = cx.explicit_implied_predicates_of(cx.parent(alias_ty.def_id));
-
-                        // instantiate the implied bounds, so we get `<T as Tr>::Fx` and not `<Self as Tr>::Fx`.
-                        let elaborated = bounds.iter_instantiated(cx, alias_ty.args).filter_map(
-                            |(clause, _)| {
-                                let ty::ClauseKind::Trait(tycompat_bound) =
-                                    clause.kind().skip_binder()
-                                else {
-                                    return None;
-                                };
-                                if !cx.is_lang_item(
-                                    tycompat_bound.def_id(),
-                                    TraitSolverLangItem::EffectsTyCompat,
-                                ) {
-                                    return None;
-                                }
-
-                                // extract `<T as SuperTr>::Fx` from the `TyCompat` bound.
-                                let supertrait_effects_ty =
-                                    tycompat_bound.trait_ref.args.type_at(1);
-                                let ty::Alias(ty::AliasTyKind::Projection, supertrait_alias_ty) =
-                                    supertrait_effects_ty.kind()
-                                else {
-                                    return None;
-                                };
-
-                                // The self types (`T`) must be equal for `<T as Tr>::Fx` and `<T as SuperTr>::Fx`.
-                                if supertrait_alias_ty.self_ty() != alias_ty.self_ty() {
-                                    return None;
-                                };
-
-                                // replace the self type in the original bound `<T as Tr>::Fx: EffectsCompat<somebool>`
-                                // to the effects type of the super trait. (`<T as SuperTr>::Fx`)
-                                let elaborated_bound = data.with_self_ty(cx, supertrait_effects_ty);
-                                Some(
-                                    elaboratable
-                                        .child(bound_clause.rebind(elaborated_bound).upcast(cx)),
-                                )
-                            },
-                        );
-                        self.extend_deduped(elaborated);
-                    }
-                }
-
                 let map_to_child_clause =
                     |(index, (clause, span)): (usize, (I::Clause, I::Span))| {
                         elaboratable.child_with_derived_cause(
@@ -220,6 +155,16 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
                     ),
                 };
             }
+            // `T: ~const Trait` implies `T: ~const Supertrait`.
+            ty::ClauseKind::HostEffect(data) => self.extend_deduped(
+                cx.implied_const_bounds(data.def_id()).iter_identity().map(|trait_ref| {
+                    elaboratable.child(
+                        trait_ref
+                            .to_host_effect_clause(cx, data.host)
+                            .instantiate_supertrait(cx, bound_clause.rebind(data.trait_ref)),
+                    )
+                }),
+            ),
             ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => {
                 // We know that `T: 'a` for some type `T`. We can
                 // often elaborate this. For example, if we know that
diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs
index b9f5cde653e..7c6a3c65ebf 100644
--- a/compiler/rustc_type_ir/src/infer_ctxt.rs
+++ b/compiler/rustc_type_ir/src/infer_ctxt.rs
@@ -38,10 +38,6 @@ pub trait InferCtxtLike: Sized {
         &self,
         vid: ty::ConstVid,
     ) -> <Self::Interner as Interner>::Const;
-    fn opportunistic_resolve_effect_var(
-        &self,
-        vid: ty::EffectVid,
-    ) -> <Self::Interner as Interner>::Const;
     fn opportunistic_resolve_lt_var(
         &self,
         vid: ty::RegionVid,
@@ -71,7 +67,6 @@ pub trait InferCtxtLike: Sized {
     fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid);
     fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid);
     fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid);
-    fn equate_effect_vids_raw(&self, a: ty::EffectVid, b: ty::EffectVid);
 
     fn instantiate_ty_var_raw<R: PredicateEmittingRelation<Self>>(
         &self,
@@ -83,11 +78,6 @@ pub trait InferCtxtLike: Sized {
     ) -> RelateResult<Self::Interner, ()>;
     fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue);
     fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue);
-    fn instantiate_effect_var_raw(
-        &self,
-        vid: ty::EffectVid,
-        value: <Self::Interner as Interner>::Const,
-    );
     fn instantiate_const_var_raw<R: PredicateEmittingRelation<Self>>(
         &self,
         relation: &mut R,
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index 02ec29a7f3d..5af1aa2f8fa 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -468,6 +468,14 @@ pub trait Clause<I: Interner<Clause = Self>>:
             .transpose()
     }
 
+    fn as_host_effect_clause(self) -> Option<ty::Binder<I, ty::HostEffectPredicate<I>>> {
+        self.kind()
+            .map_bound(
+                |clause| if let ty::ClauseKind::HostEffect(t) = clause { Some(t) } else { None },
+            )
+            .transpose()
+    }
+
     fn as_projection_clause(self) -> Option<ty::Binder<I, ty::ProjectionPredicate<I>>> {
         self.kind()
             .map_bound(
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 4184e9e313f..6a8113b38b7 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -24,6 +24,7 @@ pub trait Interner:
     + IrPrint<ty::AliasTerm<Self>>
     + IrPrint<ty::TraitRef<Self>>
     + IrPrint<ty::TraitPredicate<Self>>
+    + IrPrint<ty::HostEffectPredicate<Self>>
     + IrPrint<ty::ExistentialTraitRef<Self>>
     + IrPrint<ty::ExistentialProjection<Self>>
     + IrPrint<ty::ProjectionPredicate<Self>>
@@ -228,6 +229,16 @@ pub trait Interner:
         def_id: Self::DefId,
     ) -> ty::EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>>;
 
+    fn is_const_impl(self, def_id: Self::DefId) -> bool;
+    fn const_conditions(
+        self,
+        def_id: Self::DefId,
+    ) -> ty::EarlyBinder<Self, impl IntoIterator<Item = ty::Binder<Self, ty::TraitRef<Self>>>>;
+    fn implied_const_bounds(
+        self,
+        def_id: Self::DefId,
+    ) -> ty::EarlyBinder<Self, impl IntoIterator<Item = ty::Binder<Self, ty::TraitRef<Self>>>>;
+
     fn has_target_features(self, def_id: Self::DefId) -> bool;
 
     fn require_lang_item(self, lang_item: TraitSolverLangItem) -> Self::DefId;
diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs
index d57d0816680..0c71f3a3df2 100644
--- a/compiler/rustc_type_ir/src/ir_print.rs
+++ b/compiler/rustc_type_ir/src/ir_print.rs
@@ -2,8 +2,8 @@ use std::fmt;
 
 use crate::{
     AliasTerm, AliasTy, Binder, CoercePredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
-    Interner, NormalizesTo, OutlivesPredicate, ProjectionPredicate, SubtypePredicate,
-    TraitPredicate, TraitRef,
+    HostEffectPredicate, Interner, NormalizesTo, OutlivesPredicate, ProjectionPredicate,
+    SubtypePredicate, TraitPredicate, TraitRef,
 };
 
 pub trait IrPrint<T> {
@@ -53,6 +53,7 @@ define_display_via_print!(
     NormalizesTo,
     SubtypePredicate,
     CoercePredicate,
+    HostEffectPredicate,
     AliasTy,
     AliasTerm,
     FnSig,
diff --git a/compiler/rustc_type_ir/src/lang_items.rs b/compiler/rustc_type_ir/src/lang_items.rs
index c680c844746..d6ca22a90a4 100644
--- a/compiler/rustc_type_ir/src/lang_items.rs
+++ b/compiler/rustc_type_ir/src/lang_items.rs
@@ -20,13 +20,6 @@ pub enum TraitSolverLangItem {
     Destruct,
     DiscriminantKind,
     DynMetadata,
-    EffectsCompat,
-    EffectsIntersection,
-    EffectsIntersectionOutput,
-    EffectsMaybe,
-    EffectsNoRuntime,
-    EffectsRuntime,
-    EffectsTyCompat,
     Fn,
     FnMut,
     FnOnce,
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 9e6d1f424ba..e7ca24178cb 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -43,7 +43,6 @@ mod macros;
 mod binder;
 mod canonical;
 mod const_kind;
-mod effects;
 mod flags;
 mod generic_arg;
 mod infer_ctxt;
@@ -67,7 +66,6 @@ pub use canonical::*;
 #[cfg(feature = "nightly")]
 pub use codec::*;
 pub use const_kind::*;
-pub use effects::*;
 pub use flags::*;
 pub use generic_arg::*;
 pub use infer_ctxt::*;
diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs
index e8ce39be3e5..c3164550348 100644
--- a/compiler/rustc_type_ir/src/predicate.rs
+++ b/compiler/rustc_type_ir/src/predicate.rs
@@ -111,6 +111,13 @@ impl<I: Interner> ty::Binder<I, TraitRef<I>> {
     pub fn def_id(&self) -> I::DefId {
         self.skip_binder().def_id
     }
+
+    pub fn to_host_effect_clause(self, cx: I, host: HostPolarity) -> I::Clause {
+        self.map_bound(|trait_ref| {
+            ty::ClauseKind::HostEffect(HostEffectPredicate { trait_ref, host })
+        })
+        .upcast(cx)
+    }
 }
 
 #[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
@@ -745,6 +752,64 @@ impl<I: Interner> fmt::Debug for NormalizesTo<I> {
     }
 }
 
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
+pub struct HostEffectPredicate<I: Interner> {
+    pub trait_ref: ty::TraitRef<I>,
+    pub host: HostPolarity,
+}
+
+impl<I: Interner> HostEffectPredicate<I> {
+    pub fn self_ty(self) -> I::Ty {
+        self.trait_ref.self_ty()
+    }
+
+    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
+        Self { trait_ref: self.trait_ref.with_self_ty(interner, self_ty), ..self }
+    }
+
+    pub fn def_id(self) -> I::DefId {
+        self.trait_ref.def_id
+    }
+}
+
+impl<I: Interner> ty::Binder<I, HostEffectPredicate<I>> {
+    pub fn def_id(self) -> I::DefId {
+        // Ok to skip binder since trait `DefId` does not care about regions.
+        self.skip_binder().def_id()
+    }
+
+    pub fn self_ty(self) -> ty::Binder<I, I::Ty> {
+        self.map_bound(|trait_ref| trait_ref.self_ty())
+    }
+
+    #[inline]
+    pub fn host(self) -> HostPolarity {
+        self.skip_binder().host
+    }
+}
+
+#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
+pub enum HostPolarity {
+    /// May be called in const environments if the callee is const.
+    Maybe,
+    /// Always allowed to be called in const environments.
+    Const,
+}
+
+impl HostPolarity {
+    pub fn satisfies(self, goal: HostPolarity) -> bool {
+        match (self, goal) {
+            (HostPolarity::Const, HostPolarity::Const | HostPolarity::Maybe) => true,
+            (HostPolarity::Maybe, HostPolarity::Maybe) => true,
+            (HostPolarity::Maybe, HostPolarity::Const) => false,
+        }
+    }
+}
+
 /// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates
 /// whether the `a` type is the type that we should label as "expected" when
 /// presenting user diagnostics.
diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs
index 46202dbb0f2..21f4456abd1 100644
--- a/compiler/rustc_type_ir/src/predicate_kind.rs
+++ b/compiler/rustc_type_ir/src/predicate_kind.rs
@@ -37,6 +37,12 @@ pub enum ClauseKind<I: Interner> {
 
     /// Constant initializer must evaluate successfully.
     ConstEvaluatable(I::Const),
+
+    /// Enforces the constness of the predicate we're calling. Like a projection
+    /// goal from a where clause, it's always going to be paired with a
+    /// corresponding trait clause; this just enforces the *constness* of that
+    /// implementation.
+    HostEffect(ty::HostEffectPredicate<I>),
 }
 
 #[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
@@ -110,6 +116,7 @@ impl<I: Interner> fmt::Debug for ClauseKind<I> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             ClauseKind::ConstArgHasType(ct, ty) => write!(f, "ConstArgHasType({ct:?}, {ty:?})"),
+            ClauseKind::HostEffect(data) => data.fmt(f),
             ClauseKind::Trait(a) => a.fmt(f),
             ClauseKind::RegionOutlives(pair) => pair.fmt(f),
             ClauseKind::TypeOutlives(pair) => pair.fmt(f),
diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs
index 60a953801a4..17a3912730f 100644
--- a/compiler/rustc_type_ir/src/relate/combine.rs
+++ b/compiler/rustc_type_ir/src/relate/combine.rs
@@ -179,23 +179,9 @@ where
             Ok(a)
         }
 
-        (
-            ty::ConstKind::Infer(ty::InferConst::EffectVar(a_vid)),
-            ty::ConstKind::Infer(ty::InferConst::EffectVar(b_vid)),
-        ) => {
-            infcx.equate_effect_vids_raw(a_vid, b_vid);
-            Ok(a)
-        }
-
         // All other cases of inference with other variables are errors.
-        (
-            ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)),
-            ty::ConstKind::Infer(_),
-        )
-        | (
-            ty::ConstKind::Infer(_),
-            ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)),
-        ) => {
+        (ty::ConstKind::Infer(ty::InferConst::Var(_)), ty::ConstKind::Infer(_))
+        | (ty::ConstKind::Infer(_), ty::ConstKind::Infer(ty::InferConst::Var(_))) => {
             panic!(
                 "tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}"
             )
@@ -211,16 +197,6 @@ where
             Ok(a)
         }
 
-        (ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)), _) => {
-            infcx.instantiate_effect_var_raw(vid, b);
-            Ok(b)
-        }
-
-        (_, ty::ConstKind::Infer(ty::InferConst::EffectVar(vid))) => {
-            infcx.instantiate_effect_var_raw(vid, a);
-            Ok(a)
-        }
-
         (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
             if infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver() =>
         {
diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs
index 9e6fbc8ea0c..8db1258b65f 100644
--- a/compiler/stable_mir/src/ty.rs
+++ b/compiler/stable_mir/src/ty.rs
@@ -1393,7 +1393,6 @@ pub struct Generics {
     pub param_def_id_to_index: Vec<(GenericDef, u32)>,
     pub has_self: bool,
     pub has_late_bound_regions: Option<Span>,
-    pub host_effect_index: Option<usize>,
 }
 
 #[derive(Clone, Debug, Eq, PartialEq, Serialize)]
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index aed6be4c627..1237fc82a17 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -1069,47 +1069,3 @@ pub trait FnPtr: Copy + Clone {
 pub macro SmartPointer($item:item) {
     /* compiler built-in */
 }
-
-// Support traits and types for the desugaring of const traits and
-// `~const` bounds. Not supposed to be used by anything other than
-// the compiler.
-#[doc(hidden)]
-#[unstable(
-    feature = "effect_types",
-    issue = "none",
-    reason = "internal module for implementing effects"
-)]
-#[allow(missing_debug_implementations)] // these unit structs don't need `Debug` impls.
-pub mod effects {
-    #[lang = "EffectsNoRuntime"]
-    pub struct NoRuntime;
-    #[lang = "EffectsMaybe"]
-    pub struct Maybe;
-    #[lang = "EffectsRuntime"]
-    pub struct Runtime;
-
-    #[lang = "EffectsCompat"]
-    pub trait Compat<#[rustc_runtime] const RUNTIME: bool> {}
-
-    impl Compat<false> for NoRuntime {}
-    impl Compat<true> for Runtime {}
-    impl<#[rustc_runtime] const RUNTIME: bool> Compat<RUNTIME> for Maybe {}
-
-    #[lang = "EffectsTyCompat"]
-    #[marker]
-    pub trait TyCompat<T: ?Sized> {}
-
-    impl<T: ?Sized> TyCompat<T> for T {}
-    impl<T: ?Sized> TyCompat<Maybe> for T {}
-
-    #[lang = "EffectsIntersection"]
-    pub trait Intersection {
-        #[lang = "EffectsIntersectionOutput"]
-        type Output: ?Sized;
-    }
-
-    // FIXME(effects): remove this after next trait solver lands
-    impl Intersection for () {
-        type Output = Maybe;
-    }
-}
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index d966f993104..31e4e79c00a 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -156,7 +156,7 @@ fn clean_param_env<'tcx>(
         .iter()
         .inspect(|param| {
             if cfg!(debug_assertions) {
-                debug_assert!(!param.is_anonymous_lifetime() && !param.is_host_effect());
+                debug_assert!(!param.is_anonymous_lifetime());
                 if let ty::GenericParamDefKind::Type { synthetic, .. } = param.kind {
                     debug_assert!(!synthetic && param.name != kw::SelfUpper);
                 }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index bf168809e28..81264b49dfd 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -368,7 +368,9 @@ pub(crate) fn clean_predicate<'tcx>(
         // FIXME(generic_const_exprs): should this do something?
         ty::ClauseKind::ConstEvaluatable(..)
         | ty::ClauseKind::WellFormed(..)
-        | ty::ClauseKind::ConstArgHasType(..) => None,
+        | ty::ClauseKind::ConstArgHasType(..)
+        // FIXME(effects): We can probably use this `HostEffect` pred to render `~const`.
+        | ty::ClauseKind::HostEffect(_) => None,
     }
 }
 
@@ -542,7 +544,7 @@ fn clean_generic_param_def(
                 synthetic,
             })
         }
-        ty::GenericParamDefKind::Const { has_default, synthetic, is_host_effect: _ } => {
+        ty::GenericParamDefKind::Const { has_default, synthetic } => {
             (def.name, GenericParamDefKind::Const {
                 ty: Box::new(clean_middle_ty(
                     ty::Binder::dummy(
@@ -617,7 +619,7 @@ fn clean_generic_param<'tcx>(
                 synthetic,
             })
         }
-        hir::GenericParamKind::Const { ty, default, synthetic, is_host_effect: _ } => {
+        hir::GenericParamKind::Const { ty, default, synthetic } => {
             (param.name.ident().name, GenericParamDefKind::Const {
                 ty: Box::new(clean_ty(ty, cx)),
                 default: default.map(|ct| {
@@ -797,7 +799,7 @@ fn clean_ty_generics<'tcx>(
                 }
                 true
             }
-            ty::GenericParamDefKind::Const { is_host_effect, .. } => !is_host_effect,
+            ty::GenericParamDefKind::Const { .. } => true,
         })
         .map(|param| clean_generic_param_def(param, ParamDefaults::Yes, cx))
         .collect();
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 6090de16d55..c8cb9267eb2 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1366,8 +1366,7 @@ impl GenericParamDef {
 
     pub(crate) fn is_synthetic_param(&self) -> bool {
         match self.kind {
-            GenericParamDefKind::Lifetime { .. } => false,
-            GenericParamDefKind::Const { synthetic: is_host_effect, .. } => is_host_effect,
+            GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
             GenericParamDefKind::Type { synthetic, .. } => synthetic,
         }
     }
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index fdf628b50fb..d3a545fe0b6 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -114,10 +114,6 @@ pub(crate) fn clean_middle_generic_args<'tcx>(
 
         // Elide internal host effect args.
         let param = generics.param_at(index, cx.tcx);
-        if param.is_host_effect() {
-            return None;
-        }
-
         let arg = ty::Binder::bind_with_vars(arg, bound_vars);
 
         // Elide arguments that coincide with their default.
diff --git a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
index 91ec120adbf..3021f21df12 100644
--- a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
@@ -207,16 +207,7 @@ fn path_segment_certainty(
             if cx.tcx.res_generics_def_id(path_segment.res).is_some() {
                 let generics = cx.tcx.generics_of(def_id);
 
-                let own_count = generics.own_params.len()
-                    - usize::from(generics.host_effect_index.is_some_and(|index| {
-                        // Check that the host index actually belongs to this resolution.
-                        // E.g. for `Add::add`, host_effect_index is `Some(2)`, but it's part of the parent `Add`
-                        // trait's generics.
-                        // Add params:      [Self#0, Rhs#1, host#2]   parent_count=0, count=3
-                        // Add::add params: []                        parent_count=3, count=3
-                        // (3..3).contains(&host_effect_index) => false
-                        (generics.parent_count..generics.count()).contains(&index)
-                    }));
+                let own_count = generics.own_params.len();
                 let lhs = if (parent_certainty.is_certain() || generics.parent_count == 0) && own_count == 0 {
                     Certainty::Certain(None)
                 } else {
@@ -310,8 +301,7 @@ fn type_is_inferable_from_arguments(cx: &LateContext<'_>, expr: &Expr<'_>) -> bo
 
     // Check that all type parameters appear in the functions input types.
     (0..(generics.parent_count + generics.own_params.len()) as u32).all(|index| {
-        Some(index as usize) == generics.host_effect_index
-            || fn_sig
+        fn_sig
                 .inputs()
                 .iter()
                 .any(|input_ty| contains_param(*input_ty.skip_binder(), index))
diff --git a/tests/crashes/118320.rs b/tests/crashes/118320.rs
deleted file mode 100644
index 093c58e1c05..00000000000
--- a/tests/crashes/118320.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//@ known-bug: #118320
-//@ edition:2021
-#![feature(const_trait_impl, effects, const_closures)]
-
-#[const_trait]
-trait Bar {
-    fn foo(&self);
-}
-
-impl Bar for () {}
-
-const FOO: () = {
-    (const || (()).foo())();
-};
diff --git a/tests/crashes/119924-6.rs b/tests/crashes/119924-6.rs
deleted file mode 100644
index f1cc9d29159..00000000000
--- a/tests/crashes/119924-6.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//@ known-bug: #119924
-//@ compile-flags: -Znext-solver
-#![feature(const_trait_impl, effects)]
-
-struct S;
-#[const_trait]
-trait Trait<const N: u32> {}
-
-const fn f<T: Trait<{
-    struct I<U: ~const Trait<0>>(U); // should've gotten rejected during AST validation
-    //~^ ICE no host param id for call in const yet no errors reported
-    0
-}>>() {}
-
-pub fn main() {}
diff --git a/tests/ui/const-generics/issues/issue-88119.stderr b/tests/ui/const-generics/issues/issue-88119.stderr
index 98bb8196810..a0ca33e38ef 100644
--- a/tests/ui/const-generics/issues/issue-88119.stderr
+++ b/tests/ui/const-generics/issues/issue-88119.stderr
@@ -11,30 +11,12 @@ error[E0284]: type annotations needed: cannot normalize `<&T as ConstName>::{con
    |
 LL | impl<T: ?Sized + ConstName> const ConstName for &T
    |                                                 ^^ cannot normalize `<&T as ConstName>::{constant#0}`
-   |
-note: required for `&T` to implement `ConstName`
-  --> $DIR/issue-88119.rs:19:35
-   |
-LL | impl<T: ?Sized + ConstName> const ConstName for &T
-   |                                   ^^^^^^^^^     ^^
-LL | where
-LL |     [(); name_len::<T>()]:,
-   |     --------------------- unsatisfied trait bound introduced here
 
 error[E0284]: type annotations needed: cannot normalize `<&mut T as ConstName>::{constant#0}`
   --> $DIR/issue-88119.rs:26:49
    |
 LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
    |                                                 ^^^^^^ cannot normalize `<&mut T as ConstName>::{constant#0}`
-   |
-note: required for `&mut T` to implement `ConstName`
-  --> $DIR/issue-88119.rs:26:35
-   |
-LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
-   |                                   ^^^^^^^^^     ^^^^^^
-LL | where
-LL |     [(); name_len::<T>()]:,
-   |     --------------------- unsatisfied trait bound introduced here
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/consts/const-block-const-bound.stderr b/tests/ui/consts/const-block-const-bound.stderr
index 42a42ae3938..8cb91d78f6c 100644
--- a/tests/ui/consts/const-block-const-bound.stderr
+++ b/tests/ui/consts/const-block-const-bound.stderr
@@ -4,6 +4,14 @@ error: `~const` can only be applied to `#[const_trait]` traits
 LL | const fn f<T: ~const Destruct>(x: T) {}
    |                      ^^^^^^^^
 
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const-block-const-bound.rs:8:22
+   |
+LL | const fn f<T: ~const Destruct>(x: T) {}
+   |                      ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0493]: destructor of `T` cannot be evaluated at compile-time
   --> $DIR/const-block-const-bound.rs:8:32
    |
@@ -12,6 +20,6 @@ LL | const fn f<T: ~const Destruct>(x: T) {}
    |                                |
    |                                the destructor for this type cannot be evaluated in constant functions
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0493`.
diff --git a/tests/ui/consts/const-try.rs b/tests/ui/consts/const-try.rs
index 9089dd70a26..2862b6ffb17 100644
--- a/tests/ui/consts/const-try.rs
+++ b/tests/ui/consts/const-try.rs
@@ -1,4 +1,4 @@
-//@ known-bug: #110395
+//@ compile-flags: -Znext-solver
 
 // Demonstrates what's needed to make use of `?` in const contexts.
 
@@ -14,12 +14,14 @@ struct TryMe;
 struct Error;
 
 impl const FromResidual<Error> for TryMe {
+    //~^ ERROR const `impl` for trait `FromResidual` which is not marked with `#[const_trait]`
     fn from_residual(residual: Error) -> Self {
         TryMe
     }
 }
 
 impl const Try for TryMe {
+    //~^ ERROR const `impl` for trait `Try` which is not marked with `#[const_trait]`
     type Output = ();
     type Residual = Error;
     fn from_output(output: Self::Output) -> Self {
diff --git a/tests/ui/consts/const-try.stderr b/tests/ui/consts/const-try.stderr
index 8afdd4e0d61..ba9da242107 100644
--- a/tests/ui/consts/const-try.stderr
+++ b/tests/ui/consts/const-try.stderr
@@ -1,8 +1,3 @@
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]`
   --> $DIR/const-try.rs:16:12
    |
@@ -13,7 +8,7 @@ LL | impl const FromResidual<Error> for TryMe {
    = note: adding a non-const method body in the future would be a breaking change
 
 error: const `impl` for trait `Try` which is not marked with `#[const_trait]`
-  --> $DIR/const-try.rs:22:12
+  --> $DIR/const-try.rs:23:12
    |
 LL | impl const Try for TryMe {
    |            ^^^
@@ -21,5 +16,5 @@ LL | impl const Try for TryMe {
    = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
    = note: adding a non-const method body in the future would be a breaking change
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/consts/constifconst-call-in-const-position.stderr b/tests/ui/consts/constifconst-call-in-const-position.stderr
index 7de10f0287b..2195cab3f4d 100644
--- a/tests/ui/consts/constifconst-call-in-const-position.stderr
+++ b/tests/ui/consts/constifconst-call-in-const-position.stderr
@@ -3,24 +3,12 @@ error: using `#![feature(effects)]` without enabling next trait solver globally
    = note: the next trait solver must be enabled globally for the effects feature to work correctly
    = help: use `-Znext-solver` to enable
 
-error[E0308]: mismatched types
+error[E0080]: evaluation of `foo::<()>::{constant#0}` failed
   --> $DIR/constifconst-call-in-const-position.rs:17:38
    |
 LL | const fn foo<T: ~const Tr>() -> [u8; T::a()] {
-   |                                      ^^^^^^ expected `false`, found `host`
-   |
-   = note: expected constant `false`
-              found constant `host`
-
-error[E0308]: mismatched types
-  --> $DIR/constifconst-call-in-const-position.rs:18:9
-   |
-LL |     [0; T::a()]
-   |         ^^^^^^ expected `false`, found `host`
-   |
-   = note: expected constant `false`
-              found constant `host`
+   |                                      ^^^^^^ calling non-const function `<() as Tr>::a`
 
-error: aborting due to 3 previous errors
+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 E0080`.
diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr
index 218c90f89a9..2b012432afd 100644
--- a/tests/ui/consts/fn_trait_refs.stderr
+++ b/tests/ui/consts/fn_trait_refs.stderr
@@ -31,6 +31,22 @@ LL |     T: ~const Fn<()> + ~const Destruct,
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/fn_trait_refs.rs:13:15
+   |
+LL |     T: ~const Fn<()> + ~const Destruct,
+   |               ^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/fn_trait_refs.rs:13:31
+   |
+LL |     T: ~const Fn<()> + ~const Destruct,
+   |                               ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `~const` can only be applied to `#[const_trait]` traits
   --> $DIR/fn_trait_refs.rs:20:15
    |
 LL |     T: ~const FnMut<()> + ~const Destruct,
@@ -51,10 +67,34 @@ LL |     T: ~const FnMut<()> + ~const Destruct,
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/fn_trait_refs.rs:20:15
+   |
+LL |     T: ~const FnMut<()> + ~const Destruct,
+   |               ^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/fn_trait_refs.rs:20:34
+   |
+LL |     T: ~const FnMut<()> + ~const Destruct,
+   |                                  ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/fn_trait_refs.rs:27:15
+   |
+LL |     T: ~const FnOnce<()>,
+   |               ^^^^^^^^^^
+
+error: `~const` can only be applied to `#[const_trait]` traits
   --> $DIR/fn_trait_refs.rs:27:15
    |
 LL |     T: ~const FnOnce<()>,
    |               ^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: `~const` can only be applied to `#[const_trait]` traits
   --> $DIR/fn_trait_refs.rs:27:15
@@ -85,6 +125,22 @@ LL |     T: ~const Fn<()> + ~const Destruct,
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/fn_trait_refs.rs:34:15
+   |
+LL |     T: ~const Fn<()> + ~const Destruct,
+   |               ^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/fn_trait_refs.rs:34:31
+   |
+LL |     T: ~const Fn<()> + ~const Destruct,
+   |                               ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `~const` can only be applied to `#[const_trait]` traits
   --> $DIR/fn_trait_refs.rs:48:15
    |
 LL |     T: ~const FnMut<()> + ~const Destruct,
@@ -104,6 +160,22 @@ LL |     T: ~const FnMut<()> + ~const Destruct,
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/fn_trait_refs.rs:48:15
+   |
+LL |     T: ~const FnMut<()> + ~const Destruct,
+   |               ^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/fn_trait_refs.rs:48:34
+   |
+LL |     T: ~const FnMut<()> + ~const Destruct,
+   |                                  ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0015]: cannot call non-const operator in constants
   --> $DIR/fn_trait_refs.rs:70:17
    |
@@ -212,7 +284,7 @@ LL | const fn test_fn_mut<T>(mut f: T) -> (T::Output, T::Output)
 LL | }
    | - value is dropped here
 
-error: aborting due to 25 previous errors
+error: aborting due to 34 previous errors
 
 Some errors have detailed explanations: E0015, E0493, E0635.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr
index 6c83eff4de0..59476f98603 100644
--- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr
+++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr
@@ -4,6 +4,14 @@ error: `~const` can only be applied to `#[const_trait]` traits
 LL |     const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
    |                                       ^^^^^^^^^^^^^
 
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/unstable-const-fn-in-libcore.rs:19:39
+   |
+LL |     const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
+   |                                       ^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/unstable-const-fn-in-libcore.rs:24:26
    |
@@ -38,7 +46,7 @@ LL |     const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
 LL |     }
    |     - value is dropped here
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0015, E0493.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/delegation/ice-issue-124347.rs b/tests/ui/delegation/ice-issue-124347.rs
index ee2bf9e33eb..b2b3c61a722 100644
--- a/tests/ui/delegation/ice-issue-124347.rs
+++ b/tests/ui/delegation/ice-issue-124347.rs
@@ -4,7 +4,7 @@
 // FIXME(fn_delegation): `recursive delegation` error should be emitted here
 trait Trait {
     reuse Trait::foo { &self.0 }
-    //~^ ERROR cycle detected when computing generics of `Trait::foo`
+    //~^ ERROR recursive delegation is not supported yet
 }
 
 reuse foo;
diff --git a/tests/ui/delegation/ice-issue-124347.stderr b/tests/ui/delegation/ice-issue-124347.stderr
index bd0bc970b94..74c4b5cd949 100644
--- a/tests/ui/delegation/ice-issue-124347.stderr
+++ b/tests/ui/delegation/ice-issue-124347.stderr
@@ -1,16 +1,8 @@
-error[E0391]: cycle detected when computing generics of `Trait::foo`
+error: recursive delegation is not supported yet
   --> $DIR/ice-issue-124347.rs:6:18
    |
 LL |     reuse Trait::foo { &self.0 }
-   |                  ^^^
-   |
-   = note: ...which immediately requires computing generics of `Trait::foo` again
-note: cycle used when inheriting delegation signature
-  --> $DIR/ice-issue-124347.rs:6:18
-   |
-LL |     reuse Trait::foo { &self.0 }
-   |                  ^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+   |                  ^^^ callee defined here
 
 error[E0391]: cycle detected when computing generics of `foo`
   --> $DIR/ice-issue-124347.rs:10:7
diff --git a/tests/ui/delegation/unsupported.rs b/tests/ui/delegation/unsupported.rs
index e57effff48d..56296db85a3 100644
--- a/tests/ui/delegation/unsupported.rs
+++ b/tests/ui/delegation/unsupported.rs
@@ -51,7 +51,7 @@ mod effects {
     }
 
     reuse Trait::foo;
-    //~^ ERROR delegation to a function with effect parameter is not supported yet
+    //~^ ERROR type annotations needed
 }
 
 fn main() {}
diff --git a/tests/ui/delegation/unsupported.stderr b/tests/ui/delegation/unsupported.stderr
index 6a627be3b64..1c79a603503 100644
--- a/tests/ui/delegation/unsupported.stderr
+++ b/tests/ui/delegation/unsupported.stderr
@@ -81,15 +81,15 @@ LL |         pub reuse to_reuse2::foo;
 LL |     reuse to_reuse1::foo;
    |                      ^^^
 
-error: delegation to a function with effect parameter is not supported yet
+error[E0283]: type annotations needed
   --> $DIR/unsupported.rs:53:18
    |
-LL |         fn foo();
-   |         --------- callee defined here
-...
 LL |     reuse Trait::foo;
-   |                  ^^^
+   |                  ^^^ cannot infer type
+   |
+   = note: cannot satisfy `_: effects::Trait`
 
 error: aborting due to 5 previous errors; 2 warnings emitted
 
-For more information about this error, try `rustc --explain E0391`.
+Some errors have detailed explanations: E0283, E0391.
+For more information about an error, try `rustc --explain E0283`.
diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr
index e0d193b5d40..f1e6207ed81 100644
--- a/tests/ui/impl-trait/normalize-tait-in-const.stderr
+++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr
@@ -10,6 +10,22 @@ error: `~const` can only be applied to `#[const_trait]` traits
 LL | const fn with_positive<F: for<'a> ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
    |                                                                     ^^^^^^^^
 
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/normalize-tait-in-const.rs:26:42
+   |
+LL | const fn with_positive<F: for<'a> ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
+   |                                          ^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/normalize-tait-in-const.rs:26:69
+   |
+LL | const fn with_positive<F: for<'a> ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
+   |                                                                     ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/normalize-tait-in-const.rs:27:5
    |
@@ -35,7 +51,7 @@ LL |     fun(filter_positive());
 LL | }
    | - value is dropped here
 
-error: aborting due to 4 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0015, E0493.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/specialization/const_trait_impl.stderr b/tests/ui/specialization/const_trait_impl.stderr
index 643f1de3e8d..746b08fa710 100644
--- a/tests/ui/specialization/const_trait_impl.stderr
+++ b/tests/ui/specialization/const_trait_impl.stderr
@@ -1,23 +1,3 @@
-error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/const_trait_impl.rs:6:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | pub unsafe trait Sup {
-LL |     fn foo() -> u32;
-   |           - expected 0 const parameters
-
-error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/const_trait_impl.rs:6:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | pub unsafe trait Sup {
-LL |     fn foo() -> u32;
-   |           - expected 0 const parameters
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
 error: `~const` can only be applied to `#[const_trait]` traits
   --> $DIR/const_trait_impl.rs:34:16
    |
@@ -36,34 +16,27 @@ error: `~const` can only be applied to `#[const_trait]` traits
 LL | impl<T: ~const Default + ~const Sub> const A for T {
    |                ^^^^^^^
 
-error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/const_trait_impl.rs:29:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | pub trait A {
-LL |     fn a() -> u32;
-   |         - expected 0 const parameters
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const_trait_impl.rs:40:16
+   |
+LL | impl<T: ~const Default + ~const Sup> const A for T {
+   |                ^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/const_trait_impl.rs:29:1
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const_trait_impl.rs:34:16
    |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | pub trait A {
-LL |     fn a() -> u32;
-   |         - expected 0 const parameters
+LL | impl<T: ~const Default> const A for T {
+   |                ^^^^^^^
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/const_trait_impl.rs:29:1
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const_trait_impl.rs:46:16
    |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | pub trait A {
-LL |     fn a() -> u32;
-   |         - expected 0 const parameters
+LL | impl<T: ~const Default + ~const Sub> const A for T {
+   |                ^^^^^^^
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
@@ -115,7 +88,6 @@ help: add `#![feature(effects)]` to the crate attributes to enable
 LL + #![feature(effects)]
    |
 
-error: aborting due to 12 previous errors
+error: aborting due to 10 previous errors
 
-Some errors have detailed explanations: E0015, E0049.
-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/assoc-type-const-bound-usage-0.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs
index 4399ae2d1be..5a54e8eec91 100644
--- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs
+++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Znext-solver
 //@ known-bug: unknown
 
 #![allow(incomplete_features)]
diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.stderr
index 8288c660ce7..35069a5a52f 100644
--- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.stderr
+++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.stderr
@@ -1,46 +1,15 @@
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
-error[E0277]: the trait bound `<T as Trait>::Assoc: Trait` is not satisfied
-  --> $DIR/assoc-type-const-bound-usage-0.rs:13:5
+error[E0271]: type mismatch resolving `<T as Trait>::Assoc == T`
+  --> $DIR/assoc-type-const-bound-usage-0.rs:14:5
    |
 LL |     T::Assoc::func()
-   |     ^^^^^^^^ the trait `Trait` is not implemented for `<T as Trait>::Assoc`
-   |
-note: required by a bound in `Trait::func`
-  --> $DIR/assoc-type-const-bound-usage-0.rs:6:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ required by this bound in `Trait::func`
-...
-LL |     fn func() -> i32;
-   |        ---- required by a bound in this associated function
-help: consider further restricting the associated type
-   |
-LL | const fn unqualified<T: ~const Trait>() -> i32 where <T as Trait>::Assoc: Trait {
-   |                                                ++++++++++++++++++++++++++++++++
+   |     ^^^^^^^^^^^^^^^^ types differ
 
-error[E0277]: the trait bound `<T as Trait>::Assoc: Trait` is not satisfied
-  --> $DIR/assoc-type-const-bound-usage-0.rs:17:5
+error[E0271]: type mismatch resolving `<T as Trait>::Assoc == T`
+  --> $DIR/assoc-type-const-bound-usage-0.rs:18:5
    |
 LL |     <T as Trait>::Assoc::func()
-   |     ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `<T as Trait>::Assoc`
-   |
-note: required by a bound in `Trait::func`
-  --> $DIR/assoc-type-const-bound-usage-0.rs:6:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ required by this bound in `Trait::func`
-...
-LL |     fn func() -> i32;
-   |        ---- required by a bound in this associated function
-help: consider further restricting the associated type
-   |
-LL | const fn qualified<T: ~const Trait>() -> i32 where <T as Trait>::Assoc: Trait {
-   |                                              ++++++++++++++++++++++++++++++++
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs
index 8a1bf75f87e..04ad94556c3 100644
--- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs
+++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs
@@ -1,5 +1,5 @@
+//@ compile-flags: -Znext-solver
 //@ known-bug: unknown
-// FIXME(effects)
 
 #![feature(const_trait_impl, effects, generic_const_exprs)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.stderr
index 0792d090321..ed9182c7334 100644
--- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.stderr
+++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.stderr
@@ -1,46 +1,23 @@
-error: using `#![feature(effects)]` without enabling next trait solver globally
+error: `-Znext-solver=globally` and `generic_const_exprs` are incompatible, using them at the same time is not allowed
+  --> $DIR/assoc-type-const-bound-usage-1.rs:4:39
    |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
+LL | #![feature(const_trait_impl, effects, generic_const_exprs)]
+   |                                       ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: remove one of these features
 
-error[E0277]: the trait bound `<T as Trait>::Assoc: Trait` is not satisfied
+error[E0271]: type mismatch resolving `<T as Trait>::Assoc == T`
   --> $DIR/assoc-type-const-bound-usage-1.rs:15:44
    |
 LL | fn unqualified<T: const Trait>() -> Type<{ T::Assoc::func() }> {
-   |                                            ^^^^^^^^ the trait `Trait` is not implemented for `<T as Trait>::Assoc`
-   |
-note: required by a bound in `Trait::func`
-  --> $DIR/assoc-type-const-bound-usage-1.rs:7:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ required by this bound in `Trait::func`
-...
-LL |     fn func() -> i32;
-   |        ---- required by a bound in this associated function
-help: consider further restricting the associated type
-   |
-LL | fn unqualified<T: const Trait>() -> Type<{ T::Assoc::func() }> where <T as Trait>::Assoc: Trait {
-   |                                                                ++++++++++++++++++++++++++++++++
+   |                                            ^^^^^^^^^^^^^^^^ types differ
 
-error[E0277]: the trait bound `<T as Trait>::Assoc: Trait` is not satisfied
+error[E0271]: type mismatch resolving `<T as Trait>::Assoc == T`
   --> $DIR/assoc-type-const-bound-usage-1.rs:19:42
    |
 LL | fn qualified<T: const Trait>() -> Type<{ <T as Trait>::Assoc::func() }> {
-   |                                          ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `<T as Trait>::Assoc`
-   |
-note: required by a bound in `Trait::func`
-  --> $DIR/assoc-type-const-bound-usage-1.rs:7:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ required by this bound in `Trait::func`
-...
-LL |     fn func() -> i32;
-   |        ---- required by a bound in this associated function
-help: consider further restricting the associated type
-   |
-LL | fn qualified<T: const Trait>() -> Type<{ <T as Trait>::Assoc::func() }> where <T as Trait>::Assoc: Trait {
-   |                                                                         ++++++++++++++++++++++++++++++++
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
 
 error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/const-traits/assoc-type.rs b/tests/ui/traits/const-traits/assoc-type.rs
index ea3cbabf302..a9394d90ed8 100644
--- a/tests/ui/traits/const-traits/assoc-type.rs
+++ b/tests/ui/traits/const-traits/assoc-type.rs
@@ -1,4 +1,5 @@
-// FIXME(effects): Replace `Add` with `std::ops::Add` once the latter a `#[const_trait]` again.
+//@ compile-flags: -Znext-solver
+
 #![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete
 
 #[const_trait]
@@ -33,7 +34,7 @@ trait Foo {
 
 impl const Foo for NonConstAdd {
     type Bar = NonConstAdd;
-    // FIXME(effects) ERROR the trait bound `NonConstAdd: ~const Add` is not satisfied
+    //~^ ERROR the trait bound `NonConstAdd: ~const Add` is not satisfied
 }
 
 #[const_trait]
diff --git a/tests/ui/traits/const-traits/assoc-type.stderr b/tests/ui/traits/const-traits/assoc-type.stderr
index c20b53c210f..5c77754200a 100644
--- a/tests/ui/traits/const-traits/assoc-type.stderr
+++ b/tests/ui/traits/const-traits/assoc-type.stderr
@@ -1,5 +1,5 @@
 warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/assoc-type.rs:2:30
+  --> $DIR/assoc-type.rs:3:30
    |
 LL | #![feature(const_trait_impl, effects)]
    |                              ^^^^^^^
@@ -7,10 +7,18 @@ LL | #![feature(const_trait_impl, effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
+error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied
+  --> $DIR/assoc-type.rs:36:16
    |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
+LL |     type Bar = NonConstAdd;
+   |                ^^^^^^^^^^^
+   |
+note: required by a bound in `Foo::Bar`
+  --> $DIR/assoc-type.rs:32:15
+   |
+LL |     type Bar: ~const Add;
+   |               ^^^^^^^^^^ required by this bound in `Foo::Bar`
 
 error: aborting due to 1 previous error; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/call-const-closure.rs b/tests/ui/traits/const-traits/call-const-closure.rs
new file mode 100644
index 00000000000..cbf3e6c3ac4
--- /dev/null
+++ b/tests/ui/traits/const-traits/call-const-closure.rs
@@ -0,0 +1,22 @@
+//@ compile-flags: -Znext-solver
+//@ edition:2021
+
+#![feature(const_trait_impl, effects, const_closures)]
+#![allow(incomplete_features)]
+
+#[const_trait]
+trait Bar {
+    fn foo(&self);
+}
+
+impl Bar for () {
+    fn foo(&self) {}
+}
+
+const FOO: () = {
+    (const || ().foo())();
+    //~^ ERROR the trait bound `(): ~const Bar` is not satisfied
+    // FIXME(effects): The constness environment for const closures is wrong.
+};
+
+fn main() {}
diff --git a/tests/ui/traits/const-traits/call-const-closure.stderr b/tests/ui/traits/const-traits/call-const-closure.stderr
new file mode 100644
index 00000000000..3fed67f5d08
--- /dev/null
+++ b/tests/ui/traits/const-traits/call-const-closure.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `(): ~const Bar` is not satisfied
+  --> $DIR/call-const-closure.rs:17:15
+   |
+LL |     (const || ().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/call-const-in-tilde-const.rs b/tests/ui/traits/const-traits/call-const-in-tilde-const.rs
new file mode 100644
index 00000000000..970ee93fd49
--- /dev/null
+++ b/tests/ui/traits/const-traits/call-const-in-tilde-const.rs
@@ -0,0 +1,14 @@
+//@ compile-flags: -Znext-solver
+#![feature(const_trait_impl, effects)]
+//~^ WARN the feature `effects` is incomplete
+
+#[const_trait] trait Foo {
+    fn foo();
+}
+
+const fn foo<T: ~const Foo>() {
+    const { T::foo() }
+    //~^ ERROR the trait bound `T: const Foo` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/traits/const-traits/call-const-in-tilde-const.stderr b/tests/ui/traits/const-traits/call-const-in-tilde-const.stderr
new file mode 100644
index 00000000000..49c310f1f75
--- /dev/null
+++ b/tests/ui/traits/const-traits/call-const-in-tilde-const.stderr
@@ -0,0 +1,18 @@
+warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/call-const-in-tilde-const.rs:2:30
+   |
+LL | #![feature(const_trait_impl, effects)]
+   |                              ^^^^^^^
+   |
+   = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `T: const Foo` is not satisfied
+  --> $DIR/call-const-in-tilde-const.rs:10:13
+   |
+LL |     const { T::foo() }
+   |             ^^^^^^^^
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr b/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr
index 5d2333d94fe..40a06af85ed 100644
--- a/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr
+++ b/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr
@@ -2,20 +2,7 @@ error[E0277]: the trait bound `u32: ~const Plus` is not satisfied
   --> $DIR/call-const-trait-method-fail.rs:27:5
    |
 LL |     a.plus(b)
-   |     ^ the trait `Plus` is not implemented for `u32`
-   |
-note: required by a bound in `Plus::plus`
-  --> $DIR/call-const-trait-method-fail.rs:5:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ required by this bound in `Plus::plus`
-LL | pub trait Plus {
-LL |     fn plus(self, rhs: Self) -> Self;
-   |        ---- required by a bound in this associated function
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | pub const fn add_u32(a: u32, b: u32) -> u32 where u32: Plus {
-   |                                             +++++++++++++++
+   |     ^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr b/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr
index bf455a714a3..c1cead54216 100644
--- a/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr
+++ b/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr
@@ -16,15 +16,6 @@ LL | impl const PartialEq for Int {
    = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
    = note: adding a non-const method body in the future would be a breaking change
 
-error[E0049]: method `plus` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/call-const-trait-method-pass.rs:24:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | pub trait Plus {
-LL |     fn plus(self, rhs: Self) -> Self;
-   |            - expected 0 const parameters
-
 error[E0015]: cannot call non-const operator in constants
   --> $DIR/call-const-trait-method-pass.rs:39:22
    |
@@ -73,7 +64,6 @@ help: add `#![feature(effects)]` to the crate attributes to enable
 LL + #![feature(effects)]
    |
 
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0015, E0049.
-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/call-generic-in-impl.stderr b/tests/ui/traits/const-traits/call-generic-in-impl.stderr
index 5cd274c6c5a..368c22675e7 100644
--- a/tests/ui/traits/const-traits/call-generic-in-impl.stderr
+++ b/tests/ui/traits/const-traits/call-generic-in-impl.stderr
@@ -4,14 +4,13 @@ error: `~const` can only be applied to `#[const_trait]` traits
 LL | impl<T: ~const PartialEq> const MyPartialEq for T {
    |                ^^^^^^^^^
 
-error[E0049]: method `eq` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/call-generic-in-impl.rs:5:1
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/call-generic-in-impl.rs:10:16
+   |
+LL | impl<T: ~const PartialEq> const MyPartialEq for T {
+   |                ^^^^^^^^^
    |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait MyPartialEq {
-LL |     fn eq(&self, other: &Self) -> bool;
-   |          - expected 0 const parameters
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0015]: cannot call non-const fn `<T as PartialEq>::eq` in constant functions
   --> $DIR/call-generic-in-impl.rs:12:9
@@ -27,5 +26,4 @@ LL + #![feature(effects)]
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0015, E0049.
-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/call-generic-method-chain.rs b/tests/ui/traits/const-traits/call-generic-method-chain.rs
index 9df694a02f5..e5baedae818 100644
--- a/tests/ui/traits/const-traits/call-generic-method-chain.rs
+++ b/tests/ui/traits/const-traits/call-generic-method-chain.rs
@@ -1,6 +1,7 @@
 //! Basic test for calling methods on generic type parameters in `const fn`.
 
 //@ known-bug: #110395
+//@ compile-flags: -Znext-solver
 // FIXME(effects) check-pass
 
 #![feature(const_trait_impl, effects)]
diff --git a/tests/ui/traits/const-traits/call-generic-method-chain.stderr b/tests/ui/traits/const-traits/call-generic-method-chain.stderr
index 57d57dfd5b9..62eed0f14f9 100644
--- a/tests/ui/traits/const-traits/call-generic-method-chain.stderr
+++ b/tests/ui/traits/const-traits/call-generic-method-chain.stderr
@@ -1,5 +1,5 @@
 warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/call-generic-method-chain.rs:6:30
+  --> $DIR/call-generic-method-chain.rs:7:30
    |
 LL | #![feature(const_trait_impl, effects)]
    |                              ^^^^^^^
@@ -7,13 +7,8 @@ LL | #![feature(const_trait_impl, effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
-  --> $DIR/call-generic-method-chain.rs:10:12
+  --> $DIR/call-generic-method-chain.rs:11:12
    |
 LL | impl const PartialEq for S {
    |            ^^^^^^^^^
@@ -22,16 +17,32 @@ LL | impl const PartialEq for S {
    = note: adding a non-const method body in the future would be a breaking change
 
 error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/call-generic-method-chain.rs:19:32
+  --> $DIR/call-generic-method-chain.rs:20:32
+   |
+LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
+   |                                ^^^^^^^^^
+
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/call-generic-method-chain.rs:20:32
    |
 LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
    |                                ^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/call-generic-method-chain.rs:23:40
+  --> $DIR/call-generic-method-chain.rs:24:40
    |
 LL | const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool {
    |                                        ^^^^^^^^^
 
-error: aborting due to 4 previous errors; 1 warning emitted
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/call-generic-method-chain.rs:24:40
+   |
+LL | const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool {
+   |                                        ^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 5 previous errors; 1 warning emitted
 
diff --git a/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs b/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs
index f46a34911f1..83a4bb25436 100644
--- a/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs
+++ b/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Znext-solver
 //@ known-bug: #110395
 // FIXME(effects) check-pass
 
diff --git a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr b/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr
index 0088ed2eb13..3f9dce919d0 100644
--- a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr
+++ b/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr
@@ -1,5 +1,5 @@
 warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/call-generic-method-dup-bound.rs:4:30
+  --> $DIR/call-generic-method-dup-bound.rs:5:30
    |
 LL | #![feature(const_trait_impl, effects)]
    |                              ^^^^^^^
@@ -7,13 +7,8 @@ LL | #![feature(const_trait_impl, effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
-  --> $DIR/call-generic-method-dup-bound.rs:8:12
+  --> $DIR/call-generic-method-dup-bound.rs:9:12
    |
 LL | impl const PartialEq for S {
    |            ^^^^^^^^^
@@ -22,16 +17,32 @@ LL | impl const PartialEq for S {
    = note: adding a non-const method body in the future would be a breaking change
 
 error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/call-generic-method-dup-bound.rs:19:44
+  --> $DIR/call-generic-method-dup-bound.rs:20:44
+   |
+LL | const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
+   |                                            ^^^^^^^^^
+
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/call-generic-method-dup-bound.rs:20:44
    |
 LL | const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
    |                                            ^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/call-generic-method-dup-bound.rs:26:37
+  --> $DIR/call-generic-method-dup-bound.rs:27:37
    |
 LL | const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool {
    |                                     ^^^^^^^^^
 
-error: aborting due to 4 previous errors; 1 warning emitted
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/call-generic-method-dup-bound.rs:27:37
+   |
+LL | const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool {
+   |                                     ^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 5 previous errors; 1 warning emitted
 
diff --git a/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr b/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr
index 68c9fc40010..06b99375cda 100644
--- a/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr
+++ b/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr
@@ -1,20 +1,8 @@
 error[E0277]: the trait bound `S: const Foo` is not satisfied
-  --> $DIR/call-generic-method-nonconst.rs:25:34
+  --> $DIR/call-generic-method-nonconst.rs:25:22
    |
 LL | pub const EQ: bool = equals_self(&S);
-   |                      ----------- ^^ the trait `Foo` is not implemented for `S`
-   |                      |
-   |                      required by a bound introduced by this call
-   |
-note: required by a bound in `equals_self`
-  --> $DIR/call-generic-method-nonconst.rs:18:25
-   |
-LL | const fn equals_self<T: ~const Foo>(t: &T) -> bool {
-   |                         ^^^^^^^^^^ required by this bound in `equals_self`
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | pub const EQ: bool where S: Foo = equals_self(&S);
-   |                    ++++++++++++
+   |                      ^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/const-traits/call-generic-method-pass.rs b/tests/ui/traits/const-traits/call-generic-method-pass.rs
index 413685d8b34..cbeeb2567dd 100644
--- a/tests/ui/traits/const-traits/call-generic-method-pass.rs
+++ b/tests/ui/traits/const-traits/call-generic-method-pass.rs
@@ -1,5 +1,6 @@
 //! Basic test for calling methods on generic type parameters in `const fn`.
 
+//@ compile-flags: -Znext-solver
 //@ known-bug: #110395
 // FIXME(effects) check-pass
 
diff --git a/tests/ui/traits/const-traits/call-generic-method-pass.stderr b/tests/ui/traits/const-traits/call-generic-method-pass.stderr
index 4a6100c3c1a..e35de48ed60 100644
--- a/tests/ui/traits/const-traits/call-generic-method-pass.stderr
+++ b/tests/ui/traits/const-traits/call-generic-method-pass.stderr
@@ -1,5 +1,5 @@
 warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/call-generic-method-pass.rs:6:30
+  --> $DIR/call-generic-method-pass.rs:7:30
    |
 LL | #![feature(const_trait_impl, effects)]
    |                              ^^^^^^^
@@ -7,13 +7,8 @@ LL | #![feature(const_trait_impl, effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
-  --> $DIR/call-generic-method-pass.rs:10:12
+  --> $DIR/call-generic-method-pass.rs:11:12
    |
 LL | impl const PartialEq for S {
    |            ^^^^^^^^^
@@ -22,10 +17,18 @@ LL | impl const PartialEq for S {
    = note: adding a non-const method body in the future would be a breaking change
 
 error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/call-generic-method-pass.rs:19:32
+  --> $DIR/call-generic-method-pass.rs:20:32
+   |
+LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
+   |                                ^^^^^^^^^
+
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/call-generic-method-pass.rs:20:32
    |
 LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
    |                                ^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 3 previous errors; 1 warning emitted
 
diff --git a/tests/ui/traits/const-traits/const-bound-in-host.rs b/tests/ui/traits/const-traits/const-bound-in-host.rs
new file mode 100644
index 00000000000..6fbc21074b6
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-bound-in-host.rs
@@ -0,0 +1,15 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+#![feature(const_trait_impl, effects)]
+//~^ WARN the feature `effects` is incomplete
+
+#[const_trait] trait Foo {
+    fn foo();
+}
+
+fn foo<T: const Foo>() {
+    const { T::foo() }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/const-traits/const-bound-in-host.stderr b/tests/ui/traits/const-traits/const-bound-in-host.stderr
new file mode 100644
index 00000000000..b815f745ee8
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-bound-in-host.stderr
@@ -0,0 +1,11 @@
+warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/const-bound-in-host.rs:4:30
+   |
+LL | #![feature(const_trait_impl, effects)]
+   |                              ^^^^^^^
+   |
+   = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs b/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs
index 099cf0b00d3..7c3e2af1797 100644
--- a/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs
+++ b/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs
@@ -1,3 +1,5 @@
+//@ compile-flags: -Znext-solver
+
 #![allow(incomplete_features)]
 #![feature(const_trait_impl, effects)]
 
diff --git a/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr b/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr
index b5d9b1fff8a..ae1260ffab7 100644
--- a/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr
+++ b/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr
@@ -1,31 +1,26 @@
 error: `~const` is not allowed here
-  --> $DIR/const-bound-on-not-const-associated-fn.rs:10:40
+  --> $DIR/const-bound-on-not-const-associated-fn.rs:12:40
    |
 LL |     fn do_something_else() where Self: ~const MyTrait;
    |                                        ^^^^^^
    |
 note: this function is not `const`, so it cannot have `~const` trait bounds
-  --> $DIR/const-bound-on-not-const-associated-fn.rs:10:8
+  --> $DIR/const-bound-on-not-const-associated-fn.rs:12:8
    |
 LL |     fn do_something_else() where Self: ~const MyTrait;
    |        ^^^^^^^^^^^^^^^^^
 
 error: `~const` is not allowed here
-  --> $DIR/const-bound-on-not-const-associated-fn.rs:21:32
+  --> $DIR/const-bound-on-not-const-associated-fn.rs:23:32
    |
 LL |     pub fn foo(&self) where T: ~const MyTrait {
    |                                ^^^^^^
    |
 note: this function is not `const`, so it cannot have `~const` trait bounds
-  --> $DIR/const-bound-on-not-const-associated-fn.rs:21:12
+  --> $DIR/const-bound-on-not-const-associated-fn.rs:23:12
    |
 LL |     pub fn foo(&self) where T: ~const MyTrait {
    |            ^^^
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/traits/const-traits/const-bounds-non-const-trait.rs b/tests/ui/traits/const-traits/const-bounds-non-const-trait.rs
index db446f8bc2e..d51d231b8a9 100644
--- a/tests/ui/traits/const-traits/const-bounds-non-const-trait.rs
+++ b/tests/ui/traits/const-traits/const-bounds-non-const-trait.rs
@@ -5,6 +5,7 @@ trait NonConst {}
 
 const fn perform<T: ~const NonConst>() {}
 //~^ ERROR `~const` can only be applied to `#[const_trait]` traits
+//~| ERROR `~const` can only be applied to `#[const_trait]` traits
 
 fn operate<T: const NonConst>() {}
 //~^ ERROR `const` can only be applied to `#[const_trait]` traits
diff --git a/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr b/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr
index e1a85fc5414..6c3c11c6a47 100644
--- a/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr
+++ b/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr
@@ -18,11 +18,19 @@ error: `~const` can only be applied to `#[const_trait]` traits
 LL | const fn perform<T: ~const NonConst>() {}
    |                            ^^^^^^^^
 
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const-bounds-non-const-trait.rs:6:28
+   |
+LL | const fn perform<T: ~const NonConst>() {}
+   |                            ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error: `const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-bounds-non-const-trait.rs:9:21
+  --> $DIR/const-bounds-non-const-trait.rs:10:21
    |
 LL | fn operate<T: const NonConst>() {}
    |                     ^^^^^^^^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 4 previous errors; 1 warning emitted
 
diff --git a/tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs b/tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs
index a1710e65252..7f9b38b8207 100644
--- a/tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs
+++ b/tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs
@@ -1,3 +1,5 @@
+//@ compile-flags: -Znext-solver
+
 #![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete
 
 struct S;
diff --git a/tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr b/tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr
index 49cd1725c8c..ba12854987e 100644
--- a/tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr
+++ b/tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr
@@ -1,5 +1,5 @@
 warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-check-fns-in-const-impl.rs:1:30
+  --> $DIR/const-check-fns-in-const-impl.rs:3:30
    |
 LL | #![feature(const_trait_impl, effects)]
    |                              ^^^^^^^
@@ -7,19 +7,14 @@ LL | #![feature(const_trait_impl, effects)]
    = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error[E0015]: cannot call non-const fn `non_const` in constant functions
-  --> $DIR/const-check-fns-in-const-impl.rs:12:16
+  --> $DIR/const-check-fns-in-const-impl.rs:14:16
    |
 LL |     fn foo() { non_const() }
    |                ^^^^^^^^^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 1 previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr
index 507ceaae2ea..4e6707bba51 100644
--- a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr
+++ b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr
@@ -1,17 +1,16 @@
-error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/const-closure-trait-method-fail.rs:5:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Tr {
-LL |     fn a(self) -> i32;
-   |         - expected 0 const parameters
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const-closure-trait-method-fail.rs:14:39
+   |
+LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
+   |                                       ^^^^^^^^^^^^^^^^^
 
 error: `~const` can only be applied to `#[const_trait]` traits
   --> $DIR/const-closure-trait-method-fail.rs:14:39
    |
 LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
    |                                       ^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/const-closure-trait-method-fail.rs:15:5
@@ -31,5 +30,4 @@ LL + #![feature(effects)]
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0015, E0049.
-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-closure-trait-method.stderr b/tests/ui/traits/const-traits/const-closure-trait-method.stderr
index 2a54cd5d7f6..0f0cd73cc10 100644
--- a/tests/ui/traits/const-traits/const-closure-trait-method.stderr
+++ b/tests/ui/traits/const-traits/const-closure-trait-method.stderr
@@ -1,17 +1,16 @@
-error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/const-closure-trait-method.rs:5:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Tr {
-LL |     fn a(self) -> i32;
-   |         - expected 0 const parameters
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const-closure-trait-method.rs:14:39
+   |
+LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
+   |                                       ^^^^^^^^^^^^^^^^^
 
 error: `~const` can only be applied to `#[const_trait]` traits
   --> $DIR/const-closure-trait-method.rs:14:39
    |
 LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
    |                                       ^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/const-closure-trait-method.rs:15:5
@@ -31,5 +30,4 @@ LL + #![feature(effects)]
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0015, E0049.
-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-closures.stderr b/tests/ui/traits/const-traits/const-closures.stderr
index a0f05325389..4d354cb281f 100644
--- a/tests/ui/traits/const-traits/const-closures.stderr
+++ b/tests/ui/traits/const-traits/const-closures.stderr
@@ -17,11 +17,43 @@ LL |         F: ~const Fn() -> u8,
    |                   ^^^^^^^^^^
 
 error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const-closures.rs:8:19
+   |
+LL |         F: ~const FnOnce() -> u8,
+   |                   ^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const-closures.rs:9:19
+   |
+LL |         F: ~const FnMut() -> u8,
+   |                   ^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const-closures.rs:10:19
+   |
+LL |         F: ~const Fn() -> u8,
+   |                   ^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `~const` can only be applied to `#[const_trait]` traits
   --> $DIR/const-closures.rs:23:27
    |
 LL | const fn answer<F: ~const Fn() -> u8>(f: &F) -> u8 {
    |                           ^^^^^^^^^^
 
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const-closures.rs:23:27
+   |
+LL | const fn answer<F: ~const Fn() -> u8>(f: &F) -> u8 {
+   |                           ^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/const-closures.rs:24:5
    |
@@ -70,6 +102,6 @@ help: add `#![feature(effects)]` to the crate attributes to enable
 LL + #![feature(effects)]
    |
 
-error: aborting due to 7 previous errors
+error: aborting due to 11 previous errors
 
 For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/const-default-method-bodies.stderr b/tests/ui/traits/const-traits/const-default-method-bodies.stderr
index 0809d9c1e1d..071eaf49541 100644
--- a/tests/ui/traits/const-traits/const-default-method-bodies.stderr
+++ b/tests/ui/traits/const-traits/const-default-method-bodies.stderr
@@ -1,21 +1,8 @@
 error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied
-  --> $DIR/const-default-method-bodies.rs:26:18
+  --> $DIR/const-default-method-bodies.rs:26:5
    |
 LL |     NonConstImpl.a();
-   |                  ^ the trait `ConstDefaultFn` is not implemented for `NonConstImpl`
-   |
-note: required by a bound in `ConstDefaultFn::a`
-  --> $DIR/const-default-method-bodies.rs:5:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ required by this bound in `ConstDefaultFn::a`
-...
-LL |     fn a(self) {
-   |        - required by a bound in this associated function
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | const fn test() where NonConstImpl: ConstDefaultFn {
-   |                 ++++++++++++++++++++++++++++++++++
+   |     ^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/const-traits/const-drop-bound.stderr b/tests/ui/traits/const-traits/const-drop-bound.stderr
index be197006f02..d94b0542324 100644
--- a/tests/ui/traits/const-traits/const-drop-bound.stderr
+++ b/tests/ui/traits/const-traits/const-drop-bound.stderr
@@ -5,6 +5,14 @@ LL | const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Destruct
    |                                                                    ^^^^^^^^
 
 error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const-drop-bound.rs:9:68
+   |
+LL | const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Destruct {
+   |                                                                    ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `~const` can only be applied to `#[const_trait]` traits
   --> $DIR/const-drop-bound.rs:20:15
    |
 LL |     T: ~const Destruct,
@@ -16,12 +24,28 @@ error: `~const` can only be applied to `#[const_trait]` traits
 LL |     E: ~const Destruct,
    |               ^^^^^^^^
 
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const-drop-bound.rs:20:15
+   |
+LL |     T: ~const Destruct,
+   |               ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const-drop-bound.rs:21:15
+   |
+LL |     E: ~const Destruct,
+   |               ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0493]: destructor of `E` cannot be evaluated at compile-time
   --> $DIR/const-drop-bound.rs:12:13
    |
 LL |         Err(_e) => None,
    |             ^^ the destructor for this type cannot be evaluated in constant functions
 
-error: aborting due to 4 previous errors
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0493`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stderr
index faf24c6d911..27e8053c969 100644
--- a/tests/ui/traits/const-traits/const-drop-fail-2.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail-2.stderr
@@ -13,6 +13,14 @@ error: `~const` can only be applied to `#[const_trait]` traits
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                          ^^^^^^^^
 
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const-drop-fail-2.rs:20:26
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                          ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0493]: destructor of `T` cannot be evaluated at compile-time
   --> $DIR/const-drop-fail-2.rs:20:36
    |
@@ -33,7 +41,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
 LL + #![feature(effects)]
    |
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0015, E0493.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.precise.stderr
index 3d400bf0158..bde13b4d6cf 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail.precise.stderr
@@ -13,6 +13,14 @@ error: `~const` can only be applied to `#[const_trait]` traits
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                          ^^^^^^^^
 
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const-drop-fail.rs:23:26
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                          ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0493]: destructor of `T` cannot be evaluated at compile-time
   --> $DIR/const-drop-fail.rs:23:36
    |
@@ -71,7 +79,7 @@ LL | | }
    | |_- in this macro invocation
    = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0080, E0493.
 For more information about an error, try `rustc --explain E0080`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.stock.stderr
index fd0f6d02684..064ffacca42 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail.stock.stderr
@@ -13,6 +13,14 @@ error: `~const` can only be applied to `#[const_trait]` traits
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                          ^^^^^^^^
 
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const-drop-fail.rs:23:26
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                          ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0493]: destructor of `T` cannot be evaluated at compile-time
   --> $DIR/const-drop-fail.rs:23:36
    |
@@ -21,6 +29,6 @@ LL | const fn check<T: ~const Destruct>(_: T) {}
    |                                    |
    |                                    the destructor for this type cannot be evaluated in constant functions
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0493`.
diff --git a/tests/ui/traits/const-traits/const-drop.precise.stderr b/tests/ui/traits/const-traits/const-drop.precise.stderr
index dd3ea5d241d..7b6d185c7cc 100644
--- a/tests/ui/traits/const-traits/const-drop.precise.stderr
+++ b/tests/ui/traits/const-traits/const-drop.precise.stderr
@@ -40,23 +40,11 @@ error: `~const` can only be applied to `#[const_trait]` traits
 LL | const fn a<T: ~const Destruct>(_: T) {}
    |                      ^^^^^^^^
 
-error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/const-drop.rs:53:5
-   |
-LL |     #[const_trait]
-   |     ^^^^^^^^^^^^^^ found 1 const parameter
-LL |     pub trait SomeTrait {
-LL |         fn foo();
-   |               - expected 0 const parameters
-
-error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/const-drop.rs:53:5
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const-drop.rs:18:22
    |
-LL |     #[const_trait]
-   |     ^^^^^^^^^^^^^^ found 1 const parameter
-LL |     pub trait SomeTrait {
-LL |         fn foo();
-   |               - expected 0 const parameters
+LL | const fn a<T: ~const Destruct>(_: T) {}
+   |                      ^^^^^^^^
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
@@ -78,7 +66,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
 LL + #![feature(effects)]
    |
 
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
 
-Some errors have detailed explanations: E0015, E0049, E0493.
+Some errors have detailed explanations: E0015, E0493.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/const-drop.stock.stderr b/tests/ui/traits/const-traits/const-drop.stock.stderr
index aa59e1c8dc4..b497c39b08a 100644
--- a/tests/ui/traits/const-traits/const-drop.stock.stderr
+++ b/tests/ui/traits/const-traits/const-drop.stock.stderr
@@ -40,23 +40,11 @@ error: `~const` can only be applied to `#[const_trait]` traits
 LL | const fn a<T: ~const Destruct>(_: T) {}
    |                      ^^^^^^^^
 
-error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/const-drop.rs:53:5
-   |
-LL |     #[const_trait]
-   |     ^^^^^^^^^^^^^^ found 1 const parameter
-LL |     pub trait SomeTrait {
-LL |         fn foo();
-   |               - expected 0 const parameters
-
-error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/const-drop.rs:53:5
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/const-drop.rs:18:22
    |
-LL |     #[const_trait]
-   |     ^^^^^^^^^^^^^^ found 1 const parameter
-LL |     pub trait SomeTrait {
-LL |         fn foo();
-   |               - expected 0 const parameters
+LL | const fn a<T: ~const Destruct>(_: T) {}
+   |                      ^^^^^^^^
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
@@ -80,7 +68,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
 LL + #![feature(effects)]
    |
 
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
 
-Some errors have detailed explanations: E0015, E0049, E0493.
+Some errors have detailed explanations: E0015, E0493.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/const-fns-are-early-bound.rs b/tests/ui/traits/const-traits/const-fns-are-early-bound.rs
index b87387f4d5d..6d08d8bdd91 100644
--- a/tests/ui/traits/const-traits/const-fns-are-early-bound.rs
+++ b/tests/ui/traits/const-traits/const-fns-are-early-bound.rs
@@ -1,4 +1,6 @@
 //@ known-bug: #110395
+//@ failure-status: 101
+//@ dont-check-compiler-stderr
 // FIXME(effects) check-pass
 //@ compile-flags: -Znext-solver
 
@@ -86,51 +88,3 @@ trait Tuple {}
 trait LegacyReceiver {}
 
 impl<T: ?Sized> LegacyReceiver for &T {}
-
-impl<T: ?Sized> LegacyReceiver for &mut T {}
-
-#[stable(feature = "minicore", since = "1.0.0")]
-pub mod effects {
-    use super::Sized;
-
-    #[lang = "EffectsNoRuntime"]
-    #[stable(feature = "minicore", since = "1.0.0")]
-    pub struct NoRuntime;
-    #[lang = "EffectsMaybe"]
-    #[stable(feature = "minicore", since = "1.0.0")]
-    pub struct Maybe;
-    #[lang = "EffectsRuntime"]
-    #[stable(feature = "minicore", since = "1.0.0")]
-    pub struct Runtime;
-
-    #[lang = "EffectsCompat"]
-    #[stable(feature = "minicore", since = "1.0.0")]
-    pub trait Compat<#[rustc_runtime] const RUNTIME: bool> {}
-
-    #[stable(feature = "minicore", since = "1.0.0")]
-    impl Compat<false> for NoRuntime {}
-    #[stable(feature = "minicore", since = "1.0.0")]
-    impl Compat<true> for Runtime {}
-    #[stable(feature = "minicore", since = "1.0.0")]
-    impl<#[rustc_runtime] const RUNTIME: bool> Compat<RUNTIME> for Maybe {}
-
-    #[lang = "EffectsTyCompat"]
-    #[marker]
-    #[stable(feature = "minicore", since = "1.0.0")]
-    pub trait TyCompat<T: ?Sized> {}
-
-    #[stable(feature = "minicore", since = "1.0.0")]
-    impl<T: ?Sized> TyCompat<T> for T {}
-    #[stable(feature = "minicore", since = "1.0.0")]
-    impl<T: ?Sized> TyCompat<T> for Maybe {}
-    #[stable(feature = "minicore", since = "1.0.0")]
-    impl<T: ?Sized> TyCompat<Maybe> for T {}
-
-    #[lang = "EffectsIntersection"]
-    #[stable(feature = "minicore", since = "1.0.0")]
-    pub trait Intersection {
-        #[lang = "EffectsIntersectionOutput"]
-        #[stable(feature = "minicore", since = "1.0.0")]
-        type Output: ?Sized;
-    }
-}
diff --git a/tests/ui/traits/const-traits/const-fns-are-early-bound.stderr b/tests/ui/traits/const-traits/const-fns-are-early-bound.stderr
deleted file mode 100644
index 9eda9d98ec5..00000000000
--- a/tests/ui/traits/const-traits/const-fns-are-early-bound.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0277]: the trait bound `fn() {foo}: const FnOnce()` is not satisfied
-  --> $DIR/const-fns-are-early-bound.rs:31:17
-   |
-LL |     is_const_fn(foo);
-   |     ----------- ^^^ the trait `FnOnce()` is not implemented for fn item `fn() {foo}`
-   |     |
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `is_const_fn`
-  --> $DIR/const-fns-are-early-bound.rs:25:12
-   |
-LL |     fn is_const_fn<F>(_: F)
-   |        ----------- required by a bound in this function
-LL |     where
-LL |         F: const FnOnce<()>,
-   |            ^^^^^^^^^^^^^^^^ required by this bound in `is_const_fn`
-
-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-impl-requires-const-trait.rs b/tests/ui/traits/const-traits/const-impl-requires-const-trait.rs
index bd6f476f879..e49e9090eb4 100644
--- a/tests/ui/traits/const-traits/const-impl-requires-const-trait.rs
+++ b/tests/ui/traits/const-traits/const-impl-requires-const-trait.rs
@@ -1,11 +1,10 @@
-//@ known-bug: #110395
-
+//@ compile-flags: -Znext-solver
 #![feature(const_trait_impl, effects)]
+#![allow(incomplete_features)]
 
 pub trait A {}
-// FIXME ~^ HELP: mark `A` as const
 
 impl const A for () {}
-// FIXME ~^ ERROR: const `impl` for trait `A` which is not marked with `#[const_trait]`
+//~^ ERROR: const `impl` for trait `A` which is not marked with `#[const_trait]`
 
 fn main() {}
diff --git a/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr b/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr
index 2a030369093..828e2174f00 100644
--- a/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr
+++ b/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr
@@ -1,28 +1,14 @@
-warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-impl-requires-const-trait.rs:3:30
-   |
-LL | #![feature(const_trait_impl, effects)]
-   |                              ^^^^^^^
-   |
-   = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
 error: const `impl` for trait `A` which is not marked with `#[const_trait]`
-  --> $DIR/const-impl-requires-const-trait.rs:8:12
+  --> $DIR/const-impl-requires-const-trait.rs:7:12
    |
 LL | pub trait A {}
    | - help: mark `A` as const: `#[const_trait]`
-...
+LL |
 LL | impl const A for () {}
    |            ^
    |
    = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
    = note: adding a non-const method body in the future would be a breaking change
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/const-traits/const-impl-trait.rs b/tests/ui/traits/const-traits/const-impl-trait.rs
index 51dfe29b829..61b8c9a5bff 100644
--- a/tests/ui/traits/const-traits/const-impl-trait.rs
+++ b/tests/ui/traits/const-traits/const-impl-trait.rs
@@ -1,4 +1,7 @@
+//@ compile-flags: -Znext-solver
 //@ known-bug: #110395
+//@ failure-status: 101
+//@ dont-check-compiler-stderr
 // Broken until we have `&T: const Deref` impl in stdlib
 
 #![allow(incomplete_features)]
diff --git a/tests/ui/traits/const-traits/const-impl-trait.stderr b/tests/ui/traits/const-traits/const-impl-trait.stderr
deleted file mode 100644
index 1040af7541c..00000000000
--- a/tests/ui/traits/const-traits/const-impl-trait.stderr
+++ /dev/null
@@ -1,249 +0,0 @@
-error[E0635]: unknown feature `const_cmp`
-  --> $DIR/const-impl-trait.rs:8:5
-   |
-LL |     const_cmp,
-   |     ^^^^^^^^^
-
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:13:30
-   |
-LL | const fn cmp(a: &impl ~const PartialEq) -> bool {
-   |                              ^^^^^^^^^
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:17:30
-   |
-LL | const fn wrap(x: impl ~const PartialEq + ~const Destruct)
-   |                              ^^^^^^^^^
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:17:49
-   |
-LL | const fn wrap(x: impl ~const PartialEq + ~const Destruct)
-   |                                                 ^^^^^^^^
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:18:20
-   |
-LL |     -> impl ~const PartialEq + ~const Destruct
-   |                    ^^^^^^^^^
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:18:39
-   |
-LL |     -> impl ~const PartialEq + ~const Destruct
-   |                                       ^^^^^^^^
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:18:20
-   |
-LL |     -> impl ~const PartialEq + ~const Destruct
-   |                    ^^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:18:39
-   |
-LL |     -> impl ~const PartialEq + ~const Destruct
-   |                                       ^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:25:29
-   |
-LL |     fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
-   |                             ^^^^^^^^^
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:25:48
-   |
-LL |     fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
-   |                                                ^^^^^^^^
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:29:29
-   |
-LL |     fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
-   |                             ^^^^^^^^^
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:29:48
-   |
-LL |     fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
-   |                                                ^^^^^^^^
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:29:29
-   |
-LL |     fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
-   |                             ^^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:29:48
-   |
-LL |     fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
-   |                                                ^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:50:41
-   |
-LL | const fn apit(_: impl ~const T + ~const Destruct) {}
-   |                                         ^^^^^^^^
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:54:73
-   |
-LL | const fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T> + ~const Destruct) {}
-   |                                                                         ^^^^^^^^
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:25:29
-   |
-LL |     fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
-   |                             ^^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:25:48
-   |
-LL |     fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
-   |                                                ^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:25:29
-   |
-LL |     fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
-   |                             ^^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:25:48
-   |
-LL |     fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
-   |                                                ^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:25:29
-   |
-LL |     fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
-   |                             ^^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:25:48
-   |
-LL |     fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
-   |                                                ^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time
-  --> $DIR/const-impl-trait.rs:37:26
-   |
-LL |     assert!(wrap(123) == wrap(123));
-   |                          ^^^^^^^^^- value is dropped here
-   |                          |
-   |                          the destructor for this type cannot be evaluated in constants
-
-error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time
-  --> $DIR/const-impl-trait.rs:37:26
-   |
-LL |     assert!(wrap(123) == wrap(123));
-   |                          ^^^^^^^^^- value is dropped here
-   |                          |
-   |                          the destructor for this type cannot be evaluated in constants
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time
-  --> $DIR/const-impl-trait.rs:37:13
-   |
-LL |     assert!(wrap(123) == wrap(123));
-   |             ^^^^^^^^^             - value is dropped here
-   |             |
-   |             the destructor for this type cannot be evaluated in constants
-
-error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time
-  --> $DIR/const-impl-trait.rs:37:13
-   |
-LL |     assert!(wrap(123) == wrap(123));
-   |             ^^^^^^^^^             - value is dropped here
-   |             |
-   |             the destructor for this type cannot be evaluated in constants
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time
-  --> $DIR/const-impl-trait.rs:38:26
-   |
-LL |     assert!(wrap(123) != wrap(456));
-   |                          ^^^^^^^^^- value is dropped here
-   |                          |
-   |                          the destructor for this type cannot be evaluated in constants
-
-error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time
-  --> $DIR/const-impl-trait.rs:38:26
-   |
-LL |     assert!(wrap(123) != wrap(456));
-   |                          ^^^^^^^^^- value is dropped here
-   |                          |
-   |                          the destructor for this type cannot be evaluated in constants
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time
-  --> $DIR/const-impl-trait.rs:38:13
-   |
-LL |     assert!(wrap(123) != wrap(456));
-   |             ^^^^^^^^^             - value is dropped here
-   |             |
-   |             the destructor for this type cannot be evaluated in constants
-
-error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time
-  --> $DIR/const-impl-trait.rs:38:13
-   |
-LL |     assert!(wrap(123) != wrap(456));
-   |             ^^^^^^^^^             - value is dropped here
-   |             |
-   |             the destructor for this type cannot be evaluated in constants
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0493]: destructor of `impl ~const T + ~const Destruct` cannot be evaluated at compile-time
-  --> $DIR/const-impl-trait.rs:50:15
-   |
-LL | const fn apit(_: impl ~const T + ~const Destruct) {}
-   |               ^                                    - value is dropped here
-   |               |
-   |               the destructor for this type cannot be evaluated in constant functions
-
-error[E0493]: destructor of `impl IntoIterator<Item : ~const T> + ~const Destruct` cannot be evaluated at compile-time
-  --> $DIR/const-impl-trait.rs:54:27
-   |
-LL | const fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T> + ~const Destruct) {}
-   |                           ^                                                        - value is dropped here
-   |                           |
-   |                           the destructor for this type cannot be evaluated in constant functions
-
-error: aborting due to 33 previous errors
-
-Some errors have detailed explanations: E0493, E0635.
-For more information about an error, try `rustc --explain E0493`.
diff --git a/tests/ui/traits/const-traits/const-in-closure.rs b/tests/ui/traits/const-traits/const-in-closure.rs
new file mode 100644
index 00000000000..51b22c53036
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-in-closure.rs
@@ -0,0 +1,25 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+#![feature(const_trait_impl, effects)]
+//~^ WARN the feature `effects` is incomplete
+
+#[const_trait] trait Trait {
+    fn method();
+}
+
+const fn foo<T: Trait>() {
+    let _ = || {
+        // Make sure this doesn't enforce `T: ~const Trait`
+        T::method();
+    };
+}
+
+fn bar<T: const Trait>() {
+    let _ = || {
+        // Make sure unconditionally const bounds propagate from parent.
+        const { T::method(); };
+    };
+}
+
+fn main() {}
diff --git a/tests/ui/traits/const-traits/const-in-closure.stderr b/tests/ui/traits/const-traits/const-in-closure.stderr
new file mode 100644
index 00000000000..f4b03b9ed20
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-in-closure.stderr
@@ -0,0 +1,11 @@
+warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/const-in-closure.rs:4:30
+   |
+LL | #![feature(const_trait_impl, effects)]
+   |                              ^^^^^^^
+   |
+   = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/const-traits/cross-crate.gatednc.stderr b/tests/ui/traits/const-traits/cross-crate.gatednc.stderr
index a34bae843c8..b6f2434140d 100644
--- a/tests/ui/traits/const-traits/cross-crate.gatednc.stderr
+++ b/tests/ui/traits/const-traits/cross-crate.gatednc.stderr
@@ -1,21 +1,8 @@
 error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
-  --> $DIR/cross-crate.rs:19:14
+  --> $DIR/cross-crate.rs:19:5
    |
 LL |     NonConst.func();
-   |              ^^^^ the trait `cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
-   |
-note: required by a bound in `func`
-  --> $DIR/auxiliary/cross-crate.rs:5:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ required by this bound in `MyTrait::func`
-...
-LL |     fn func(self);
-   |        ---- required by a bound in this associated function
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | const fn const_context() where cross_crate::NonConst: cross_crate::MyTrait {
-   |                          +++++++++++++++++++++++++++++++++++++++++++++++++
+   |     ^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr
index d0f22c0b9b6..7b4d512e391 100644
--- a/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr
+++ b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr
@@ -1,21 +1,8 @@
 error[E0277]: the trait bound `(): ~const Tr` is not satisfied
-  --> $DIR/default-method-body-is-const-same-trait-ck.rs:10:12
+  --> $DIR/default-method-body-is-const-same-trait-ck.rs:10:9
    |
 LL |         ().a()
-   |            ^ the trait `Tr` is not implemented for `()`
-   |
-note: required by a bound in `Tr::a`
-  --> $DIR/default-method-body-is-const-same-trait-ck.rs:5:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ required by this bound in `Tr::a`
-LL | pub trait Tr {
-LL |     fn a(&self) {}
-   |        - required by a bound in this associated function
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | pub trait Tr where (): Tr {
-   |              ++++++++++++
+   |         ^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/const-traits/dont-observe-host-opaque.rs b/tests/ui/traits/const-traits/dont-observe-host-opaque.rs
new file mode 100644
index 00000000000..4a5ae346e39
--- /dev/null
+++ b/tests/ui/traits/const-traits/dont-observe-host-opaque.rs
@@ -0,0 +1,12 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+#![feature(const_trait_impl, effects)]
+//~^ WARN the feature `effects` is incomplete
+
+const fn opaque() -> impl Sized {}
+
+fn main() {
+    let mut x = const { opaque() };
+    x = opaque();
+}
diff --git a/tests/ui/traits/const-traits/dont-observe-host-opaque.stderr b/tests/ui/traits/const-traits/dont-observe-host-opaque.stderr
new file mode 100644
index 00000000000..1b457ab7643
--- /dev/null
+++ b/tests/ui/traits/const-traits/dont-observe-host-opaque.stderr
@@ -0,0 +1,11 @@
+warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/dont-observe-host-opaque.rs:4:30
+   |
+LL | #![feature(const_trait_impl, effects)]
+   |                              ^^^^^^^
+   |
+   = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/const-traits/dont-observe-host.rs b/tests/ui/traits/const-traits/dont-observe-host.rs
new file mode 100644
index 00000000000..d027d578c42
--- /dev/null
+++ b/tests/ui/traits/const-traits/dont-observe-host.rs
@@ -0,0 +1,23 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+#![feature(const_trait_impl, effects)]
+//~^ WARN the feature `effects` is incomplete
+
+#[const_trait]
+trait Trait {
+    fn method() {}
+}
+
+impl const Trait for () {}
+
+fn main() {
+    let mut x = const {
+        let x = <()>::method;
+        x();
+        x
+    };
+    let y = <()>::method;
+    y();
+    x = y;
+}
diff --git a/tests/ui/traits/const-traits/dont-observe-host.stderr b/tests/ui/traits/const-traits/dont-observe-host.stderr
new file mode 100644
index 00000000000..64ef611f011
--- /dev/null
+++ b/tests/ui/traits/const-traits/dont-observe-host.stderr
@@ -0,0 +1,11 @@
+warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/dont-observe-host.rs:4:30
+   |
+LL | #![feature(const_trait_impl, effects)]
+   |                              ^^^^^^^
+   |
+   = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/const-traits/effects/minicore.rs b/tests/ui/traits/const-traits/effects/minicore.rs
index 9b615450c68..a756f4d9f6c 100644
--- a/tests/ui/traits/const-traits/effects/minicore.rs
+++ b/tests/ui/traits/const-traits/effects/minicore.rs
@@ -536,35 +536,3 @@ fn test_const_eval_select() {
 
     const_eval_select((), const_fn, rt_fn);
 }
-
-mod effects {
-    use super::Sized;
-
-    #[lang = "EffectsNoRuntime"]
-    pub struct NoRuntime;
-    #[lang = "EffectsMaybe"]
-    pub struct Maybe;
-    #[lang = "EffectsRuntime"]
-    pub struct Runtime;
-
-    #[lang = "EffectsCompat"]
-    pub trait Compat<#[rustc_runtime] const RUNTIME: bool> {}
-
-    impl Compat<false> for NoRuntime {}
-    impl Compat<true> for Runtime {}
-    impl<#[rustc_runtime] const RUNTIME: bool> Compat<RUNTIME> for Maybe {}
-
-    #[lang = "EffectsTyCompat"]
-    #[marker]
-    pub trait TyCompat<T: ?Sized> {}
-
-    impl<T: ?Sized> TyCompat<T> for T {}
-    impl<T: ?Sized> TyCompat<T> for Maybe {}
-    impl<T: ?Sized> TyCompat<Maybe> for T {}
-
-    #[lang = "EffectsIntersection"]
-    pub trait Intersection {
-        #[lang = "EffectsIntersectionOutput"]
-        type Output: ?Sized;
-    }
-}
diff --git a/tests/ui/traits/const-traits/effects/minicore.stderr b/tests/ui/traits/const-traits/effects/minicore.stderr
index 823ab69df9c..568d98cfe87 100644
--- a/tests/ui/traits/const-traits/effects/minicore.stderr
+++ b/tests/ui/traits/const-traits/effects/minicore.stderr
@@ -1,13 +1,13 @@
 error: the compiler unexpectedly panicked. this is a bug.
 
 query stack during panic:
-#0 [check_well_formed] checking that `<impl at $DIR/minicore.rs:459:1: 459:36>` is well-formed
-#1 [check_mod_type_wf] checking that types are well-formed in top-level module
+#0 [typeck] type-checking `Clone::clone_from`
+#1 [analysis] running analysis passes on this crate
 end of query stack
 
 error: the compiler unexpectedly panicked. this is a bug.
 
 query stack during panic:
-#0 [check_well_formed] checking that `drop` is well-formed
-#1 [check_mod_type_wf] checking that types are well-formed in top-level module
+#0 [typeck] type-checking `test_const_eval_select`
+#1 [analysis] running analysis passes on this crate
 end of query stack
diff --git a/tests/ui/traits/const-traits/effects/no-explicit-const-params-cross-crate.stderr b/tests/ui/traits/const-traits/effects/no-explicit-const-params-cross-crate.stderr
index 8c591edac54..eea6a06c1c8 100644
--- a/tests/ui/traits/const-traits/effects/no-explicit-const-params-cross-crate.stderr
+++ b/tests/ui/traits/const-traits/effects/no-explicit-const-params-cross-crate.stderr
@@ -16,17 +16,15 @@ error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplie
   --> $DIR/no-explicit-const-params-cross-crate.rs:16:12
    |
 LL |     <() as Bar<false>>::bar();
-   |            ^^^ expected 0 generic arguments
+   |            ^^^------- help: remove the unnecessary generics
+   |            |
+   |            expected 0 generic arguments
    |
 note: trait defined here, with 0 generic parameters
   --> $DIR/auxiliary/cross-crate.rs:8:11
    |
 LL | pub trait Bar {
    |           ^^^
-help: replace the generic bound with the associated type
-   |
-LL |     <() as Bar< = false>>::bar();
-   |                 +
 
 error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/no-explicit-const-params-cross-crate.rs:7:5
@@ -46,17 +44,15 @@ error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplie
   --> $DIR/no-explicit-const-params-cross-crate.rs:9:12
    |
 LL |     <() as Bar<true>>::bar();
-   |            ^^^ expected 0 generic arguments
+   |            ^^^------ help: remove the unnecessary generics
+   |            |
+   |            expected 0 generic arguments
    |
 note: trait defined here, with 0 generic parameters
   --> $DIR/auxiliary/cross-crate.rs:8:11
    |
 LL | pub trait Bar {
    |           ^^^
-help: replace the generic bound with the associated type
-   |
-LL |     <() as Bar< = true>>::bar();
-   |                 +
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/traits/const-traits/effects/no-explicit-const-params.rs b/tests/ui/traits/const-traits/effects/no-explicit-const-params.rs
index 84f5f2803e1..b08aba9acbc 100644
--- a/tests/ui/traits/const-traits/effects/no-explicit-const-params.rs
+++ b/tests/ui/traits/const-traits/effects/no-explicit-const-params.rs
@@ -23,5 +23,4 @@ const FOO: () = {
     //~^ ERROR: function takes 0 generic arguments but 1 generic argument was supplied
     <() as Bar<false>>::bar();
     //~^ ERROR: trait takes 0 generic arguments but 1 generic argument was supplied
-    //~| ERROR: mismatched types
 };
diff --git a/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr b/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr
index cc08114ddb5..a3aa970e94d 100644
--- a/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr
+++ b/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr
@@ -30,26 +30,15 @@ error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplie
   --> $DIR/no-explicit-const-params.rs:24:12
    |
 LL |     <() as Bar<false>>::bar();
-   |            ^^^ expected 0 generic arguments
+   |            ^^^------- help: remove the unnecessary generics
+   |            |
+   |            expected 0 generic arguments
    |
 note: trait defined here, with 0 generic parameters
   --> $DIR/no-explicit-const-params.rs:6:7
    |
 LL | trait Bar {
    |       ^^^
-help: replace the generic bound with the associated type
-   |
-LL |     <() as Bar< = false>>::bar();
-   |                 +
-
-error[E0308]: mismatched types
-  --> $DIR/no-explicit-const-params.rs:24:5
-   |
-LL |     <() as Bar<false>>::bar();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `false`, found `true`
-   |
-   = note: expected constant `false`
-              found constant `true`
 
 error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/no-explicit-const-params.rs:15:5
@@ -69,19 +58,16 @@ error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplie
   --> $DIR/no-explicit-const-params.rs:17:12
    |
 LL |     <() as Bar<true>>::bar();
-   |            ^^^ expected 0 generic arguments
+   |            ^^^------ help: remove the unnecessary generics
+   |            |
+   |            expected 0 generic arguments
    |
 note: trait defined here, with 0 generic parameters
   --> $DIR/no-explicit-const-params.rs:6:7
    |
 LL | trait Bar {
    |       ^^^
-help: replace the generic bound with the associated type
-   |
-LL |     <() as Bar< = true>>::bar();
-   |                 +
 
-error: aborting due to 6 previous errors; 1 warning emitted
+error: aborting due to 5 previous errors; 1 warning emitted
 
-Some errors have detailed explanations: E0107, E0308.
-For more information about an error, try `rustc --explain E0107`.
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/traits/const-traits/effects/spec-effectvar-ice.rs b/tests/ui/traits/const-traits/effects/spec-effectvar-ice.rs
index 0508b1c5e26..d29cd93d3fb 100644
--- a/tests/ui/traits/const-traits/effects/spec-effectvar-ice.rs
+++ b/tests/ui/traits/const-traits/effects/spec-effectvar-ice.rs
@@ -1,4 +1,3 @@
-//@ check-fail
 // Fixes #119830
 
 #![feature(effects)] //~ WARN the feature `effects` is incomplete
diff --git a/tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr b/tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr
index e97a9615ae1..d9655c4995f 100644
--- a/tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr
+++ b/tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr
@@ -1,5 +1,5 @@
 warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/spec-effectvar-ice.rs:4:12
+  --> $DIR/spec-effectvar-ice.rs:3:12
    |
 LL | #![feature(effects)]
    |            ^^^^^^^
@@ -13,7 +13,7 @@ error: using `#![feature(effects)]` without enabling next trait solver globally
    = help: use `-Znext-solver` to enable
 
 error: const `impl` for trait `Foo` which is not marked with `#[const_trait]`
-  --> $DIR/spec-effectvar-ice.rs:12:15
+  --> $DIR/spec-effectvar-ice.rs:11:15
    |
 LL | trait Foo {}
    | - help: mark `Foo` as const: `#[const_trait]`
@@ -25,7 +25,7 @@ LL | impl<T> const Foo for T {}
    = note: adding a non-const method body in the future would be a breaking change
 
 error: const `impl` for trait `Foo` which is not marked with `#[const_trait]`
-  --> $DIR/spec-effectvar-ice.rs:15:15
+  --> $DIR/spec-effectvar-ice.rs:14:15
    |
 LL | trait Foo {}
    | - help: mark `Foo` as const: `#[const_trait]`
@@ -37,25 +37,25 @@ LL | impl<T> const Foo for T where T: const Specialize {}
    = note: adding a non-const method body in the future would be a breaking change
 
 error: `const` can only be applied to `#[const_trait]` traits
-  --> $DIR/spec-effectvar-ice.rs:15:40
+  --> $DIR/spec-effectvar-ice.rs:14:40
    |
 LL | impl<T> const Foo for T where T: const Specialize {}
    |                                        ^^^^^^^^^^
 
 error: specialization impl does not specialize any associated items
-  --> $DIR/spec-effectvar-ice.rs:15:1
+  --> $DIR/spec-effectvar-ice.rs:14:1
    |
 LL | impl<T> const Foo for T where T: const Specialize {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: impl is a specialization of this impl
-  --> $DIR/spec-effectvar-ice.rs:12:1
+  --> $DIR/spec-effectvar-ice.rs:11:1
    |
 LL | impl<T> const Foo for T {}
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: cannot specialize on trait `Specialize`
-  --> $DIR/spec-effectvar-ice.rs:15:34
+  --> $DIR/spec-effectvar-ice.rs:14:34
    |
 LL | impl<T> const Foo for T where T: const Specialize {}
    |                                  ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/const-traits/fn-ptr-lub.rs b/tests/ui/traits/const-traits/fn-ptr-lub.rs
new file mode 100644
index 00000000000..0fc32678827
--- /dev/null
+++ b/tests/ui/traits/const-traits/fn-ptr-lub.rs
@@ -0,0 +1,20 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+#![feature(const_trait_impl, effects)]
+//~^ WARN the feature `effects` is incomplete
+
+const fn foo() {}
+const fn bar() {}
+fn baz() {}
+
+const fn caller(branch: bool) {
+    let mut x = if branch {
+      foo
+    } else {
+      bar
+    };
+    x = baz;
+}
+
+fn main() {}
diff --git a/tests/ui/traits/const-traits/fn-ptr-lub.stderr b/tests/ui/traits/const-traits/fn-ptr-lub.stderr
new file mode 100644
index 00000000000..b333311b660
--- /dev/null
+++ b/tests/ui/traits/const-traits/fn-ptr-lub.stderr
@@ -0,0 +1,11 @@
+warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/fn-ptr-lub.rs:4:30
+   |
+LL | #![feature(const_trait_impl, effects)]
+   |                              ^^^^^^^
+   |
+   = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/const-traits/hir-const-check.rs b/tests/ui/traits/const-traits/hir-const-check.rs
index f5fb0fd516a..b3df6495afc 100644
--- a/tests/ui/traits/const-traits/hir-const-check.rs
+++ b/tests/ui/traits/const-traits/hir-const-check.rs
@@ -1,3 +1,5 @@
+//@ compile-flags: -Znext-solver
+
 // Regression test for #69615.
 
 #![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete
diff --git a/tests/ui/traits/const-traits/hir-const-check.stderr b/tests/ui/traits/const-traits/hir-const-check.stderr
index 598129d8694..19ea734efb7 100644
--- a/tests/ui/traits/const-traits/hir-const-check.stderr
+++ b/tests/ui/traits/const-traits/hir-const-check.stderr
@@ -1,5 +1,5 @@
 warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/hir-const-check.rs:3:30
+  --> $DIR/hir-const-check.rs:5:30
    |
 LL | #![feature(const_trait_impl, effects)]
    |                              ^^^^^^^
@@ -8,7 +8,7 @@ LL | #![feature(const_trait_impl, effects)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0658]: `?` is not allowed in a `const fn`
-  --> $DIR/hir-const-check.rs:12:9
+  --> $DIR/hir-const-check.rs:14:9
    |
 LL |         Some(())?;
    |         ^^^^^^^^^
@@ -17,11 +17,6 @@ LL |         Some(())?;
    = help: add `#![feature(const_try)]` 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: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 1 previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs b/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs
index 64634e7b7ac..29f40604747 100644
--- a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs
+++ b/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs
@@ -3,5 +3,6 @@
 
 const fn with_positive<F: ~const Fn()>() {}
 //~^ ERROR `~const` can only be applied to `#[const_trait]` traits
+//~| ERROR `~const` can only be applied to `#[const_trait]` traits
 
 pub fn main() {}
diff --git a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr b/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr
index c937430a1ca..03f88be0093 100644
--- a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr
+++ b/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr
@@ -9,5 +9,13 @@ error: `~const` can only be applied to `#[const_trait]` traits
 LL | const fn with_positive<F: ~const Fn()>() {}
    |                                  ^^^^
 
-error: aborting due to 2 previous errors
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/ice-123664-unexpected-bound-var.rs:4:34
+   |
+LL | const fn with_positive<F: ~const Fn()>() {}
+   |                                  ^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/traits/const-traits/issue-92111.stderr b/tests/ui/traits/const-traits/issue-92111.stderr
index ecc994a3fe6..805cc537014 100644
--- a/tests/ui/traits/const-traits/issue-92111.stderr
+++ b/tests/ui/traits/const-traits/issue-92111.stderr
@@ -4,6 +4,14 @@ error: `~const` can only be applied to `#[const_trait]` traits
 LL | const fn a<T: ~const Destruct>(t: T) {}
    |                      ^^^^^^^^
 
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/issue-92111.rs:20:22
+   |
+LL | const fn a<T: ~const Destruct>(t: T) {}
+   |                      ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0493]: destructor of `T` cannot be evaluated at compile-time
   --> $DIR/issue-92111.rs:20:32
    |
@@ -12,6 +20,6 @@ LL | const fn a<T: ~const Destruct>(t: T) {}
    |                                |
    |                                the destructor for this type cannot be evaluated in constant functions
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0493`.
diff --git a/tests/ui/traits/const-traits/item-bound-entailment-fails.rs b/tests/ui/traits/const-traits/item-bound-entailment-fails.rs
new file mode 100644
index 00000000000..42799e3700c
--- /dev/null
+++ b/tests/ui/traits/const-traits/item-bound-entailment-fails.rs
@@ -0,0 +1,31 @@
+//@ compile-flags: -Znext-solver
+#![feature(const_trait_impl, effects)]
+//~^ WARN the feature `effects` is incomplete
+
+#[const_trait] trait Foo {
+    type Assoc<T>: ~const Bar
+    where
+        T: ~const Bar;
+}
+
+#[const_trait] trait Bar {}
+struct N<T>(T);
+impl<T> Bar for N<T> where T: Bar {}
+struct C<T>(T);
+impl<T> const Bar for C<T> where T: ~const Bar {}
+
+impl const Foo for u32 {
+    type Assoc<T> = N<T>
+    //~^ ERROR the trait bound `N<T>: ~const Bar` is not satisfied
+    where
+        T: ~const Bar;
+}
+
+impl const Foo for i32 {
+    type Assoc<T> = C<T>
+    //~^ ERROR the trait bound `T: ~const Bar` is not satisfied
+    where
+        T: Bar;
+}
+
+fn main() {}
diff --git a/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr b/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr
new file mode 100644
index 00000000000..3b3868c4bc8
--- /dev/null
+++ b/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr
@@ -0,0 +1,36 @@
+warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/item-bound-entailment-fails.rs:2:30
+   |
+LL | #![feature(const_trait_impl, effects)]
+   |                              ^^^^^^^
+   |
+   = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `N<T>: ~const Bar` is not satisfied
+  --> $DIR/item-bound-entailment-fails.rs:18:21
+   |
+LL |     type Assoc<T> = N<T>
+   |                     ^^^^
+   |
+note: required by a bound in `Foo::Assoc`
+  --> $DIR/item-bound-entailment-fails.rs:6:20
+   |
+LL |     type Assoc<T>: ~const Bar
+   |                    ^^^^^^^^^^ required by this bound in `Foo::Assoc`
+
+error[E0277]: the trait bound `T: ~const Bar` is not satisfied
+  --> $DIR/item-bound-entailment-fails.rs:25:21
+   |
+LL |     type Assoc<T> = C<T>
+   |                     ^^^^
+   |
+note: required by a bound in `Foo::Assoc`
+  --> $DIR/item-bound-entailment-fails.rs:6:20
+   |
+LL |     type Assoc<T>: ~const Bar
+   |                    ^^^^^^^^^^ required by this bound in `Foo::Assoc`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/item-bound-entailment.rs b/tests/ui/traits/const-traits/item-bound-entailment.rs
new file mode 100644
index 00000000000..3670eabd66c
--- /dev/null
+++ b/tests/ui/traits/const-traits/item-bound-entailment.rs
@@ -0,0 +1,31 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+#![feature(const_trait_impl, effects)]
+//~^ WARN the feature `effects` is incomplete
+
+#[const_trait] trait Foo {
+    type Assoc<T>: ~const Bar
+    where
+        T: ~const Bar;
+}
+
+#[const_trait] trait Bar {}
+struct N<T>(T);
+impl<T> Bar for N<T> where T: Bar {}
+struct C<T>(T);
+impl<T> const Bar for C<T> where T: ~const Bar {}
+
+impl Foo for u32 {
+    type Assoc<T> = N<T>
+    where
+        T: Bar;
+}
+
+impl const Foo for i32 {
+    type Assoc<T> = C<T>
+    where
+        T: ~const Bar;
+}
+
+fn main() {}
diff --git a/tests/ui/traits/const-traits/item-bound-entailment.stderr b/tests/ui/traits/const-traits/item-bound-entailment.stderr
new file mode 100644
index 00000000000..b4a4ebdbee2
--- /dev/null
+++ b/tests/ui/traits/const-traits/item-bound-entailment.stderr
@@ -0,0 +1,11 @@
+warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/item-bound-entailment.rs:4:30
+   |
+LL | #![feature(const_trait_impl, effects)]
+   |                              ^^^^^^^
+   |
+   = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.stderr b/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.stderr
index de4783bdb3f..2803c37646b 100644
--- a/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.stderr
+++ b/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.stderr
@@ -4,14 +4,13 @@ error: `~const` can only be applied to `#[const_trait]` traits
 LL | impl<A, B> const Convert<B> for A where B: ~const From<A> {
    |                                                   ^^^^^^^
 
-error[E0049]: method `to` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/non-const-op-in-closure-in-const.rs:5:1
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/non-const-op-in-closure-in-const.rs:10:51
+   |
+LL | impl<A, B> const Convert<B> for A where B: ~const From<A> {
+   |                                                   ^^^^^^^
    |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Convert<T> {
-LL |     fn to(self) -> T;
-   |          - expected 0 const parameters
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0015]: cannot call non-const fn `<B as From<A>>::from` in constant functions
   --> $DIR/non-const-op-in-closure-in-const.rs:12:9
@@ -27,5 +26,4 @@ LL + #![feature(effects)]
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0015, E0049.
-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/predicate-entailment-fails.rs b/tests/ui/traits/const-traits/predicate-entailment-fails.rs
new file mode 100644
index 00000000000..5d6109bfad3
--- /dev/null
+++ b/tests/ui/traits/const-traits/predicate-entailment-fails.rs
@@ -0,0 +1,43 @@
+//@ compile-flags: -Znext-solver
+#![feature(const_trait_impl, effects)]
+//~^ WARN the feature `effects` is incomplete
+
+#[const_trait] trait Bar {}
+impl const Bar for () {}
+
+
+#[const_trait] trait TildeConst {
+    type Bar<T> where T: ~const Bar;
+
+    fn foo<T>() where T: ~const Bar;
+}
+impl TildeConst for () {
+    type Bar<T> = () where T: const Bar;
+    //~^ ERROR impl has stricter requirements than trait
+
+    fn foo<T>() where T: const Bar {}
+    //~^ ERROR impl has stricter requirements than trait
+}
+
+
+#[const_trait] trait NeverConst {
+    type Bar<T> where T: Bar;
+
+    fn foo<T>() where T: Bar;
+}
+impl NeverConst for i32 {
+    type Bar<T> = () where T: const Bar;
+    //~^ ERROR impl has stricter requirements than trait
+
+    fn foo<T>() where T: const Bar {}
+    //~^ ERROR impl has stricter requirements than trait
+}
+impl const NeverConst for u32 {
+    type Bar<T> = () where T: ~const Bar;
+    //~^ ERROR impl has stricter requirements than trait
+
+    fn foo<T>() where T: ~const Bar {}
+    //~^ ERROR impl has stricter requirements than trait
+}
+
+fn main() {}
diff --git a/tests/ui/traits/const-traits/predicate-entailment-fails.stderr b/tests/ui/traits/const-traits/predicate-entailment-fails.stderr
new file mode 100644
index 00000000000..7cd48ef1d48
--- /dev/null
+++ b/tests/ui/traits/const-traits/predicate-entailment-fails.stderr
@@ -0,0 +1,66 @@
+warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/predicate-entailment-fails.rs:2:30
+   |
+LL | #![feature(const_trait_impl, effects)]
+   |                              ^^^^^^^
+   |
+   = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/predicate-entailment-fails.rs:15:31
+   |
+LL |     type Bar<T> where T: ~const Bar;
+   |     ----------- definition of `Bar` from trait
+...
+LL |     type Bar<T> = () where T: const Bar;
+   |                               ^^^^^^^^^ impl has extra requirement `T: const Bar`
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/predicate-entailment-fails.rs:18:26
+   |
+LL |     fn foo<T>() where T: ~const Bar;
+   |     -------------------------------- definition of `foo` from trait
+...
+LL |     fn foo<T>() where T: const Bar {}
+   |                          ^^^^^^^^^ impl has extra requirement `T: const Bar`
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/predicate-entailment-fails.rs:29:31
+   |
+LL |     type Bar<T> where T: Bar;
+   |     ----------- definition of `Bar` from trait
+...
+LL |     type Bar<T> = () where T: const Bar;
+   |                               ^^^^^^^^^ impl has extra requirement `T: const Bar`
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/predicate-entailment-fails.rs:32:26
+   |
+LL |     fn foo<T>() where T: Bar;
+   |     ------------------------- definition of `foo` from trait
+...
+LL |     fn foo<T>() where T: const Bar {}
+   |                          ^^^^^^^^^ impl has extra requirement `T: const Bar`
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/predicate-entailment-fails.rs:36:31
+   |
+LL |     type Bar<T> where T: Bar;
+   |     ----------- definition of `Bar` from trait
+...
+LL |     type Bar<T> = () where T: ~const Bar;
+   |                               ^^^^^^^^^^ impl has extra requirement `T: ~const Bar`
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/predicate-entailment-fails.rs:39:26
+   |
+LL |     fn foo<T>() where T: Bar;
+   |     ------------------------- definition of `foo` from trait
+...
+LL |     fn foo<T>() where T: ~const Bar {}
+   |                          ^^^^^^^^^^ impl has extra requirement `T: ~const Bar`
+
+error: aborting due to 6 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0276`.
diff --git a/tests/ui/traits/const-traits/predicate-entailment-passes.rs b/tests/ui/traits/const-traits/predicate-entailment-passes.rs
new file mode 100644
index 00000000000..b660329151b
--- /dev/null
+++ b/tests/ui/traits/const-traits/predicate-entailment-passes.rs
@@ -0,0 +1,39 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+#![feature(const_trait_impl, effects)]
+//~^ WARN the feature `effects` is incomplete
+
+#[const_trait] trait Bar {}
+impl const Bar for () {}
+
+
+#[const_trait] trait TildeConst {
+    type Bar<T> where T: ~const Bar;
+
+    fn foo<T>() where T: ~const Bar;
+}
+impl TildeConst for () {
+    type Bar<T> = () where T: Bar;
+
+    fn foo<T>() where T: Bar {}
+}
+
+
+#[const_trait] trait AlwaysConst {
+    type Bar<T> where T: const Bar;
+
+    fn foo<T>() where T: const Bar;
+}
+impl AlwaysConst for i32 {
+    type Bar<T> = () where T: Bar;
+
+    fn foo<T>() where T: Bar {}
+}
+impl const AlwaysConst for u32 {
+    type Bar<T> = () where T: ~const Bar;
+
+    fn foo<T>() where T: ~const Bar {}
+}
+
+fn main() {}
diff --git a/tests/ui/traits/const-traits/predicate-entailment-passes.stderr b/tests/ui/traits/const-traits/predicate-entailment-passes.stderr
new file mode 100644
index 00000000000..dcaeea73b58
--- /dev/null
+++ b/tests/ui/traits/const-traits/predicate-entailment-passes.stderr
@@ -0,0 +1,11 @@
+warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/predicate-entailment-passes.rs:4:30
+   |
+LL | #![feature(const_trait_impl, effects)]
+   |                              ^^^^^^^
+   |
+   = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr
index 7643697874f..bffc60c65fc 100644
--- a/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr
+++ b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr
@@ -1,12 +1,3 @@
-error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/const-default-bound-non-const-specialized-bound.rs:16:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Bar {
-LL |     fn bar();
-   |           - expected 0 const parameters
-
 error: cannot specialize on const impl with non-const impl
   --> $DIR/const-default-bound-non-const-specialized-bound.rs:28:1
    |
@@ -16,26 +7,5 @@ LL | |     T: Foo, //FIXME ~ ERROR missing `~const` qualifier
 LL | |     T: Specialize,
    | |__________________^
 
-error[E0049]: associated function `baz` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/const-default-bound-non-const-specialized-bound.rs:36:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Baz {
-LL |     fn baz();
-   |           - expected 0 const parameters
-
-error[E0049]: associated function `baz` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/const-default-bound-non-const-specialized-bound.rs:36:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Baz {
-LL |     fn baz();
-   |           - expected 0 const parameters
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 4 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0049`.
diff --git a/tests/ui/traits/const-traits/specialization/const-default-const-specialized.stderr b/tests/ui/traits/const-traits/specialization/const-default-const-specialized.stderr
index 9b2ae8d739c..f127268d2a1 100644
--- a/tests/ui/traits/const-traits/specialization/const-default-const-specialized.stderr
+++ b/tests/ui/traits/const-traits/specialization/const-default-const-specialized.stderr
@@ -1,23 +1,3 @@
-error[E0049]: associated function `value` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/const-default-const-specialized.rs:10:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Value {
-LL |     fn value() -> u32;
-   |             - expected 0 const parameters
-
-error[E0049]: associated function `value` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/const-default-const-specialized.rs:10:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Value {
-LL |     fn value() -> u32;
-   |             - expected 0 const parameters
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
 error[E0015]: cannot call non-const fn `<T as Value>::value` in constant functions
   --> $DIR/const-default-const-specialized.rs:16:5
    |
@@ -30,7 +10,6 @@ help: add `#![feature(effects)]` to the crate attributes to enable
 LL + #![feature(effects)]
    |
 
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0015, E0049.
-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/specialization/default-keyword.rs b/tests/ui/traits/const-traits/specialization/default-keyword.rs
index d9ffd237dce..bc45a70777c 100644
--- a/tests/ui/traits/const-traits/specialization/default-keyword.rs
+++ b/tests/ui/traits/const-traits/specialization/default-keyword.rs
@@ -1,5 +1,4 @@
-//@ known-bug: #110395
-// FIXME check-pass
+//@ check-pass
 
 #![feature(const_trait_impl)]
 #![feature(min_specialization)]
diff --git a/tests/ui/traits/const-traits/specialization/default-keyword.stderr b/tests/ui/traits/const-traits/specialization/default-keyword.stderr
deleted file mode 100644
index 18a25045f4b..00000000000
--- a/tests/ui/traits/const-traits/specialization/default-keyword.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/default-keyword.rs:7:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Foo {
-LL |     fn foo();
-   |           - expected 0 const parameters
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0049`.
diff --git a/tests/ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.rs b/tests/ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.rs
index 219e5f3a600..d80370aee82 100644
--- a/tests/ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.rs
+++ b/tests/ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.rs
@@ -1,7 +1,6 @@
 // Tests that `~const` trait bounds can be used to specialize const trait impls.
 
-//@ known-bug: #110395
-// FIXME check-pass
+//@ check-pass
 
 #![feature(const_trait_impl)]
 #![feature(rustc_attrs)]
diff --git a/tests/ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.stderr b/tests/ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.stderr
deleted file mode 100644
index ecdc7b930e6..00000000000
--- a/tests/ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.stderr
+++ /dev/null
@@ -1,43 +0,0 @@
-error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/issue-95186-specialize-on-tilde-const.rs:14:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Foo {
-LL |     fn foo();
-   |           - expected 0 const parameters
-
-error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/issue-95186-specialize-on-tilde-const.rs:14:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Foo {
-LL |     fn foo();
-   |           - expected 0 const parameters
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/issue-95186-specialize-on-tilde-const.rs:30:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Bar {
-LL |     fn bar() {}
-   |           - expected 0 const parameters
-
-error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/issue-95186-specialize-on-tilde-const.rs:30:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Bar {
-LL |     fn bar() {}
-   |           - expected 0 const parameters
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0049`.
diff --git a/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.rs b/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.rs
index 7514baa2fd5..d97469edaf9 100644
--- a/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.rs
+++ b/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.rs
@@ -2,8 +2,7 @@
 // `T: Foo` in the default impl for the purposes of specialization (i.e., it
 // does not think that the user is attempting to specialize on trait `Foo`).
 
-//@ known-bug: #110395
-// FIXME check-pass
+//@ check-pass
 
 #![feature(rustc_attrs)]
 #![feature(min_specialization)]
diff --git a/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.stderr b/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.stderr
deleted file mode 100644
index 6679bb46537..00000000000
--- a/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.stderr
+++ /dev/null
@@ -1,43 +0,0 @@
-error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/issue-95187-same-trait-bound-different-constness.rs:18:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Bar {
-LL |     fn bar();
-   |           - expected 0 const parameters
-
-error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/issue-95187-same-trait-bound-different-constness.rs:18:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Bar {
-LL |     fn bar();
-   |           - expected 0 const parameters
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0049]: associated function `baz` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/issue-95187-same-trait-bound-different-constness.rs:38:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Baz {
-LL |     fn baz();
-   |           - expected 0 const parameters
-
-error[E0049]: associated function `baz` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/issue-95187-same-trait-bound-different-constness.rs:38:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Baz {
-LL |     fn baz();
-   |           - expected 0 const parameters
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0049`.
diff --git a/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.stderr b/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.stderr
index 7f363922947..a4095d7e8ce 100644
--- a/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.stderr
+++ b/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.stderr
@@ -1,23 +1,3 @@
-error[E0049]: associated function `value` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/non-const-default-const-specialized.rs:9:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Value {
-LL |     fn value() -> u32;
-   |             - expected 0 const parameters
-
-error[E0049]: associated function `value` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/non-const-default-const-specialized.rs:9:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | trait Value {
-LL |     fn value() -> u32;
-   |             - expected 0 const parameters
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
 error[E0015]: cannot call non-const fn `<T as Value>::value` in constant functions
   --> $DIR/non-const-default-const-specialized.rs:15:5
    |
@@ -30,7 +10,6 @@ help: add `#![feature(effects)]` to the crate attributes to enable
 LL + #![feature(effects)]
    |
 
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0015, E0049.
-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/specializing-constness-2.stderr b/tests/ui/traits/const-traits/specializing-constness-2.stderr
index bf273f349b4..8e6f6945a1b 100644
--- a/tests/ui/traits/const-traits/specializing-constness-2.stderr
+++ b/tests/ui/traits/const-traits/specializing-constness-2.stderr
@@ -1,23 +1,3 @@
-error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/specializing-constness-2.rs:9:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | pub trait A {
-LL |     fn a() -> u32;
-   |         - expected 0 const parameters
-
-error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters
-  --> $DIR/specializing-constness-2.rs:9:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ found 1 const parameter
-LL | pub trait A {
-LL |     fn a() -> u32;
-   |         - expected 0 const parameters
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
 error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions
   --> $DIR/specializing-constness-2.rs:27:5
    |
@@ -30,7 +10,6 @@ help: add `#![feature(effects)]` to the crate attributes to enable
 LL + #![feature(effects)]
    |
 
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0015, E0049.
-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/specializing-constness.rs b/tests/ui/traits/const-traits/specializing-constness.rs
index 4501a218ad7..3aabaf137d5 100644
--- a/tests/ui/traits/const-traits/specializing-constness.rs
+++ b/tests/ui/traits/const-traits/specializing-constness.rs
@@ -22,8 +22,6 @@ impl<T: ~const Spec> const A for T {
 
 impl<T: Spec + Sup> A for T {
 //~^ ERROR: cannot specialize
-//~| ERROR: cannot specialize
-//~| ERROR: cannot specialize
 //FIXME(effects) ~| ERROR: missing `~const` qualifier
     fn a() -> u32 {
         3
diff --git a/tests/ui/traits/const-traits/specializing-constness.stderr b/tests/ui/traits/const-traits/specializing-constness.stderr
index 90721af8e5a..e8c4fb0f0c7 100644
--- a/tests/ui/traits/const-traits/specializing-constness.stderr
+++ b/tests/ui/traits/const-traits/specializing-constness.stderr
@@ -18,17 +18,5 @@ error: cannot specialize on const impl with non-const impl
 LL | impl<T: Spec + Sup> A for T {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: cannot specialize on trait `Compat`
-  --> $DIR/specializing-constness.rs:23:16
-   |
-LL | impl<T: Spec + Sup> A for T {
-   |                ^^^
-
-error: cannot specialize on trait `Compat`
-  --> $DIR/specializing-constness.rs:23:9
-   |
-LL | impl<T: Spec + Sup> A for T {
-   |         ^^^^
-
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors; 1 warning emitted
 
diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr
index 029c3b4bde3..a0848fe520e 100644
--- a/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr
+++ b/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr
@@ -20,5 +20,21 @@ LL | trait Bar: ~const Foo {}
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 3 previous errors
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-2.rs:12:19
+   |
+LL | trait Bar: ~const Foo {}
+   |                   ^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-2.rs:12:19
+   |
+LL | trait Bar: ~const Foo {}
+   |                   ^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 5 previous errors
 
diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.rs b/tests/ui/traits/const-traits/super-traits-fail-2.rs
index 93a6f385e47..0ea61f4ae20 100644
--- a/tests/ui/traits/const-traits/super-traits-fail-2.rs
+++ b/tests/ui/traits/const-traits/super-traits-fail-2.rs
@@ -13,7 +13,9 @@ trait Bar: ~const Foo {}
 //[ny,nn]~^ ERROR: `~const` can only be applied to `#[const_trait]`
 //[ny,nn]~| ERROR: `~const` can only be applied to `#[const_trait]`
 //[ny,nn]~| ERROR: `~const` can only be applied to `#[const_trait]`
-//[yn,nn]~^^^^ ERROR: `~const` is not allowed here
+//[ny]~| ERROR: `~const` can only be applied to `#[const_trait]`
+//[ny]~| ERROR: `~const` can only be applied to `#[const_trait]`
+//[yn,nn]~^^^^^^ ERROR: `~const` is not allowed here
 
 const fn foo<T: Bar>(x: &T) {
     x.a();
diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr
index 873c57ec71f..ec6ca107289 100644
--- a/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr
+++ b/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr
@@ -11,23 +11,10 @@ LL | trait Bar: ~const Foo {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `T: ~const Foo` is not satisfied
-  --> $DIR/super-traits-fail-2.rs:19:7
+  --> $DIR/super-traits-fail-2.rs:21:5
    |
 LL |     x.a();
-   |       ^ the trait `Foo` is not implemented for `T`
-   |
-note: required by a bound in `Foo::a`
-  --> $DIR/super-traits-fail-2.rs:6:25
-   |
-LL | #[cfg_attr(any(yy, yn), const_trait)]
-   |                         ^^^^^^^^^^^ required by this bound in `Foo::a`
-LL | trait Foo {
-LL |     fn a(&self);
-   |        - required by a bound in this associated function
-help: consider further restricting this bound
-   |
-LL | const fn foo<T: Bar + Foo>(x: &T) {
-   |                     +++++
+   |     ^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr
index bea3aea2f3a..3fa6256abc3 100644
--- a/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr
+++ b/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr
@@ -1,21 +1,8 @@
 error[E0277]: the trait bound `T: ~const Foo` is not satisfied
-  --> $DIR/super-traits-fail-2.rs:19:7
+  --> $DIR/super-traits-fail-2.rs:21:5
    |
 LL |     x.a();
-   |       ^ the trait `Foo` is not implemented for `T`
-   |
-note: required by a bound in `Foo::a`
-  --> $DIR/super-traits-fail-2.rs:6:25
-   |
-LL | #[cfg_attr(any(yy, yn), const_trait)]
-   |                         ^^^^^^^^^^^ required by this bound in `Foo::a`
-LL | trait Foo {
-LL |     fn a(&self);
-   |        - required by a bound in this associated function
-help: consider further restricting this bound
-   |
-LL | const fn foo<T: Bar + Foo>(x: &T) {
-   |                     +++++
+   |     ^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.nn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.nn.stderr
index f40583f0ca5..294545014bf 100644
--- a/tests/ui/traits/const-traits/super-traits-fail-3.nn.stderr
+++ b/tests/ui/traits/const-traits/super-traits-fail-3.nn.stderr
@@ -33,10 +33,18 @@ LL | trait Bar: ~const Foo {}
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/super-traits-fail-3.rs:20:24
+  --> $DIR/super-traits-fail-3.rs:22:24
    |
 LL | const fn foo<T: ~const Bar>(x: &T) {
    |                        ^^^
 
-error: aborting due to 5 previous errors
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-3.rs:22:24
+   |
+LL | const fn foo<T: ~const Bar>(x: &T) {
+   |                        ^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.ny.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.ny.stderr
index 3f6dfa7b008..54bb6c5ca44 100644
--- a/tests/ui/traits/const-traits/super-traits-fail-3.ny.stderr
+++ b/tests/ui/traits/const-traits/super-traits-fail-3.ny.stderr
@@ -20,5 +20,21 @@ LL | trait Bar: ~const Foo {}
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 3 previous errors
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-3.rs:14:19
+   |
+LL | trait Bar: ~const Foo {}
+   |                   ^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-3.rs:14:19
+   |
+LL | trait Bar: ~const Foo {}
+   |                   ^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 5 previous errors
 
diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.rs b/tests/ui/traits/const-traits/super-traits-fail-3.rs
index b5643b11700..a9b08e6edcd 100644
--- a/tests/ui/traits/const-traits/super-traits-fail-3.rs
+++ b/tests/ui/traits/const-traits/super-traits-fail-3.rs
@@ -15,10 +15,13 @@ trait Bar: ~const Foo {}
 //[ny,nn]~^ ERROR: `~const` can only be applied to `#[const_trait]`
 //[ny,nn]~| ERROR: `~const` can only be applied to `#[const_trait]`
 //[ny,nn]~| ERROR: `~const` can only be applied to `#[const_trait]`
-//[yn,nn]~^^^^ ERROR: `~const` is not allowed here
+//[ny]~| ERROR: `~const` can only be applied to `#[const_trait]`
+//[ny]~| ERROR: `~const` can only be applied to `#[const_trait]`
+//[yn,nn]~^^^^^^ ERROR: `~const` is not allowed here
 
 const fn foo<T: ~const Bar>(x: &T) {
     //[yn,nn]~^ ERROR: `~const` can only be applied to `#[const_trait]`
+    //[yn,nn]~| ERROR: `~const` can only be applied to `#[const_trait]`
     x.a();
     //[yn]~^ ERROR: the trait bound `T: ~const Foo` is not satisfied
 }
diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr
index bbc95948a59..b6747d10e83 100644
--- a/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr
+++ b/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr
@@ -11,30 +11,25 @@ LL | trait Bar: ~const Foo {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/super-traits-fail-3.rs:20:24
+  --> $DIR/super-traits-fail-3.rs:22:24
    |
 LL | const fn foo<T: ~const Bar>(x: &T) {
    |                        ^^^
 
-error[E0277]: the trait bound `T: ~const Foo` is not satisfied
-  --> $DIR/super-traits-fail-3.rs:22:7
-   |
-LL |     x.a();
-   |       ^ the trait `Foo` is not implemented for `T`
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-3.rs:22:24
    |
-note: required by a bound in `Foo::a`
-  --> $DIR/super-traits-fail-3.rs:8:25
+LL | const fn foo<T: ~const Bar>(x: &T) {
+   |                        ^^^
    |
-LL | #[cfg_attr(any(yy, yn), const_trait)]
-   |                         ^^^^^^^^^^^ required by this bound in `Foo::a`
-LL | trait Foo {
-LL |     fn a(&self);
-   |        - required by a bound in this associated function
-help: consider further restricting this bound
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: the trait bound `T: ~const Foo` is not satisfied
+  --> $DIR/super-traits-fail-3.rs:25:5
    |
-LL | const fn foo<T: ~const Bar + Foo>(x: &T) {
-   |                            +++++
+LL |     x.a();
+   |     ^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/super-traits-fail.rs b/tests/ui/traits/const-traits/super-traits-fail.rs
index da41d7fcc72..c07619fbf62 100644
--- a/tests/ui/traits/const-traits/super-traits-fail.rs
+++ b/tests/ui/traits/const-traits/super-traits-fail.rs
@@ -1,4 +1,3 @@
-//~ ERROR the trait bound
 //@ compile-flags: -Znext-solver
 
 #![allow(incomplete_features)]
diff --git a/tests/ui/traits/const-traits/super-traits-fail.stderr b/tests/ui/traits/const-traits/super-traits-fail.stderr
index 3870f0f722f..7a734a6c9f1 100644
--- a/tests/ui/traits/const-traits/super-traits-fail.stderr
+++ b/tests/ui/traits/const-traits/super-traits-fail.stderr
@@ -1,24 +1,9 @@
-error[E0277]: the trait bound `Bar::{synthetic#0}: TyCompat<Foo::{synthetic#0}>` is not satisfied
-  --> $DIR/super-traits-fail.rs:19:12
+error[E0277]: the trait bound `S: ~const Foo` is not satisfied
+  --> $DIR/super-traits-fail.rs:18:20
    |
 LL | impl const Bar for S {}
-   |            ^^^ the trait `TyCompat<Foo::{synthetic#0}>` is not implemented for `Bar::{synthetic#0}`, which is required by `S: Bar`
-   |
-   = help: the trait `Bar` is implemented for `S`
-note: required for `S` to implement `Bar`
-  --> $DIR/super-traits-fail.rs:12:7
-   |
-LL | trait Bar: ~const Foo {}
-   |       ^^^
-
-error[E0277]: the trait bound `Maybe: TyCompat<Foo::{synthetic#0}>` is not satisfied
-   |
-note: required by a bound in `Bar::{synthetic#0}`
-  --> $DIR/super-traits-fail.rs:12:12
-   |
-LL | trait Bar: ~const Foo {}
-   |            ^^^^^^^^^^ required by this bound in `Bar::{synthetic#0}`
+   |                    ^
 
-error: aborting due to 2 previous errors
+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/tilde-const-and-const-params.rs b/tests/ui/traits/const-traits/tilde-const-and-const-params.rs
index 4b720b534a4..f6a7c7c1746 100644
--- a/tests/ui/traits/const-traits/tilde-const-and-const-params.rs
+++ b/tests/ui/traits/const-traits/tilde-const-and-const-params.rs
@@ -8,7 +8,6 @@ struct Foo<const N: usize>;
 impl<const N: usize> Foo<N> {
     fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
         //~^ ERROR `~const` is not allowed here
-        //~| ERROR mismatched types
         Foo
     }
 }
@@ -26,7 +25,6 @@ impl const Add42 for () {
 
 fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
     //~^ ERROR `~const` is not allowed here
-    //~| ERROR mismatched types
     Foo
 }
 
diff --git a/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr b/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr
index 73526a26e08..84a425f6791 100644
--- a/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr
+++ b/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr
@@ -11,13 +11,13 @@ LL |     fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
    |        ^^^
 
 error: `~const` is not allowed here
-  --> $DIR/tilde-const-and-const-params.rs:27:11
+  --> $DIR/tilde-const-and-const-params.rs:26:11
    |
 LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
    |           ^^^^^^
    |
 note: this function is not `const`, so it cannot have `~const` trait bounds
-  --> $DIR/tilde-const-and-const-params.rs:27:4
+  --> $DIR/tilde-const-and-const-params.rs:26:4
    |
 LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
    |    ^^^
@@ -27,24 +27,5 @@ error: using `#![feature(effects)]` without enabling next trait solver globally
    = note: the next trait solver must be enabled globally for the effects feature to work correctly
    = help: use `-Znext-solver` to enable
 
-error[E0308]: mismatched types
-  --> $DIR/tilde-const-and-const-params.rs:27:61
-   |
-LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
-   |                                                             ^^^^^^^^^ expected `false`, found `true`
-   |
-   = note: expected constant `false`
-              found constant `true`
-
-error[E0308]: mismatched types
-  --> $DIR/tilde-const-and-const-params.rs:9:44
-   |
-LL |     fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
-   |                                            ^^^^^^^^^ expected `false`, found `true`
-   |
-   = note: expected constant `false`
-              found constant `true`
-
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/const-traits/tilde-const-in-struct-args.rs b/tests/ui/traits/const-traits/tilde-const-in-struct-args.rs
new file mode 100644
index 00000000000..4722be955e9
--- /dev/null
+++ b/tests/ui/traits/const-traits/tilde-const-in-struct-args.rs
@@ -0,0 +1,21 @@
+//@ compile-flags: -Znext-solver
+//@ known-bug: #132067
+//@ check-pass
+
+#![feature(const_trait_impl, effects)]
+
+struct S;
+#[const_trait]
+trait Trait<const N: u32> {}
+
+const fn f<
+    T: Trait<
+        {
+            struct I<U: ~const Trait<0>>(U);
+            0
+        },
+    >,
+>() {
+}
+
+pub fn main() {}
diff --git a/tests/ui/traits/const-traits/tilde-const-in-struct-args.stderr b/tests/ui/traits/const-traits/tilde-const-in-struct-args.stderr
new file mode 100644
index 00000000000..a9759f10d06
--- /dev/null
+++ b/tests/ui/traits/const-traits/tilde-const-in-struct-args.stderr
@@ -0,0 +1,11 @@
+warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/tilde-const-in-struct-args.rs:5:30
+   |
+LL | #![feature(const_trait_impl, effects)]
+   |                              ^^^^^^^
+   |
+   = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/const-traits/trait-where-clause-const.rs b/tests/ui/traits/const-traits/trait-where-clause-const.rs
index 8ca9b7cc7aa..61e2bc38426 100644
--- a/tests/ui/traits/const-traits/trait-where-clause-const.rs
+++ b/tests/ui/traits/const-traits/trait-where-clause-const.rs
@@ -20,11 +20,9 @@ trait Foo {
 const fn test1<T: ~const Foo + Bar>() {
     T::a();
     T::b();
-    //~^ ERROR mismatched types
-    //~| ERROR the trait bound
+    //~^ ERROR the trait bound
     T::c::<T>();
-    //~^ ERROR mismatched types
-    //~| ERROR the trait bound
+    //~^ ERROR the trait bound
 }
 
 const fn test2<T: ~const Foo + ~const Bar>() {
diff --git a/tests/ui/traits/const-traits/trait-where-clause-const.stderr b/tests/ui/traits/const-traits/trait-where-clause-const.stderr
index eaa981ec744..30a7ef1fd0d 100644
--- a/tests/ui/traits/const-traits/trait-where-clause-const.stderr
+++ b/tests/ui/traits/const-traits/trait-where-clause-const.stderr
@@ -1,52 +1,15 @@
-error[E0277]: the trait bound `T: Foo` is not satisfied
+error[E0277]: the trait bound `T: ~const Bar` is not satisfied
   --> $DIR/trait-where-clause-const.rs:22:5
    |
 LL |     T::b();
-   |     ^ the trait `Foo` is not implemented for `T`
-   |
-note: required by a bound in `Foo::b`
-  --> $DIR/trait-where-clause-const.rs:13:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ required by this bound in `Foo::b`
-...
-LL |     fn b() where Self: ~const Bar;
-   |        - required by a bound in this associated function
-
-error[E0308]: mismatched types
-  --> $DIR/trait-where-clause-const.rs:22:5
-   |
-LL |     T::b();
-   |     ^^^^^^ expected `host`, found `true`
-   |
-   = note: expected constant `host`
-              found constant `true`
+   |     ^^^^^^
 
-error[E0277]: the trait bound `T: Foo` is not satisfied
-  --> $DIR/trait-where-clause-const.rs:25:5
+error[E0277]: the trait bound `T: ~const Bar` is not satisfied
+  --> $DIR/trait-where-clause-const.rs:24:5
    |
 LL |     T::c::<T>();
-   |     ^ the trait `Foo` is not implemented for `T`
-   |
-note: required by a bound in `Foo::c`
-  --> $DIR/trait-where-clause-const.rs:13:1
-   |
-LL | #[const_trait]
-   | ^^^^^^^^^^^^^^ required by this bound in `Foo::c`
-...
-LL |     fn c<T: ~const Bar>();
-   |        - required by a bound in this associated function
-
-error[E0308]: mismatched types
-  --> $DIR/trait-where-clause-const.rs:25:5
-   |
-LL |     T::c::<T>();
-   |     ^^^^^^^^^^^ expected `host`, found `true`
-   |
-   = note: expected constant `host`
-              found constant `true`
+   |     ^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0277, E0308.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr
index 848aa68689b..e0cf062ad95 100644
--- a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr
+++ b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr
@@ -6,41 +6,30 @@ LL | #![feature(const_trait_impl, effects, generic_const_exprs)]
    |
    = help: remove one of these features
 
-error[E0308]: mismatched types
+error[E0277]: the trait bound `T: const Trait` is not satisfied
   --> $DIR/unsatisfied-const-trait-bound.rs:29:37
    |
 LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
-   |                                     ^^^^^^^^^ expected `false`, found `true`
-   |
-   = note: expected constant `false`
-              found constant `true`
+   |                                     ^^^^^^^^^
 
-error[E0308]: mismatched types
+error[E0277]: the trait bound `T: const Trait` is not satisfied
   --> $DIR/unsatisfied-const-trait-bound.rs:33:50
    |
 LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
-   |                                                  ^^^^^^^^^ expected `false`, found `host`
-   |
-   = note: expected constant `false`
-              found constant `host`
+   |                                                  ^^^^^^^^^
 
 error[E0277]: the trait bound `Ty: const Trait` is not satisfied
-  --> $DIR/unsatisfied-const-trait-bound.rs:22:15
+  --> $DIR/unsatisfied-const-trait-bound.rs:22:5
    |
 LL |     require::<Ty>();
-   |               ^^ the trait `Trait` is not implemented for `Ty`
+   |     ^^^^^^^^^^^^^^^
    |
 note: required by a bound in `require`
   --> $DIR/unsatisfied-const-trait-bound.rs:8:15
    |
 LL | fn require<T: const Trait>() {}
    |               ^^^^^^^^^^^ required by this bound in `require`
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | fn main() where Ty: Trait {
-   |           +++++++++++++++
 
 error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0277, E0308.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0277`.