Add some more info to param_env (#610)
* add some more info to param_env * Remove some trailing spaces Co-authored-by: Yuki Okushi <huyuumi.dev@gmail.com>
This commit is contained in:
parent
5f6514575c
commit
fc6fe52313
|
|
@ -3,28 +3,67 @@
|
||||||
When working with associated and/or or generic items (types, constants,
|
When working with associated and/or or generic items (types, constants,
|
||||||
functions/methods) it is often relevant to have more information about the
|
functions/methods) it is often relevant to have more information about the
|
||||||
`Self` or generic parameters. Trait bounds and similar information is encoded in
|
`Self` or generic parameters. Trait bounds and similar information is encoded in
|
||||||
the `ParamEnv`. Often this is not enough information to obtain things like the
|
the [`ParamEnv`][pe]. Often this is not enough information to obtain things like the
|
||||||
type's `Layout`, but you can do all kinds of other checks on it (e.g. whether a
|
type's `Layout`, but you can do all kinds of other checks on it (e.g. whether a
|
||||||
type implements `Copy`) or you can evaluate an associated constant whose value
|
type implements `Copy`) or you can evaluate an associated constant whose value
|
||||||
does not depend on anything from the parameter environment.
|
does not depend on anything from the parameter environment.
|
||||||
|
|
||||||
|
[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.ParamEnv.html
|
||||||
|
|
||||||
For example if you have a function
|
For example if you have a function
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn foo<T: Copy>(t: T) {
|
fn foo<T: Copy>(t: T) { ... }
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
the parameter environment for that function is `[T: Copy]`. This means any
|
the parameter environment for that function is `[T: Copy]`. This means any
|
||||||
evaluation within this function will, when accessing the type `T`, know about
|
evaluation within this function will, when accessing the type `T`, know about
|
||||||
its `Copy` bound via the parameter environment.
|
its `Copy` bound via the parameter environment.
|
||||||
|
|
||||||
Although you can obtain a valid `ParamEnv` for any item via
|
You can get the parameter environment for a `def_id` using the
|
||||||
`tcx.param_env(def_id)`, this `ParamEnv` can be too generic for your use case.
|
[`param_env`][query] query. However, this `ParamEnv` can be too generic for
|
||||||
Using the `ParamEnv` from the surrounding context can allow you to evaluate more
|
your use case. Using the `ParamEnv` from the surrounding context can allow you
|
||||||
things.
|
to evaluate more things. For example, suppose we had something the following:
|
||||||
|
|
||||||
|
[query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ty/ty/fn.param_env.html
|
||||||
|
|
||||||
|
```rust
|
||||||
|
trait Foo {
|
||||||
|
type Assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Bar { }
|
||||||
|
|
||||||
|
trait Baz {
|
||||||
|
fn stuff() -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo<T>(t: T)
|
||||||
|
where
|
||||||
|
T: Foo,
|
||||||
|
<T as Foo>::Assoc: Bar
|
||||||
|
{
|
||||||
|
bar::<T::Assoc>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bar<T: Baz>() {
|
||||||
|
if T::stuff() { mep() } else { mop() }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
We may know some things inside `bar` that we wouldn't know if we just fetched
|
||||||
|
`bar`'s param env because of the `<T as Foo>::Assoc: Bar` bound in `foo`. This
|
||||||
|
is a contrived example that makes no sense in our existing analyses, but we may
|
||||||
|
run into similar cases when doing analyses with associated constants on generic
|
||||||
|
traits or traits with assoc types.
|
||||||
|
|
||||||
|
## Bundling
|
||||||
|
|
||||||
Another great thing about `ParamEnv` is that you can use it to bundle the thing
|
Another great thing about `ParamEnv` is that you can use it to bundle the thing
|
||||||
depending on generic parameters (e.g. a `Ty`) by calling `param_env.and(ty)`.
|
depending on generic parameters (e.g. a `Ty`) by calling the [`and`][and]
|
||||||
This will produce a `ParamEnvAnd<Ty>`, making clear that you should probably not
|
method. This will produce a [`ParamEnvAnd<Ty>`][pea], making clear that you
|
||||||
be using the inner value without taking care to also use the `ParamEnv`.
|
should probably not be using the inner value without taking care to also use
|
||||||
|
the [`ParamEnv`][pe].
|
||||||
|
|
||||||
|
[and]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.ParamEnv.html#method.and
|
||||||
|
[pea]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.ParamEnvAnd.html
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue