# Effects and const condition checking
## The `HostEffect` predicate
[`HostEffectPredicate`]s are a kind of predicate from `~const Tr` or `const Tr`
bounds. It has a trait reference, and a `constness` which could be `Maybe` or
`Const` depending on the bound. Because `~const Tr`, or rather `Maybe` bounds
apply differently based on whichever contexts they are in, they have different
behavior than normal bounds. Where normal trait bounds on a function such as
`T: Tr` are collected within the [`predicates_of`] query to be proven when a
function is called and to be assumed within the function, bounds such as
`T: ~const Tr` will behave as a normal trait bound and add `T: Tr` to the result
from `predicates_of`, but also adds a `HostEffectPredicate` to the
[`const_conditions`] query.
On the other hand, `T: const Tr` bounds do not change meaning across contexts,
therefore they will result in `HostEffect(T: Tr, const)` being added to
`predicates_of`, and not `const_conditions`.
## The `const_conditions` query
`predicates_of` represents a set of predicates that need to be proven to use an
item. For example, to use `foo` in the example below:
```rust
fn foo<T>() where T: Default {}
```
We must be able to prove that `T` implements `Default`. In a similar vein,
`const_conditions` represents a set of predicates that need to be proven to use
an item *in const contexts*. If we adjust the example above to use `const` trait
bounds:
```rust
const fn foo<T>() where T: ~const Default {}
```
Then `foo` would get a `HostEffect(T: Default, maybe)` in the `const_conditions`
query, suggesting that in order to call `foo` from const contexts, one must
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