Skip to content

Commit 09bf2bd

Browse files
lcnrnikomatsakis
andauthored
ty::Unevaluated: dealing with unused substs (#1190)
* unused ct substs * q * q * Update src/constants.md Co-authored-by: Niko Matsakis <[email protected]>
1 parent 8c39edb commit 09bf2bd

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

src/constants.md

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Constants in the type system
2+
3+
Constants used in the type system are represented as [`ty::Const`].
4+
The variants of their [`ty::ConstKind`] mostly mirror the variants of [`ty::TyKind`]
5+
with the two *additional* variants being `ConstKind::Value` and `ConstKind::Unevaluated`.
6+
7+
8+
## Unevaluated constants
9+
10+
*This section talks about what's happening with `feature(const_generics)` enabled.
11+
On stable we do not yet supply any generic parameters to anonymous constants,
12+
avoiding most of the issues mentioned here.*
13+
14+
Unless a constant is either a simple literal, e.g. `[u8; 3]` or `foo::<{ 'c' }>()`,
15+
or a generic parameter, e.g. `[u8; N]`, converting a constant to its [`ty::Const`] representation
16+
returns an unevaluated constant. Even fully concrete constants which do not depend on a
17+
generic parameter are not evaluated right away.
18+
19+
We do not eagerly evaluate constant as they can be used in the `where`-clauses of their
20+
parent item, for example:
21+
22+
```rust
23+
#[feature(const_generics, const_evaluatable_checked)]
24+
fn foo<T: Trait>()
25+
where
26+
[u8; <T as Trait>::ASSOC + 1]: SomeOtherTrait,
27+
{}
28+
```
29+
30+
The constant `<T as Trait>::ASSOC + 1` depends on the `T: Trait` bound of
31+
its parents caller bounds, but is also part of another bound itself.
32+
If we were to eagerly evaluate this constant while computing its parents bounds
33+
this would cause a query cycle.
34+
35+
### Generic arguments of anonymous constants
36+
37+
Anonymous constants inherit the generic parameters of their parent, which is
38+
why the array length in `foo<const N: usize>() -> [u8; N + 1]` can use `N`.
39+
40+
Without any manual adjustments, this causes us to include parameters even if
41+
the constant doesn't use them in any way. This can cause
42+
[some interesting errors](pcg-unused-substs) and breaks some already stable code.
43+
44+
To deal with this, we intend to look at the generic parameters explicitly mentioned
45+
by the constants and then search the predicates of its parents to figure out which
46+
of the other generic parameters are reachable by our constant.
47+
48+
**TODO**: Expand this section once the parameter filtering is implemented.
49+
50+
As constants can be part of their parents `where`-clauses, we mention unevaluated
51+
constants in their parents predicates. It is therefore necessary to mention unevaluated
52+
constants before we have computed the generic parameters
53+
available to these constants.
54+
55+
To do this unevaluated constants start out with [`substs_`] being `None` while assuming
56+
that their generic arguments could be arbitrary generic parameters.
57+
When first accessing the generic arguments of an unevaluated constants, we then replace
58+
`substs_` with the actual default arguments of a constants, which are the generic parameters
59+
of their parent we assume to be used by this constant.
60+
61+
[`ty::Const`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Const.html
62+
[`ty::ConstKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.ConstKind.html
63+
[`ty::TyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html
64+
[pcg-unused-substs]: https://github.com/rust-lang/project-const-generics/blob/master/design-docs/anon-const-substs.md#unused-substs
65+
[`substs_`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/consts/kind/struct.Unevaluated.html#structfield.substs_

0 commit comments

Comments
 (0)