diff options
Diffstat (limited to 'compiler/rustc_middle/src/ty/mod.rs')
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 76 |
1 files changed, 56 insertions, 20 deletions
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 038de42a6f1..7428f34153c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -588,7 +588,18 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> { #[rustc_diagnostic_item = "Ty"] pub type Ty<'tcx> = &'tcx TyS<'tcx>; -#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + TyEncodable, + TyDecodable, + TypeFoldable, + HashStable +)] pub struct UpvarPath { pub hir_id: hir::HirId, } @@ -596,7 +607,7 @@ pub struct UpvarPath { /// Upvars do not get their own `NodeId`. Instead, we use the pair of /// the original var ID (that is, the root variable that is referenced /// by the upvar) and the ID of the closure expression. -#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub struct UpvarId { pub var_path: UpvarPath, pub closure_expr_id: LocalDefId, @@ -608,7 +619,7 @@ impl UpvarId { } } -#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable)] +#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, TypeFoldable, Copy, HashStable)] pub enum BorrowKind { /// Data must be immutable and is aliasable. ImmBorrow, @@ -662,7 +673,7 @@ pub enum BorrowKind { /// Information describing the capture of an upvar. This is computed /// during `typeck`, specifically by `regionck`. -#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)] +#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub enum UpvarCapture<'tcx> { /// Upvar is captured by value. This is always true when the /// closure is labeled `move`, but can also be true in other cases @@ -679,7 +690,7 @@ pub enum UpvarCapture<'tcx> { ByRef(UpvarBorrow<'tcx>), } -#[derive(PartialEq, Clone, Copy, TyEncodable, TyDecodable, HashStable)] +#[derive(PartialEq, Clone, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub struct UpvarBorrow<'tcx> { /// The kind of borrow: by-ref upvars have access to shared /// immutable borrows, which are not part of the normal language @@ -706,7 +717,7 @@ pub type RootVariableMinCaptureList<'tcx> = FxIndexMap<hir::HirId, MinCaptureLis pub type MinCaptureList<'tcx> = Vec<CapturedPlace<'tcx>>; /// A `Place` and the corresponding `CaptureInfo`. -#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)] +#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub struct CapturedPlace<'tcx> { pub place: HirPlace<'tcx>, pub info: CaptureInfo<'tcx>, @@ -715,7 +726,7 @@ pub struct CapturedPlace<'tcx> { /// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move) /// for a particular capture as well as identifying the part of the source code /// that triggered this capture to occur. -#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)] +#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub struct CaptureInfo<'tcx> { /// Expr Id pointing to use that resulted in selecting the current capture kind /// @@ -1599,34 +1610,59 @@ pub struct BoundConst<'tcx> { pub type PlaceholderConst<'tcx> = Placeholder<BoundConst<'tcx>>; -/// A `DefId` which is potentially bundled with its corresponding generic parameter -/// in case `did` is a const argument. +/// A `DefId` which, in case it is a const argument, is potentially bundled with +/// the `DefId` of the generic parameter it instantiates. /// -/// This is used to prevent cycle errors during typeck -/// as `type_of(const_arg)` depends on `typeck(owning_body)` -/// which once again requires the type of its generic arguments. -/// -/// Luckily we only need to deal with const arguments once we -/// know their corresponding parameters. We (ab)use this by -/// calling `type_of(param_did)` for these arguments. +/// This is used to avoid calls to `type_of` for const arguments during typeck +/// which cause cycle errors. /// /// ```rust /// #![feature(const_generics)] /// /// struct A; /// impl A { -/// fn foo<const N: usize>(&self) -> usize { N } +/// fn foo<const N: usize>(&self) -> [u8; N] { [0; N] } +/// // ^ const parameter /// } /// struct B; /// impl B { -/// fn foo<const N: u8>(&self) -> usize { 42 } +/// fn foo<const M: u8>(&self) -> usize { 42 } +/// // ^ const parameter /// } /// /// fn main() { /// let a = A; -/// a.foo::<7>(); +/// let _b = a.foo::<{ 3 + 7 }>(); +/// // ^^^^^^^^^ const argument /// } /// ``` +/// +/// Let's look at the call `a.foo::<{ 3 + 7 }>()` here. We do not know +/// which `foo` is used until we know the type of `a`. +/// +/// We only know the type of `a` once we are inside of `typeck(main)`. +/// We also end up normalizing the type of `_b` during `typeck(main)` which +/// requires us to evaluate the const argument. +/// +/// To evaluate that const argument we need to know its type, +/// which we would get using `type_of(const_arg)`. This requires us to +/// resolve `foo` as it can be either `usize` or `u8` in this example. +/// However, resolving `foo` once again requires `typeck(main)` to get the type of `a`, +/// which results in a cycle. +/// +/// In short we must not call `type_of(const_arg)` during `typeck(main)`. +/// +/// When first creating the `ty::Const` of the const argument inside of `typeck` we have +/// already resolved `foo` so we know which const parameter this argument instantiates. +/// This means that we also know the expected result of `type_of(const_arg)` even if we +/// aren't allowed to call that query: it is equal to `type_of(const_param)` which is +/// trivial to compute. +/// +/// If we now want to use that constant in a place which potentionally needs its type +/// we also pass the type of its `const_param`. This is the point of `WithOptConstParam`, +/// except that instead of a `Ty` we bundle the `DefId` of the const parameter. +/// Meaning that we need to use `type_of(const_param_did)` if `const_param_did` is `Some` +/// to get the type of `did`. #[derive(Copy, Clone, Debug, TypeFoldable, Lift, TyEncodable, TyDecodable)] #[derive(PartialEq, Eq, PartialOrd, Ord)] #[derive(Hash, HashStable)] @@ -1637,7 +1673,7 @@ pub struct WithOptConstParam<T> { /// /// Note that even if `did` is a const argument, this may still be `None`. /// All queries taking `WithOptConstParam` start by calling `tcx.opt_const_param_of(def.did)` - /// to potentially update `param_did` in case it `None`. + /// to potentially update `param_did` in the case it is `None`. pub const_param_did: Option<DefId>, } |
