Home Explore Blog CI



rustc

2nd chunk of `src/effects.md`
f9d11f5ae02ef693e393782758f98d36938da2c35a8c6f870000000100000e94
prove that `T` has a const implementation of `Default`.

## Enforcement of `const_conditions`

`const_conditions` are currently checked in various places. 

Every call in HIR from a const context (which includes `const fn` and `const`
items) will check that `const_conditions` of the function we are calling hold.
This is done in [`FnCtxt::enforce_context_effects`]. Note that we don't check
if the function is only referred to but not called, as the following code needs
to compile:

```rust
const fn hi<T: ~const Default>() -> T {
    T::default()
}
const X: fn() -> u32 = hi::<u32>;
```

For a trait `impl` to be well-formed, we must be able to prove the
`const_conditions` of the trait from the `impl`'s environment. This is checked
in [`wfcheck::check_impl`].

Here's an example:

```rust
#[const_trait]
trait Bar {}
#[const_trait]
trait Foo: ~const Bar {}
// `const_conditions` contains `HostEffect(Self: Bar, maybe)`

impl const Bar for () {}
impl const Foo for () {}
// ^ here we check `const_conditions` for the impl to be well-formed
```

Methods of trait impls must not have stricter bounds than the method of the
trait that they are implementing. To check that the methods are compatible, a
hybrid environment is constructed with the predicates of the `impl` plus the
predicates of the trait method, and we attempt to prove the predicates of the
impl method. We do the same for `const_conditions`:

```rust
#[const_trait]
trait Foo {
    fn hi<T: ~const Default>();
}

impl<T: ~const Clone> Foo for Vec<T> {
    fn hi<T: ~const PartialEq>();
    // ^ we can't prove `T: ~const PartialEq` given `T: ~const Clone` and
    // `T: ~const Default`, therefore we know that the method on the impl
    // is stricter than the method on the trait.
}
```

These checks are done in [`compare_method_predicate_entailment`]. A similar
function that does the same check for associated types is called
[`compare_type_predicate_entailment`]. Both of these need to consider
`const_conditions` when in const contexts.

In MIR, as part of const checking, `const_conditions` of items that are called
are revalidated again in [`Checker::revalidate_conditional_constness`].


## `explicit_implied_const_bounds` on associated types and traits

Bounds on associated types, opaque types, and supertraits such as
```rust
trait Foo: ~const PartialEq {
    type X: ~const PartialEq;
}

fn foo() -> impl ~const PartialEq {
    // ^ unimplemented syntax
}
```

Have their bounds represented differently. Unlike `const_conditions` which need
to be proved for callers, and can be assumed inside the definition (e.g. trait
bounds on functions), these bounds need to be proved at definition (at the impl,
or when returning the opaque) but can be assumed for callers. The non-const
equivalent of these bounds are called [`explicit_item_bounds`].

These bounds are checked in [`compare_impl_item::check_type_bounds`] for HIR
typeck, [`evaluate_host_effect_from_item_bounds`] in the old solver and
[`consider_additional_alias_assumptions`] in the new solver.


## Proving `HostEffectPredicate`s

`HostEffectPredicate`s are implemented both in the [old solver] and the [new
trait solver]. In general, we can prove a `HostEffect` predicate when either of
these conditions are met:

* The predicate can be assumed from caller bounds;
* The type has a `const` `impl` for the trait, *and* that const conditions on
the impl holds, *and* that the `explicit_implied_const_bounds` on the trait
holds; or
* The type has a built-in implementation for the trait in const contexts. For
example, `Fn` may be implemented by function items if their const conditions
are satisfied, or `Destruct` is implemented in const contexts if the type can
be dropped at compile time.


Title: Enforcement of Const Conditions and Proving HostEffectPredicates
Summary
This section details how `const_conditions` are enforced in various contexts like HIR calls, trait `impl`s, and method implementations, including checks for stricter bounds and revalidation in MIR. It then discusses how associated types, opaque types, and supertraits handle bounds differently via `explicit_implied_const_bounds`. Finally, it outlines the conditions under which a `HostEffectPredicate` can be proven, including assumptions from caller bounds, the presence of a const `impl` with valid const conditions, and built-in implementations in const contexts.