|
| 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