Update (doc) comments

Several (doc) comments were super outdated or didn't provide enough context.

Some doc comments shoved everything in a single paragraph without respecting
the fact that the first paragraph should be a single sentence because rustdoc
treats these as item descriptions / synopses on module pages.
This commit is contained in:
León Orell Valerian Liehr 2024-02-11 09:22:52 +01:00
parent 05d48b936f
commit 82c2c8deb1
No known key found for this signature in database
GPG Key ID: D17A07215F68E713
36 changed files with 332 additions and 252 deletions

View File

@ -303,10 +303,6 @@ impl TraitBoundModifiers {
};
}
/// The AST represents all type param bounds as types.
/// `typeck::collect::compute_bounds` matches these against
/// the "special" built-in traits (see `middle::lang_items`) and
/// detects `Copy`, `Send` and `Sync`.
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum GenericBound {
Trait(PolyTraitRef, TraitBoundModifiers),

View File

@ -480,7 +480,7 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
try_visit!(visitor.visit_path(&use_tree.prefix, id));
match use_tree.kind {
UseTreeKind::Simple(rename) => {
// The extra IDs are handled during HIR lowering.
// The extra IDs are handled during AST lowering.
visit_opt!(visitor, visit_ident, rename);
}
UseTreeKind::Glob => {}

View File

@ -29,11 +29,12 @@
//! item id (`item_id`) in case of impl trait or path resolution id (`path_id`) otherwise.
//!
//! Since we do not have a proper way to obtain function type information by path resolution
//! in AST, we mark each function parameter type as `InferDelegation` and inherit it in `AstConv`.
//! in AST, we mark each function parameter type as `InferDelegation` and inherit it during
//! HIR ty lowering.
//!
//! Similarly generics, predicates and header are set to the "default" values.
//! In case of discrepancy with callee function the `NotSupportedDelegation` error will
//! also be emitted in `AstConv`.
//! also be emitted during HIR ty lowering.
use crate::{ImplTraitPosition, ResolverAstLoweringExt};
@ -129,7 +130,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
) -> &'hir hir::FnDecl<'hir> {
let args_count = if let Some(local_sig_id) = sig_id.as_local() {
// Map may be filled incorrectly due to recursive delegation.
// Error will be emmited later in astconv.
// Error will be emitted later during HIR ty lowering.
self.resolver.fn_parameter_counts.get(&local_sig_id).cloned().unwrap_or_default()
} else {
self.tcx.fn_arg_names(sig_id).len()

View File

@ -1427,8 +1427,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Error if `?Trait` bounds in where clauses don't refer directly to type parameters.
// Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
// these into hir when we lower thee where clauses), but this makes it quite difficult to
// keep track of the Span info. Now, `add_implicitly_sized` in `AstConv` checks both param bounds and
// where clauses for `?Sized`.
// keep track of the Span info. Now, `<dyn HirTyLowerer>::add_implicit_sized_bound`
// checks both param bounds and where clauses for `?Sized`.
for pred in &generics.where_clause.predicates {
let WherePredicate::BoundPredicate(bound_pred) = pred else {
continue;

View File

@ -428,10 +428,6 @@ pub enum TraitBoundModifier {
MaybeConst,
}
/// The AST represents all type param bounds as types.
/// `typeck::collect::compute_bounds` matches these against
/// the "special" built-in traits (see `middle::lang_items`) and
/// detects `Copy`, `Send` and `Sync`.
#[derive(Clone, Copy, Debug, HashStable_Generic)]
pub enum GenericBound<'hir> {
Trait(PolyTraitRef<'hir>, TraitBoundModifier),
@ -1860,7 +1856,7 @@ pub enum ExprKind<'hir> {
/// Wraps the expression in a terminating scope.
/// This makes it semantically equivalent to `{ let _t = expr; _t }`.
///
/// This construct only exists to tweak the drop order in HIR lowering.
/// This construct only exists to tweak the drop order in AST lowering.
/// An example of that is the desugaring of `for` loops.
DropTemps(&'hir Expr<'hir>),
/// A `let $pat = $expr` expression.
@ -2293,7 +2289,7 @@ pub enum ImplItemKind<'hir> {
/// Bind a type to an associated type (i.e., `A = Foo`).
///
/// Bindings like `A: Debug` are represented as a special type `A =
/// $::Debug` that is understood by the astconv code.
/// $::Debug` that is understood by the HIR ty lowering code.
///
/// FIXME(alexreg): why have a separate type for the binding case,
/// wouldn't it be better to make the `ty` field an enum like the

View File

@ -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.
///
/// ```text
/// fn foo<T: Debug>
/// ^ ^^^^^ `ast_bounds` parameter, in HIR form
/// |
/// `param_ty`, in ty form
/// ### Examples
///
/// ```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:** 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.
/// ### 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.
#[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,

View File

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

View File

@ -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.
///
/// 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".
/// 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` 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.
///
/// this would return `Foo: Iterator` and add `<Foo as Iterator>::Item = u32` into `bounds`.
/// ### Example
///
/// 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`.

View File

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

View File

@ -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};

View File

@ -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);

View File

@ -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) {

View File

@ -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) {

View File

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

View File

@ -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();

View File

@ -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, .. }),

View File

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

View File

@ -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(),

View File

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

View File

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

View File

@ -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};

View File

@ -826,7 +826,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
QPath::TypeRelative(ref qself, ref segment) => {
// Don't use `self.to_ty`, since this will register a WF obligation.
// Don't use `self.lower_ty`, since this will register a WF obligation.
// If we're trying to call a nonexistent method on a trait
// (e.g. `MyTrait::missing_method`), then resolution will
// give us a `QPath::TypeRelative` with a trait object as

View File

@ -360,8 +360,8 @@ impl<'a, 'tcx> HirTyLowerer<'tcx> for FnCtxt<'a, 'tcx> {
/// The `ty` representation of a user-provided type. Depending on the use-site
/// we want to either use the unnormalized or the normalized form of this type.
///
/// This is a bridge between the interface of `AstConv`, which outputs a raw `Ty`,
/// and the API in this module, which expect `Ty` to be fully normalized.
/// This is a bridge between the interface of HIR ty lowering, which outputs a raw
/// `Ty`, and the API in this module, which expect `Ty` to be fully normalized.
#[derive(Clone, Copy, Debug)]
pub struct LoweredTy<'tcx> {
/// The unnormalized type provided by the user.

View File

@ -957,7 +957,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
bounded_ty,
..
}) => {
// FIXME: Maybe these calls to `ast_ty_to_ty` can be removed (and the ones below)
// FIXME: Maybe these calls to `lower_ty` can be removed (and the ones below)
let ty = self.lowerer().lower_ty(bounded_ty);
Some((ty, bounds))
}

