|
3 | 3 | When working with associated and/or or generic items (types, constants,
|
4 | 4 | functions/methods) it is often relevant to have more information about the
|
5 | 5 | `Self` or generic parameters. Trait bounds and similar information is encoded in
|
6 |
| -the `ParamEnv`. Often this is not enough information to obtain things like the |
| 6 | +the [`ParamEnv`][pe]. Often this is not enough information to obtain things like the |
7 | 7 | type's `Layout`, but you can do all kinds of other checks on it (e.g. whether a
|
8 | 8 | type implements `Copy`) or you can evaluate an associated constant whose value
|
9 | 9 | does not depend on anything from the parameter environment.
|
10 | 10 |
|
| 11 | +[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.ParamEnv.html |
| 12 | + |
11 | 13 | For example if you have a function
|
12 | 14 |
|
13 | 15 | ```rust
|
14 |
| -fn foo<T: Copy>(t: T) { |
15 |
| -} |
| 16 | +fn foo<T: Copy>(t: T) { ... } |
16 | 17 | ```
|
17 | 18 |
|
18 | 19 | the parameter environment for that function is `[T: Copy]`. This means any
|
19 | 20 | evaluation within this function will, when accessing the type `T`, know about
|
20 | 21 | its `Copy` bound via the parameter environment.
|
21 | 22 |
|
22 |
| -Although you can obtain a valid `ParamEnv` for any item via |
23 |
| -`tcx.param_env(def_id)`, this `ParamEnv` can be too generic for your use case. |
24 |
| -Using the `ParamEnv` from the surrounding context can allow you to evaluate more |
25 |
| -things. |
| 23 | +You can get the parameter environment for a `def_id` using the |
| 24 | +[`param_env`][query] query. However, this `ParamEnv` can be too generic for |
| 25 | +your use case. Using the `ParamEnv` from the surrounding context can allow you |
| 26 | +to evaluate more things. For example, suppose we had something the following: |
| 27 | + |
| 28 | +[query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ty/ty/fn.param_env.html |
| 29 | + |
| 30 | +```rust |
| 31 | +trait Foo { |
| 32 | + type Assoc; |
| 33 | +} |
| 34 | + |
| 35 | +trait Bar { } |
| 36 | + |
| 37 | +trait Baz { |
| 38 | + fn stuff() -> bool; |
| 39 | +} |
| 40 | + |
| 41 | +fn foo<T>(t: T) |
| 42 | +where |
| 43 | + T: Foo, |
| 44 | + <T as Foo>::Assoc: Bar |
| 45 | +{ |
| 46 | + bar::<T::Assoc>() |
| 47 | +} |
| 48 | + |
| 49 | +fn bar<T: Baz>() { |
| 50 | + if T::stuff() { mep() } else { mop() } |
| 51 | +} |
| 52 | +``` |
| 53 | + |
| 54 | +We may know some things inside `bar` that we wouldn't know if we just fetched |
| 55 | +`bar`'s param env because of the `<T as Foo>::Assoc: Bar` bound in `foo`. This |
| 56 | +is a contrived example that makes no sense in our existing analyses, but we may |
| 57 | +run into similar cases when doing analyses with associated constants on generic |
| 58 | +traits or traits with assoc types. |
| 59 | + |
| 60 | +## Bundling |
26 | 61 |
|
27 | 62 | Another great thing about `ParamEnv` is that you can use it to bundle the thing
|
28 |
| -depending on generic parameters (e.g. a `Ty`) by calling `param_env.and(ty)`. |
29 |
| -This will produce a `ParamEnvAnd<Ty>`, making clear that you should probably not |
30 |
| -be using the inner value without taking care to also use the `ParamEnv`. |
| 63 | +depending on generic parameters (e.g. a `Ty`) by calling the [`and`][and] |
| 64 | +method. This will produce a [`ParamEnvAnd<Ty>`][pea], making clear that you |
| 65 | +should probably not be using the inner value without taking care to also use |
| 66 | +the [`ParamEnv`][pe]. |
| 67 | + |
| 68 | +[and]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.ParamEnv.html#method.and |
| 69 | +[pea]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.ParamEnvAnd.html |
0 commit comments