diff options
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
16 files changed, 301 insertions, 215 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index dd11f58ca19..1fe7baaa250 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -17,7 +17,9 @@ use crate::bounds::Bounds; use crate::errors; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { - /// Sets `implicitly_sized` to true on `Bounds` if necessary + /// Add a `Sized` bound to the `bounds` if appropriate. + /// + /// Doesn't add the bound if the HIR bounds contain any of `Sized`, `?Sized` or `!Sized`. pub(crate) fn add_sized_bound( &self, bounds: &mut Bounds<'tcx>, @@ -101,21 +103,27 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - /// This helper takes a *converted* parameter type (`param_ty`) - /// and an *unconverted* list of bounds: + /// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any. + /// + /// ### Examples /// - /// ```text - /// fn foo<T: Debug> - /// ^ ^^^^^ `ast_bounds` parameter, in HIR form - /// | - /// `param_ty`, in ty form + /// ```ignore (illustrative) + /// fn foo<T>() where for<'a> T: Trait<'a> + Copy {} + /// // ^^^^^^^ ^ ^^^^^^^^^^^^^^^^ `ast_bounds`, in HIR form + /// // | | + /// // | `param_ty`, in ty form + /// // `bound_vars`, in ty form + /// + /// fn bar<T>() where T: for<'a> Trait<'a> + Copy {} // no overarching `bound_vars` here! + /// // ^ ^^^^^^^^^^^^^^^^^^^^^^^^ `ast_bounds`, in HIR form + /// // | + /// // `param_ty`, in ty form /// ``` /// - /// It adds these `ast_bounds` into the `bounds` structure. + /// ### A Note on Binders /// - /// **A note on binders:** there is an implied binder around - /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref` - /// for more details. + /// There is an implied binder around `param_ty` and `ast_bounds`. + /// See `lower_poly_trait_ref` for more details. #[instrument(level = "debug", skip(self, ast_bounds, bounds))] pub(crate) fn lower_poly_bounds<'hir, I: Iterator<Item = &'hir hir::GenericBound<'tcx>>>( &self, @@ -170,22 +178,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - /// Translates a list of bounds from the HIR into the `Bounds` data structure. - /// The self-type for the bounds is given by `param_ty`. + /// Lower HIR bounds into `bounds` given the self type `param_ty` and *no* overarching late-bound vars. /// - /// Example: + /// ### Example /// /// ```ignore (illustrative) - /// fn foo<T: Bar + Baz>() { } + /// fn foo<T: Bar + Baz>() {} /// // ^ ^^^^^^^^^ ast_bounds /// // param_ty /// ``` - /// - /// The `sized_by_default` parameter indicates if, in this context, the `param_ty` should be - /// considered `Sized` unless there is an explicit `?Sized` bound. This would be true in the - /// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`. - /// - /// `span` should be the declaration size of the parameter. pub(crate) fn lower_mono_bounds( &self, param_ty: Ty<'tcx>, @@ -227,12 +228,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { bounds } - /// Given an HIR binding like `Item = Foo` or `Item: Foo`, pushes the corresponding predicates - /// onto `bounds`. + /// Lower an associated item binding from HIR into `bounds`. + /// + /// ### A Note on Binders /// - /// **A note on binders:** given something like `T: for<'a> Iterator<Item = &'a u32>`, the - /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside* - /// the binder (e.g., `&'a u32`) and hence may reference bound regions. + /// Given something like `T: for<'a> Iterator<Item = &'a u32>`, + /// the `trait_ref` here will be `for<'a> T: Iterator`. + /// The `binding` data however is from *inside* the binder + /// (e.g., `&'a u32`) and hence may reference bound regions. #[instrument(level = "debug", skip(self, bounds, dup_bindings, path_span))] pub(super) fn lower_assoc_item_binding( &self, @@ -244,22 +247,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { path_span: Span, only_self_bounds: OnlySelfBounds, ) -> Result<(), ErrorGuaranteed> { - // Given something like `U: SomeTrait<T = X>`, we want to produce a - // predicate like `<U as SomeTrait>::T = X`. This is somewhat - // subtle in the event that `T` is defined in a supertrait of - // `SomeTrait`, because in that case we need to upcast. - // - // That is, consider this case: - // - // ``` - // trait SubTrait: SuperTrait<i32> { } - // trait SuperTrait<A> { type T; } - // - // ... B: SubTrait<T = foo> ... - // ``` - // - // We want to produce `<B as SuperTrait<i32>>::T == foo`. - let tcx = self.tcx(); let assoc_kind = if binding.gen_args.parenthesized @@ -272,6 +259,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::AssocKind::Type }; + // Given something like `U: Trait<T = X>`, we want to produce a predicate like + // `<U as Trait>::T = X`. + // This is somewhat subtle in the event that `T` is defined in a supertrait of `Trait`, + // because in that case we need to upcast. I.e., we want to produce + // `<B as SuperTrait<i32>>::T == X` for `B: SubTrait<T = X>` where + // + // trait SubTrait: SuperTrait<i32> {} + // trait SuperTrait<A> { type T; } let candidate = if self.probe_trait_that_defines_assoc_item( trait_ref.def_id(), assoc_kind, @@ -449,6 +444,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span: binding.span, })); } + // Lower an equality constraint like `Item = u32` as found in HIR bound `T: Iterator<Item = u32>` + // to a projection predicate: `<T as Iterator>::Item = u32`. hir::TypeBindingKind::Equality { term } => { let term = match term { hir::Term::Ty(ty) => self.lower_ty(ty).into(), @@ -490,10 +487,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }, ); - // "Desugar" a constraint like `T: Iterator<Item = u32>` this to - // the "projection predicate" for: - // - // `<T as Iterator>::Item = u32` bounds.push_projection_bound( tcx, projection_ty @@ -501,18 +494,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { binding.span, ); } + // Lower a constraint like `Item: Debug` as found in HIR bound `T: Iterator<Item: Debug>` + // to a bound involving a projection: `<T as Iterator>::Item: Debug`. hir::TypeBindingKind::Constraint { bounds: ast_bounds } => { - // "Desugar" a constraint like `T: Iterator<Item: Debug>` to - // - // `<T as Iterator>::Item: Debug` - // - // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` - // parameter to have a skipped binder. - // - // NOTE: If `only_self_bounds` is true, do NOT expand this associated - // type bound into a trait predicate, since we only want to add predicates - // for the `Self` type. + // NOTE: If `only_self_bounds` is true, do NOT expand this associated type bound into + // a trait predicate, since we only want to add predicates for the `Self` type. if !only_self_bounds.0 { + // Calling `skip_binder` is okay, because `lower_bounds` expects the `param_ty` + // parameter to have a skipped binder. let param_ty = Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder()); self.lower_poly_bounds( param_ty, diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 9ad6fec22ac..cd980526db1 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -143,24 +143,22 @@ fn generic_arg_mismatch_err( err.emit() } -/// Creates the relevant generic arguments -/// corresponding to a set of generic parameters. This is a -/// rather complex function. Let us try to explain the role +/// Lower generic arguments from the HIR to the [`rustc_middle::ty`] representation. +/// +/// This is a rather complex function. Let us try to explain the role /// of each of its parameters: /// -/// To start, we are given the `def_id` of the thing whose generic -/// parameters we are instantiating, and a partial set of -/// arguments `parent_args`. In general, the generic arguments -/// for an item begin with arguments for all the "parents" of -/// that item -- e.g., for a method it might include the -/// parameters from the impl. +/// To start, we are given the `def_id` of the thing whose generic parameters we +/// are creating, and a partial set of arguments `parent_args`. In general, +/// the generic arguments for an item begin with arguments for all the "parents" +/// of that item -- e.g., for a method it might include the parameters from the impl. /// /// Therefore, the method begins by walking down these parents, /// starting with the outermost parent and proceed inwards until /// it reaches `def_id`. For each parent `P`, it will check `parent_args` /// first to see if the parent's arguments are listed in there. If so, -/// we can append those and move on. Otherwise, it invokes the -/// three callback functions: +/// we can append those and move on. Otherwise, it uses the provided +/// [`GenericArgsLowerer`] `ctx` which has the following methods: /// /// - `args_for_def_id`: given the `DefId` `P`, supplies back the /// generic arguments that were given to that parent from within @@ -168,10 +166,10 @@ fn generic_arg_mismatch_err( /// might refer to the trait `Foo`, and the arguments might be /// `[T]`. The boolean value indicates whether to infer values /// for arguments whose values were not explicitly provided. -/// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`, -/// instantiate a `GenericArg`. -/// - `inferred_kind`: if no parameter was provided, and inference is enabled, then -/// creates a suitable inference variable. +/// - `provided_kind`: given the generic parameter and the value +/// from `args_for_def_id`, creating a `GenericArg`. +/// - `inferred_kind`: if no parameter was provided, and inference +/// is enabled, then creates a suitable inference variable. pub fn lower_generic_args<'tcx: 'a, 'a>( tcx: TyCtxt<'tcx>, def_id: DefId, diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 14864da1e39..a9e3c3b75bd 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1,6 +1,17 @@ -//! Conversion from AST representation of types to the `ty.rs` representation. -//! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an -//! instance of `AstConv`. +//! HIR ty lowering: Lowers type-system entities[^1] from the [HIR][hir] to +//! the [`rustc_middle::ty`] representation. +//! +//! Not to be confused with *AST lowering* which lowers AST constructs to HIR ones +//! or with *THIR* / *MIR* *lowering* / *building* which lowers HIR *bodies* +//! (i.e., “executable code”) to THIR / MIR. +//! +//! Most lowering routines are defined on [`dyn HirTyLowerer`](HirTyLowerer) directly, +//! like the main routine of this module, `lower_ty`. +//! +//! This module used to be called `astconv`. +//! +//! [^1]: This includes types, lifetimes / regions, constants in type positions, +//! trait references and bounds. mod bounds; mod errors; @@ -43,6 +54,7 @@ use rustc_trait_selection::traits::{self, ObligationCtxt}; use std::fmt::Display; use std::slice; +/// A path segment that is semantically allowed to have generic arguments. #[derive(Debug)] pub struct GenericPathSegment(pub DefId, pub usize); @@ -67,23 +79,30 @@ pub enum PredicateFilter { SelfAndAssociatedTypeBounds, } +/// A context which can lower type-system entities from the [HIR][hir] to +/// the [`rustc_middle::ty`] representation. +/// +/// This trait used to be called `AstConv`. pub trait HirTyLowerer<'tcx> { fn tcx(&self) -> TyCtxt<'tcx>; + /// Returns the [`DefId`] of the overarching item whose constituents get lowered. fn item_def_id(&self) -> DefId; - /// Returns predicates in scope of the form `X: Foo<T>`, where `X` - /// is a type parameter `X` with the given id `def_id` and T - /// matches `assoc_name`. This is a subset of the full set of - /// predicates. + /// Probe bounds in scope where the bounded type coincides with the given type parameter. + /// + /// Rephrased, this returns bounds of the form `T: Trait`, where `T` is a type parameter + /// with the given `def_id`. This is a subset of the full set of bounds. + /// + /// This method may use the given `assoc_name` to disregard bounds whose trait reference + /// doesn't define an associated item with the provided name. /// - /// This is used for one specific purpose: resolving "short-hand" - /// associated type references like `T::Item`. In principle, we - /// would do that by first getting the full set of predicates in - /// scope and then filtering down to find those that apply to `T`, - /// but this can lead to cycle errors. The problem is that we have - /// to do this resolution *in order to create the predicates in - /// the first place*. Hence, we have this "special pass". + /// This is used for one specific purpose: Resolving “short-hand” associated type references + /// like `T::Item` where `T` is a type parameter. In principle, we would do that by first + /// getting the full set of predicates in scope and then filtering down to find those that + /// apply to `T`, but this can lead to cycle errors. The problem is that we have to do this + /// resolution *in order to create the predicates in the first place*. + /// Hence, we have this “special pass”. fn probe_ty_param_bounds( &self, span: Span, @@ -91,14 +110,14 @@ pub trait HirTyLowerer<'tcx> { assoc_name: Ident, ) -> ty::GenericPredicates<'tcx>; - /// Returns the lifetime to use when a lifetime is omitted (and not elided). + /// Returns the region to use when a lifetime is omitted (and not elided). fn re_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Option<ty::Region<'tcx>>; /// Returns the type to use when a type is omitted. fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>; - /// Returns `true` if `_` is allowed in type signatures in the current context. + /// Returns `true` if the current context allows the use of inference variables. fn allow_infer(&self) -> bool; /// Returns the const to use when a const is omitted. @@ -109,13 +128,18 @@ pub trait HirTyLowerer<'tcx> { span: Span, ) -> Const<'tcx>; - /// Projecting an associated type from a (potentially) - /// higher-ranked trait reference is more complicated, because of - /// the possibility of late-bound regions appearing in the - /// associated type binding. This is not legal in function - /// signatures for that reason. In a function body, we can always - /// handle it because we can use inference variables to remove the - /// late-bound regions. + /// Lower an associated type to a projection. + /// + /// This method has to be defined by the concrete lowering context because + /// dealing with higher-ranked trait references depends on its capabilities: + /// + /// If the context can make use of type inference, it can simply instantiate + /// any late-bound vars bound by the trait reference with inference variables. + /// If it doesn't support type inference, there is nothing reasonable it can + /// do except reject the associated type. + /// + /// The canonical example of this is associated type `T::P` where `T` is a type + /// param constrained by `T: for<'a> Trait<'a>` and where `Trait` defines `P`. fn lower_assoc_ty( &self, span: Span, @@ -125,20 +149,26 @@ pub trait HirTyLowerer<'tcx> { ) -> Ty<'tcx>; /// Returns `AdtDef` if `ty` is an ADT. - /// Note that `ty` might be a projection type that needs normalization. + /// + /// Note that `ty` might be a alias type that needs normalization. /// This used to get the enum variants in scope of the type. /// For example, `Self::A` could refer to an associated type /// or to an enum variant depending on the result of this function. fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>>; - /// Invoked when we encounter an error from some prior pass - /// (e.g., resolve) that is translated into a ty-error. This is - /// used to help suppress derived errors typeck might otherwise - /// report. + /// Taint the context with errors. + /// + /// Invoke this when you encounter an error from some prior pass like name resolution. + /// This is used to help suppress derived errors typeck might otherwise report. fn set_tainted_by_errors(&self, e: ErrorGuaranteed); + /// Record the lowered type of a HIR node in this context. fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span); + /// Convenience method for coercing the lowering context into a trait object type. + /// + /// Most lowering routines are defined on the trait object type directly + /// necessitating a coercion step from the concrete lowering context. fn lowerer(&self) -> &dyn HirTyLowerer<'tcx> where Self: Sized, @@ -146,6 +176,7 @@ pub trait HirTyLowerer<'tcx> { self } + /// The inference context of the lowering context if applicable. fn infcx(&self) -> Option<&InferCtxt<'tcx>>; } @@ -197,6 +228,10 @@ pub struct GenericArgCountResult { pub correct: Result<(), GenericArgCountMismatch>, } +/// A context which can lower HIR's [`GenericArg`] to `rustc_middle`'s [`ty::GenericArg`]. +/// +/// Its only consumer is [`generics::lower_generic_args`]. +/// Read its documentation to learn more. pub trait GenericArgsLowerer<'a, 'tcx> { fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool); @@ -215,6 +250,7 @@ pub trait GenericArgsLowerer<'a, 'tcx> { } impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { + /// Lower a lifetime from the HIR to our internal notion of a lifetime called a *region*. #[instrument(level = "debug", skip(self), ret)] pub fn lower_lifetime( &self, @@ -271,8 +307,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`, - /// returns an appropriate set of generic arguments for this particular reference to `I`. pub fn lower_generic_args_of_path_segment( &self, span: Span, @@ -293,14 +327,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { args } - /// Given the type/lifetime/const arguments provided to some path (along with - /// an implicit `Self`, if this is a trait reference), returns the complete - /// set of generic arguments. This may involve applying defaulted type parameters. + /// Lower the generic arguments provided to some path. /// - /// Constraints on associated types are not converted here but - /// separately in `add_predicates_for_ast_type_binding`. + /// If this is a trait reference, you also need to pass the self type `self_ty`. + /// The lowering process may involve applying defaulted type parameters. /// - /// Example: + /// Associated item bindings are not handled here! + /// + /// ### Example /// /// ```ignore (illustrative) /// T: std::ops::Index<usize, Output = u32> @@ -589,16 +623,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if let Some(b) = item_segment.args().bindings.first() { prohibit_assoc_item_binding(self.tcx(), b.span, Some((item_segment, span))); } - args } - /// Instantiates the path for the given trait reference, assuming that it's - /// bound to a valid trait type. Returns the `DefId` of the defining trait. - /// The type _cannot_ be a type other than a trait type. + /// Lower a trait reference as found in an impl header as the implementee. /// - /// If the `projections` argument is `None`, then assoc type bindings like `Foo<T = X>` - /// are disallowed. Otherwise, they are pushed onto the vector given. + /// The self type `self_ty` is the implementer of the trait. pub fn lower_impl_trait_ref( &self, trait_ref: &hir::TraitRef<'tcx>, @@ -616,25 +646,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) } - /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct - /// a full trait reference. The resulting trait reference is returned. This may also generate - /// auxiliary bounds, which are added to `bounds`. + /// Lower a polymorphic trait reference given a self type into `bounds`. /// - /// Example: + /// *Polymorphic* in the sense that it may bind late-bound vars. /// - /// ```ignore (illustrative) - /// poly_trait_ref = Iterator<Item = u32> - /// self_ty = Foo - /// ``` + /// This may generate auxiliary bounds if the trait reference contains associated item bindings. + /// + /// ### Example /// - /// this would return `Foo: Iterator` and add `<Foo as Iterator>::Item = u32` into `bounds`. + /// Given the trait ref `Iterator<Item = u32>` and the self type `Ty`, this will add the + /// + /// 1. *trait predicate* `<Ty as Iterator>` (known as `Foo: Iterator` in surface syntax) and the + /// 2. *projection predicate* `<Ty as Iterator>::Item = u32` + /// + /// to `bounds`. + /// + /// ### A Note on Binders + /// + /// Against our usual convention, there is an implied binder around the `self_ty` and the + /// `trait_ref` here. So they may reference late-bound vars. /// - /// **A note on binders:** against our usual convention, there is an implied binder around - /// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions. /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>` - /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be - /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly, - /// however. + /// where `'a` is a bound region at depth 0. Similarly, the `trait_ref` would be `Bar<'a>`. + /// The lowered poly-trait-ref will track this binder explicitly, however. #[instrument(level = "debug", skip(self, span, constness, bounds))] pub(crate) fn lower_poly_trait_ref( &self, @@ -702,6 +736,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { arg_count } + /// Lower a monomorphic trait reference given a self type while prohibiting associated item bindings. + /// + /// *Monomorphic* in the sense that it doesn't bind any late-bound vars. fn lower_mono_trait_ref( &self, span: Span, @@ -709,7 +746,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self_ty: Ty<'tcx>, trait_segment: &hir::PathSegment<'tcx>, is_impl: bool, - // FIXME(effects) move all host param things in astconv to hir lowering + // FIXME(effects): Move all host param things in HIR ty lowering to AST lowering. constness: ty::BoundConstness, ) -> ty::TraitRef<'tcx> { self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl); @@ -762,10 +799,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - // Search for a bound on a type parameter which includes the associated item - // given by `assoc_name`. `ty_param_def_id` is the `DefId` of the type parameter - // This function will fail if there are no suitable bounds or there is - // any ambiguity. + /// Search for a trait bound on a type parameter whose trait defines the associated type given by `assoc_name`. + /// + /// This fails if there is no such bound in the list of candidates or if there are multiple + /// candidates in which case it reports ambiguity. + /// + /// `ty_param_def_id` is the `LocalDefId` of the type parameter. fn probe_single_ty_param_bound_for_assoc_ty( &self, ty_param_def_id: LocalDefId, @@ -803,8 +842,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) } - // Checks that `bounds` contains exactly one element and reports appropriate - // errors otherwise. + /// Search for a single trait bound whose trait defines the associated item given by `assoc_name`. + /// + /// This fails if there is no such bound in the list of candidates or if there are multiple + /// candidates in which case it reports ambiguity. #[instrument(level = "debug", skip(self, all_candidates, ty_param_name, binding), ret)] fn probe_single_bound_for_assoc_item<I>( &self, @@ -927,12 +968,31 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Ok(bound) } - // Create a type from a path to an associated type or to an enum variant. - // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C` - // and item_segment is the path segment for `D`. We return a type and a def for - // the whole path. - // Will fail except for `T::A` and `Self::A`; i.e., if `qself_ty`/`qself_def` are not a type - // parameter or `Self`. + /// Lower a [type-relative] path referring to an associated type or to an enum variant. + /// + /// If the path refers to an enum variant and `permit_variants` holds, + /// the returned type is simply the provided self type `qself_ty`. + /// + /// A path like `A::B::C::D` is understood as `<A::B::C>::D`. I.e., + /// `qself_ty` / `qself` is `A::B::C` and `assoc_segment` is `D`. + /// We return the lowered type and the `DefId` for the whole path. + /// + /// We only support associated type paths whose self type is a type parameter or a `Self` + /// type alias (in a trait impl) like `T::Ty` (where `T` is a ty param) or `Self::Ty`. + /// We **don't** support paths whose self type is an arbitrary type like `Struct::Ty` where + /// struct `Struct` impls an in-scope trait that defines an associated type called `Ty`. + /// For the latter case, we report ambiguity. + /// While desirable to support, the implemention would be non-trivial. Tracked in [#22519]. + /// + /// At the time of writing, *inherent associated types* are also resolved here. This however + /// is [problematic][iat]. A proper implementation would be as non-trivial as the one + /// described in the previous paragraph and their modeling of projections would likely be + /// very similar in nature. + /// + /// [type-relative]: hir::QPath::TypeRelative + /// [#22519]: https://github.com/rust-lang/rust/issues/22519 + /// [iat]: https://github.com/rust-lang/rust/issues/8995#issuecomment-1569208403 + // // NOTE: When this function starts resolving `Trait::AssocTy` successfully // it should also start reporting the `BARE_TRAIT_OBJECTS` lint. #[instrument(level = "debug", skip(self, hir_ref_id, span, qself, assoc_segment), fields(assoc_ident=?assoc_segment.ident), ret)] @@ -1064,6 +1124,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } + // FIXME(inherent_associated_types, #106719): Support self types other than ADTs. if let Some((ty, did)) = self.probe_inherent_assoc_ty( assoc_ident, assoc_segment, @@ -1233,8 +1294,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Don't attempt to look up inherent associated types when the feature is not enabled. // Theoretically it'd be fine to do so since we feature-gate their definition site. // However, due to current limitations of the implementation (caused by us performing - // selection in AstConv), IATs can lead to cycle errors (#108491, #110106) which mask the - // feature-gate error, needlessly confusing users that use IATs by accident (#113265). + // selection during HIR ty lowering instead of in the trait solver), IATs can lead to cycle + // errors (#108491) which mask the feature-gate error, needlessly confusing users + // who use IATs by accident (#113265). if !tcx.features().inherent_associated_types { return Ok(None); } @@ -1289,7 +1351,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.check_assoc_ty(assoc_item, name, def_scope, block, span); // FIXME(fmease): Currently creating throwaway `parent_args` to please - // `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to + // `lower_generic_args_of_assoc_item`. Modify the latter instead (or sth. similar) to // not require the parent args logic. let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_); let args = self.lower_generic_args_of_assoc_item(span, assoc_item, segment, parent_args); @@ -1490,6 +1552,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .collect() } + /// Lower a qualified path to a type. fn lower_qpath( &self, span: Span, @@ -1676,6 +1739,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { emitted } + /// Probe path segments that are semantically allowed to have generic arguments. + /// + /// ### Example + /// + /// ```ignore (illustrative) + /// Option::None::<()> + /// // ^^^^ permitted to have generic args + /// + /// // ==> [GenericPathSegment(Option_def_id, 1)] + /// + /// Option::<()>::None + /// // ^^^^^^ ^^^^ *not* permitted to have generic args + /// // permitted to have generic args + /// + /// // ==> [GenericPathSegment(Option_def_id, 0)] + /// ``` // FIXME(eddyb, varkor) handle type paths here too, not just value ones. pub fn probe_generic_path_segments( &self, @@ -1685,9 +1764,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { def_id: DefId, span: Span, ) -> Vec<GenericPathSegment> { - // We need to extract the type parameters supplied by the user in + // We need to extract the generic arguments supplied by the user in // the path `path`. Due to the current setup, this is a bit of a - // tricky-process; the problem is that resolve only tells us the + // tricky process; the problem is that resolve only tells us the // end-point of the path resolution, and not the intermediate steps. // Luckily, we can (at least for now) deduce the intermediate steps // just from the end-point. @@ -1698,35 +1777,35 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // // struct Foo<T>(...) // - // In this case, the parameters are declared in the type space. + // In this case, the generic arguments are declared in the type space. // // 2. Reference to a constructor of an enum variant: // // enum E<T> { Foo(...) } // - // In this case, the parameters are defined in the type space, + // In this case, the generic arguments are defined in the type space, // but may be specified either on the type or the variant. // - // 3. Reference to a fn item or a free constant: + // 3. Reference to a free function or constant: // - // fn foo<T>() { } + // fn foo<T>() {} // // In this case, the path will again always have the form - // `a::b::foo::<T>` where only the final segment should have - // type parameters. However, in this case, those parameters are - // declared on a value, and hence are in the `FnSpace`. + // `a::b::foo::<T>` where only the final segment should have generic + // arguments. However, in this case, those arguments are declared on + // a value, and hence are in the value space. // - // 4. Reference to a method or an associated constant: + // 4. Reference to an associated function or constant: // // impl<A> SomeStruct<A> { - // fn foo<B>(...) + // fn foo<B>(...) {} // } // - // Here we can have a path like - // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters - // may appear in two places. The penultimate segment, - // `SomeStruct::<A>`, contains parameters in TypeSpace, and the - // final segment, `foo::<B>` contains parameters in fn space. + // Here we can have a path like `a::b::SomeStruct::<A>::foo::<B>`, + // in which case generic arguments may appear in two places. The + // penultimate segment, `SomeStruct::<A>`, contains generic arguments + // in the type space, and the final segment, `foo::<B>` contains + // generic arguments in value space. // // The first step then is to categorize the segments appropriately. @@ -1804,7 +1883,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { generic_segments } - /// Check a type `Path` and convert it to a `Ty`. + /// Lower a type `Path` to a type. pub fn lower_path( &self, opt_self_ty: Option<Ty<'tcx>>, @@ -1844,7 +1923,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lower_path_segment(span, did, path.segments.last().unwrap()) } Res::Def(kind @ DefKind::Variant, def_id) if permit_variants => { - // Convert "variant type" as if it were a real type. + // Lower "variant type" as if it were a real type. // The resulting `Ty` is type of the variant's enum for now. assert_eq!(opt_self_ty, None); @@ -2045,8 +2124,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - // Converts a hir id corresponding to a type parameter to - // a early-bound `ty::Param` or late-bound `ty::Bound`. + /// Lower a type parameter from the HIR to our internal notion of a type. + /// + /// Early-bound type parameters get lowered to [`ty::Param`] + /// and late-bound ones to [`ty::Bound`]. pub(crate) fn lower_ty_param(&self, hir_id: hir::HirId) -> Ty<'tcx> { let tcx = self.tcx(); match tcx.named_bound_var(hir_id) { @@ -2070,8 +2151,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - // Converts a hir id corresponding to a const parameter to - // a early-bound `ConstKind::Param` or late-bound `ConstKind::Bound`. + /// Lower a const parameter from the HIR to our internal notion of a constant. + /// + /// Early-bound const parameters get lowered to [`ty::ConstKind::Param`] + /// and late-bound ones to [`ty::ConstKind::Bound`]. pub(crate) fn lower_const_param(&self, hir_id: hir::HirId, param_ty: Ty<'tcx>) -> Const<'tcx> { let tcx = self.tcx(); match tcx.named_bound_var(hir_id) { @@ -2092,14 +2175,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - /// Parses the programmer's textual representation of a type into our - /// internal notion of a type. + /// Lower a type from the HIR to our internal notion of a type. pub fn lower_ty(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { self.lower_ty_common(ast_ty, false, false) } - /// Parses the programmer's textual representation of a type into our - /// internal notion of a type. This is meant to be used within a path. + /// Lower a type inside of a path from the HIR to our internal notion of a type. pub fn lower_ty_in_path(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { self.lower_ty_common(ast_ty, false, true) } @@ -2202,8 +2283,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { sig.instantiate_identity() }; - // Bound vars are also inherited from `sig_id`. They will be - // rebinded later in `ty_of_fn`. + // Bound vars are also inherited from `sig_id`. + // They will be rebound later in `lower_fn_ty`. let sig = sig.skip_binder(); match idx { @@ -2212,8 +2293,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait - /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors. + /// Lower a type from the HIR to our internal notion of a type given some extra data for diagnostics. + /// + /// Extra diagnostic data: + /// + /// 1. `borrowed`: Whether trait object types are borrowed like in `&dyn Trait`. + /// Used to avoid emitting redundant errors. + /// 2. `in_path`: Whether the type appears inside of a path. + /// Used to provide correct diagnostics for bare trait object types. #[instrument(level = "debug", skip(self), ret)] fn lower_ty_common(&self, ast_ty: &hir::Ty<'tcx>, borrowed: bool, in_path: bool) -> Ty<'tcx> { let tcx = self.tcx(); @@ -2348,6 +2435,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { result_ty } + /// Lower an opaque type (i.e., an existential impl-Trait type) from the HIR. #[instrument(level = "debug", skip(self), ret)] fn lower_opaque_ty( &self, @@ -2405,6 +2493,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } + /// Lower a function type from the HIR to our internal notion of a function signature. #[instrument(level = "debug", skip(self, hir_id, unsafety, abi, decl, generics, hir_ty), ret)] pub fn lower_fn_ty( &self, @@ -2484,7 +2573,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if !self.allow_infer() && !(visitor.0.is_empty() && infer_replacements.is_empty()) { // We always collect the spans for placeholder types when evaluating `fn`s, but we // only want to emit an error complaining about them if infer types (`_`) are not - // allowed. `allow_ty_infer` gates this behavior. We check for the presence of + // allowed. `allow_infer` gates this behavior. We check for the presence of // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`. let mut diag = crate::collect::placeholder_type_error_diag( @@ -2610,7 +2699,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } /// Given the bounds on an object, determines what single region bound (if any) we can - /// use to summarize this type. The basic idea is that we will use the bound the user + /// use to summarize this type. + /// + /// The basic idea is that we will use the bound the user /// provided, if they provided one, and otherwise search the supertypes of trait bounds /// for region bounds. It may be that we can derive no bound at all, in which case /// we return `None`. diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index 140055cf764..2a3f956bfba 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -18,6 +18,7 @@ use smallvec::{smallvec, SmallVec}; use super::HirTyLowerer; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { + /// Lower a trait object type from the HIR to our internal notion of a type. pub(super) fn lower_trait_object_ty( &self, span: Span, diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index b69f679880d..d659d2c5235 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -1,5 +1,5 @@ -//! Bounds are restrictions applied to some types after they've been converted into the -//! `ty` form from the HIR. +//! Bounds are restrictions applied to some types after they've been lowered from the HIR to the +//! [`rustc_middle::ty`] form. use rustc_hir::LangItem; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index d1fed13ee9f..09b20917e2a 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -382,8 +382,8 @@ fn check_opaque_meets_bounds<'tcx>( Ok(()) => {} Err(ty_err) => { // Some types may be left "stranded" if they can't be reached - // from an astconv'd bound but they're mentioned in the HIR. This - // will happen, e.g., when a nested opaque is inside of a non- + // from a lowered rustc_middle bound but they're mentioned in the HIR. + // This will happen, e.g., when a nested opaque is inside of a non- // existent associated type, like `impl Trait<Missing = impl Trait>`. // See <tests/ui/impl-trait/stranded-opaque.rs>. let ty_err = ty_err.to_string(tcx); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index d2fdff6177e..8fb6569aa14 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -746,7 +746,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // We may not collect all RPITITs that we see in the HIR for a trait signature // because an RPITIT was located within a missing item. Like if we have a sig - // returning `-> Missing<impl Sized>`, that gets converted to `-> [type error]`, + // returning `-> Missing<impl Sized>`, that gets converted to `-> {type error}`, // and when walking through the signature we end up never collecting the def id // of the `impl Sized`. Insert that here, so we don't ICE later. for assoc_item in tcx.associated_types_for_impl_traits_in_associated_fn(trait_m.def_id) { diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index eb31e1546cf..e84bce92fc5 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -760,7 +760,7 @@ impl<'tcx> RegionResolutionVisitor<'tcx> { fn enter_node_scope_with_dtor(&mut self, id: hir::ItemLocalId) { // If node was previously marked as a terminating scope during the - // recursive visit of its parent node in the AST, then we need to + // recursive visit of its parent node in the HIR, then we need to // account for the destruction scope representing the scope of // the destructors that run immediately after it completes. if self.terminating_scopes.contains(&id) { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index e466fc5e44e..2b4a35d0b9b 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -272,7 +272,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() } Some(ty::ImplPolarity::Negative) => { let ast::ImplPolarity::Negative(span) = impl_.polarity else { - bug!("impl_polarity query disagrees with impl's polarity in AST"); + bug!("impl_polarity query disagrees with impl's polarity in HIR"); }; // FIXME(#27579): what amount of WF checking do we need for neg impls? if let hir::Defaultness::Default { .. } = impl_.defaultness { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 06e7576e897..1fa8cbd9627 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -88,13 +88,12 @@ pub fn provide(providers: &mut Providers) { /////////////////////////////////////////////////////////////////////////// -/// Context specific to some particular item. This is what implements -/// [`AstConv`]. +/// Context specific to some particular item. This is what implements [`HirTyLowerer`]. /// /// # `ItemCtxt` vs `FnCtxt` /// /// `ItemCtxt` is primarily used to type-check item signatures and lower them -/// from HIR to their [`ty::Ty`] representation, which is exposed using [`AstConv`]. +/// from HIR to their [`ty::Ty`] representation, which is exposed using [`HirTyLowerer`]. /// It's also used for the bodies of items like structs where the body (the fields) /// are just signatures. /// @@ -111,11 +110,11 @@ pub fn provide(providers: &mut Providers) { /// `ItemCtxt` has information about the predicates that are defined /// on the trait. Unfortunately, this predicate information is /// available in various different forms at various points in the -/// process. So we can't just store a pointer to e.g., the AST or the +/// process. So we can't just store a pointer to e.g., the HIR or the /// parsed ty form, we have to be more flexible. To this end, the /// `ItemCtxt` is parameterized by a `DefId` that it uses to satisfy -/// `get_type_parameter_bounds` requests, drawing the information from -/// the AST (`hir::Generics`), recursively. +/// `probe_ty_param_bounds` requests, drawing the information from +/// the HIR (`hir::Generics`), recursively. pub struct ItemCtxt<'tcx> { tcx: TyCtxt<'tcx>, item_def_id: LocalDefId, @@ -785,8 +784,7 @@ fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) { tcx.ensure().predicates_of(f.did); } - // Convert the ctor, if any. This also registers the variant as - // an item. + // Lower the ctor, if any. This also registers the variant as an item. if let Some(ctor_def_id) = variant.ctor_def_id() { lower_variant_ctor(tcx, ctor_def_id.expect_local()); } @@ -1545,7 +1543,7 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai // we have a const impl, but for a trait without `#[const_trait]`, so // without the host param. If we continue with the HIR trait ref, we get // ICEs for generic arg count mismatch. We do a little HIR editing to - // make astconv happy. + // make HIR ty lowering happy. let mut path_segments = ast_trait_ref.path.segments.to_vec(); let last_segment = path_segments.len() - 1; let mut args = *path_segments[last_segment].args(); diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index b4e113d47ed..2890038a373 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -138,8 +138,8 @@ pub(super) fn explicit_item_bounds_with_filter( let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter) } - // Since RPITITs are astconv'd as projections in `ast_ty_to_ty`, when we're asking - // for the item bounds of the *opaques* in a trait's default method signature, we + // Since RPITITs are lowered as projections in `<dyn HirTyLowerer>::lower_ty`, when we're + // asking for the item bounds of the *opaques* in a trait's default method signature, we // need to map these projections back to opaques. hir::Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait: true, origin, .. }), diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 4c4cf9fa1b6..6d90a867486 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -542,8 +542,8 @@ pub(super) fn explicit_predicates_of<'tcx>( } /// Ensures that the super-predicates of the trait with a `DefId` -/// of `trait_def_id` are converted and stored. This also ensures that -/// the transitive super-predicates are converted. +/// of `trait_def_id` are lowered and stored. This also ensures that +/// the transitive super-predicates are lowered. pub(super) fn super_predicates_of( tcx: TyCtxt<'_>, trait_def_id: LocalDefId, @@ -574,8 +574,8 @@ pub(super) fn implied_predicates_of( } /// Ensures that the super-predicates of the trait with a `DefId` -/// of `trait_def_id` are converted and stored. This also ensures that -/// the transitive super-predicates are converted. +/// of `trait_def_id` are lowered and stored. This also ensures that +/// the transitive super-predicates are lowered. pub(super) fn implied_predicates_with_filter( tcx: TyCtxt<'_>, trait_def_id: DefId, @@ -615,7 +615,7 @@ pub(super) fn implied_predicates_with_filter( &*tcx.arena.alloc_from_iter(superbounds.clauses().chain(where_bounds_that_match)); debug!(?implied_bounds); - // Now require that immediate supertraits are converted, which will, in + // Now require that immediate supertraits are lowered, which will, in // turn, reach indirect supertraits, so we detect cycles now instead of // overflowing during elaboration. Same for implied predicates, which // make sure we walk into associated type bounds. @@ -656,7 +656,7 @@ pub(super) fn type_param_predicates( use rustc_hir::*; use rustc_middle::ty::Ty; - // In the AST, bounds can derive from two places. Either + // In the HIR, bounds can derive from two places. Either // written inline like `<T: Foo>` or in a where-clause like // `where T: Foo`. @@ -714,10 +714,11 @@ pub(super) fn type_param_predicates( } impl<'tcx> ItemCtxt<'tcx> { - /// Finds bounds from `hir::Generics`. This requires scanning through the - /// AST. We do this to avoid having to convert *all* the bounds, which - /// would create artificial cycles. Instead, we can only convert the - /// bounds for a type parameter `X` if `X::Foo` is used. + /// Finds bounds from `hir::Generics`. + /// + /// This requires scanning through the HIR. + /// We do this to avoid having to lower *all* the bounds, which would create artificial cycles. + /// Instead, we can only lower the bounds for a type parameter `X` if `X::Foo` is used. #[instrument(level = "trace", skip(self, ast_generics))] fn probe_ty_param_bounds_in_generics( &self, diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 83877bff98c..27a26cfe474 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1917,7 +1917,7 @@ fn is_late_bound_map( /// /// If we conservatively considered `'a` unconstrained then we could break users who had written code before /// we started correctly handling aliases. If we considered `'a` constrained then it would become late bound - /// causing an error during astconv as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc` + /// causing an error during HIR ty lowering as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc` /// but appears in the output type `<() as Trait<'a>>::Assoc`. /// /// We must therefore "look into" the `Alias` to see whether we should consider `'a` constrained or not. @@ -1970,8 +1970,8 @@ fn is_late_bound_map( None, hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span }, )) => { - // See comments on `ConstrainedCollectorPostAstConv` for why this arm does not just consider - // args to be unconstrained. + // See comments on `ConstrainedCollectorPostHirTyLowering` for why this arm does not + // just consider args to be unconstrained. let generics = self.tcx.generics_of(alias_def); let mut walker = ConstrainedCollectorPostHirTyLowering { arg_is_constrained: vec![false; generics.params.len()].into_boxed_slice(), diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 4d8e0e04c73..722def2563c 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -97,10 +97,10 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { // I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU Node::Ty(hir_ty @ hir::Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => { // Find the Item containing the associated type so we can create an ItemCtxt. - // Using the ItemCtxt convert the HIR for the unresolved assoc type into a + // Using the ItemCtxt lower the HIR for the unresolved assoc type into a // ty which is a fully resolved projection. - // For the code example above, this would mean converting Self::Assoc<3> - // into a ty::Alias(ty::Projection, <Self as Foo>::Assoc<3>) + // For the code example above, this would mean lowering `Self::Assoc<3>` + // to a ty::Alias(ty::Projection, `<Self as Foo>::Assoc<3>`). let item_def_id = tcx .hir() .parent_owner_iter(hir_id) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index e95ed554a78..d7fcb19a536 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -30,8 +30,8 @@ several major phases: The type checker is defined into various submodules which are documented independently: -- astconv: converts the AST representation of types - into the `ty` representation. +- astconv: lowers type-system entities from the [HIR][hir] to the + [`rustc_middle::ty`] representation. - collect: computes the types of each top-level item and enters them into the `tcx.types` table for later use. @@ -211,8 +211,16 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { Ok(()) } -/// A quasi-deprecated helper used in rustdoc and clippy to get -/// the type from a HIR node. +/// Lower a [`hir::Ty`] to a [`Ty`]. +/// +/// <div class="warning"> +/// +/// This function is **quasi-deprecated**. It can cause ICEs if called inside of a body +/// (of a function or constant) and especially if it contains inferred types (`_`). +/// +/// It's used in rustdoc and Clippy. +/// +/// </div> pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { // In case there are any projections, etc., find the "environment" // def-ID that will be used to determine the traits/predicates in diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 580cdb4a3a2..93a0e924099 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -1,6 +1,6 @@ //! Constraint construction and representation //! -//! The second pass over the AST determines the set of constraints. +//! The second pass over the HIR determines the set of constraints. //! We walk the set of items and, for each member, generate new constraints. use hir::def_id::{DefId, LocalDefId}; |