View File

@ -1062,7 +1062,7 @@ pub enum ExpnKind {
Macro(MacroKind, Symbol),
/// Transform done by the compiler on the AST.
AstPass(AstPass),
/// Desugaring done by the compiler during HIR lowering.
/// Desugaring done by the compiler during AST lowering.
Desugaring(DesugaringKind),
}

View File

@ -1,5 +1,5 @@
//! Computes a normalizes-to (projection) goal for inherent associated types,
//! `#![feature(inherent_associated_type)]`. Since astconv already determines
//! `#![feature(inherent_associated_type)]`. Since HIR ty lowering already determines
//! which impl the IAT is being projected from, we just:
//! 1. instantiate generic parameters,
//! 2. equate the self type, and

View File

@ -32,8 +32,9 @@ use std::ops::ControlFlow;
pub use crate::traits::{MethodViolationCode, ObjectSafetyViolation};
/// Returns the object safety violations that affect
/// astconv -- currently, `Self` in supertraits. This is needed
/// Returns the object safety violations that affect HIR ty lowering.
///
/// Currently that is `Self` in supertraits. This is needed
/// because `object_safety_violations` can't be used during
/// type collection.
pub fn hir_ty_lowering_object_safety_violations(

View File

@ -1264,7 +1264,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`,
// normalizing in the process, since `type_of` returns something directly from
// astconv (which means it's un-normalized).
// HIR ty lowering (which means it's un-normalized).
let source_tail = normalize_with_depth_to(
self,
obligation.param_env,

View File

@ -396,7 +396,7 @@ pub(crate) fn assoc_def(
// associated type. Normally this situation
// could only arise through a compiler bug --
// if the user wrote a bad item name, it
// should have failed in astconv.
// should have failed during HIR ty lowering.
bug!(
"No associated type `{}` for {}",
tcx.item_name(assoc_def_id),

View File

@ -60,7 +60,7 @@ impl AliasKind {
/// Defines the kinds of types used by the type system.
///
/// Types written by the user start out as `hir::TyKind` and get
/// converted to this representation using `AstConv::ast_ty_to_ty`.
/// converted to this representation using `<dyn HirTyLowerer>::lower_ty`.
#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")]
#[derive(derivative::Derivative)]
#[derivative(

View File

@ -118,10 +118,10 @@ Here the HIR sees the types without "thinking" about them, it knows that the fun
an `u32`. As far as `hir::Ty` is concerned those might be different types. But at the `ty::Ty` level the compiler
understands that they're the same type, in-depth lifetimes, etc...
To get from a `hir::Ty` to a `ty::Ty`, you can use the [`hir_ty_to_ty`][hir_ty_to_ty] function outside of bodies or
To get from a `hir::Ty` to a `ty::Ty`, you can use the [`lower_ty`][lower_ty] function outside of bodies or
the [`TypeckResults::node_type()`][node_type] method inside of bodies.
> **Warning**: Don't use `hir_ty_to_ty` inside of bodies, because this can cause ICEs.
> **Warning**: Don't use `lower_ty` inside of bodies, because this can cause ICEs.
## Creating Types programmatically
@ -162,6 +162,6 @@ in this chapter:
[Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html
[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/ty_kind/enum.TyKind.html
[TypeckResults]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html
[middle_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_middle/ty/struct.Ty.html
[hir_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir/struct.Ty.html
[hir_ty_to_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir_analysis/fn.hir_ty_to_ty.html
[middle_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html
[hir_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/struct.Ty.html
[lower_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/fn.lower_ty.html

View File

@ -56,7 +56,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath:
};
let inner_span = match qpath_generic_tys(inner_qpath).next() {
Some(hir_ty) => {
// Reallocation of a fat pointer causes it to become thin. `hir_ty_to_ty` is safe to use
// Reallocation of a fat pointer causes it to become thin. `lower_ty` is safe to use
// here because `mod.rs` guarantees this lint is only run on types outside of bodies and
// is not run on locals.
let ty = lower_ty(cx.tcx, hir_ty);

View File

@ -193,7 +193,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
}
fn check_body(&mut self, _: &LateContext<'_>, _: &hir::Body<'_>) {
// `hir_ty_to_ty` cannot be called in `Body`s or it will panic (sometimes). But in bodies
// `lower_ty` cannot be called in `Body`s or it will panic (sometimes). But in bodies
// we can use `cx.typeck_results.node_type(..)` to get the `ty::Ty` from a `hir::Ty`.
// However the `node_type()` method can *only* be called in bodies.
if let Some(&mut StackItem::Check { ref mut in_body, .. }) = self.stack.last_mut() {

View File

@ -1,5 +1,5 @@
//! This is a minimal reproducer for the ICE in https://github.com/rust-lang/rust-clippy/pull/6179.
//! The ICE is mainly caused by using `hir_ty_to_ty`. See the discussion in the PR for details.
//! The ICE is mainly caused by using `lower_ty`. See the discussion in the PR for details.
#![warn(clippy::use_self)]
#![allow(dead_code, clippy::let_with_type_underscore)]

View File

@ -1,5 +1,5 @@
//@ run-pass
// Test that astconv doesn't forget about mutability of &mut str
// Test that HIR ty lowering doesn't forget about mutability of `&mut str`.
//@ pretty-expanded FIXME #23616

View File

@ -1,4 +1,4 @@
// astconv uses `FreshTy(0)` as a dummy `Self` type when instanciating trait objects.
// HIR ty lowering uses `FreshTy(0)` as a dummy `Self` type when instanciating trait objects.
// This `FreshTy(0)` can leak into substs, causing ICEs in several places.
#![feature(trait_alias)]