compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs RUST 3,700 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 3,700.
1//! HIR ty lowering: Lowers type-system entities[^1] from the [HIR][hir] to2//! the [`rustc_middle::ty`] representation.3//!4//! Not to be confused with *AST lowering* which lowers AST constructs to HIR ones5//! or with *THIR* / *MIR* *lowering* / *building* which lowers HIR *bodies*6//! (i.e., “executable code”) to THIR / MIR.7//!8//! Most lowering routines are defined on [`dyn HirTyLowerer`](HirTyLowerer) directly,9//! like the main routine of this module, `lower_ty`.10//!11//! This module used to be called `astconv`.12//!13//! [^1]: This includes types, lifetimes / regions, constants in type positions,14//! trait references and bounds.1516mod bounds;17mod cmse;18mod dyn_trait;19pub mod errors;20pub mod generics;2122use std::{assert_matches, slice};2324use rustc_abi::FIRST_VARIANT;25use rustc_ast::LitKind;26use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};27use rustc_errors::codes::*;28use rustc_errors::{29    Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, StashKey,30    struct_span_code_err,31};32use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};33use rustc_hir::def_id::{DefId, LocalDefId};34use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId};35use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};36use rustc_infer::traits::DynCompatibilityViolation;37use rustc_macros::{TypeFoldable, TypeVisitable};38use rustc_middle::middle::stability::AllowUnstable;39use rustc_middle::ty::{40    self, Const, FnSigKind, GenericArgKind, GenericArgsRef, GenericParamDefKind, LitToConstInput,41    Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, TypingMode, Unnormalized, Upcast,42    const_lit_matches_ty, fold_regions,43};44use rustc_middle::{bug, span_bug};45use rustc_session::errors::feature_err;46use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;47use rustc_span::{DUMMY_SP, Ident, Span, kw, sym};48use rustc_trait_selection::infer::InferCtxtExt;49use rustc_trait_selection::traits::{self, FulfillmentError};50use tracing::{debug, instrument};5152use crate::check::check_abi;53use crate::diagnostics::{BadReturnTypeNotation, NoFieldOnType};54use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint};55use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};56use crate::middle::resolve_bound_vars as rbv;57use crate::{NoVariantNamed, check_c_variadic_abi};5859/// The context in which an implied bound is being added to a item being lowered (i.e. a sizedness60/// trait or a default trait)61#[derive(Clone, Copy)]62pub(crate) enum ImpliedBoundsContext<'tcx> {63    /// An implied bound is added to a trait definition (i.e. a new supertrait), used when adding64    /// a default `MetaSized` supertrait65    TraitDef(LocalDefId),66    /// An implied bound is added to a type parameter67    TyParam(LocalDefId, &'tcx [hir::WherePredicate<'tcx>]),68    /// An implied bound being added in any other context69    AssociatedTypeOrImplTrait,70}7172/// A path segment that is semantically allowed to have generic arguments.73#[derive(Debug)]74pub struct GenericPathSegment(pub DefId, pub usize);7576#[derive(Copy, Clone, Debug)]77pub enum PredicateFilter {78    /// All predicates may be implied by the trait.79    All,8081    /// Only traits that reference `Self: ..` are implied by the trait.82    SelfOnly,8384    /// Only traits that reference `Self: ..` and define an associated type85    /// with the given ident are implied by the trait. This mode exists to86    /// side-step query cycles when lowering associated types.87    SelfTraitThatDefines(Ident),8889    /// Only traits that reference `Self: ..` and their associated type bounds.90    /// For example, given `Self: Tr<A: B>`, this would expand to `Self: Tr`91    /// and `<Self as Tr>::A: B`.92    SelfAndAssociatedTypeBounds,9394    /// Filter only the `[const]` bounds, which are lowered into `HostEffect` clauses.95    ConstIfConst,9697    /// Filter only the `[const]` bounds which are *also* in the supertrait position.98    SelfConstIfConst,99}100101#[derive(Debug)]102pub enum RegionInferReason<'a> {103    /// Lifetime on a trait object that is spelled explicitly, e.g. `+ 'a` or `+ '_`.104    ExplicitObjectLifetime,105    /// A trait object's lifetime when it is elided, e.g. `dyn Any`.106    ObjectLifetimeDefault(Span),107    /// Generic lifetime parameter108    Param(&'a ty::GenericParamDef),109    RegionPredicate,110    Reference,111    OutlivesBound,112}113114#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Debug)]115pub struct InherentAssocCandidate {116    pub impl_: DefId,117    pub assoc_item: DefId,118    pub scope: DefId,119}120121pub struct ResolvedStructPath<'tcx> {122    pub res: Result<Res, ErrorGuaranteed>,123    pub ty: Ty<'tcx>,124}125126/// A context which can lower type-system entities from the [HIR][hir] to127/// the [`rustc_middle::ty`] representation.128///129/// This trait used to be called `AstConv`.130pub trait HirTyLowerer<'tcx> {131    fn tcx(&self) -> TyCtxt<'tcx>;132133    fn dcx(&self) -> DiagCtxtHandle<'_>;134135    /// Returns the [`LocalDefId`] of the overarching item whose constituents get lowered.136    fn item_def_id(&self) -> LocalDefId;137138    /// Returns the region to use when a lifetime is omitted (and not elided).139    fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx>;140141    /// Returns the type to use when a type is omitted.142    fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>;143144    /// Returns the const to use when a const is omitted.145    fn ct_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx>;146147    fn register_trait_ascription_bounds(148        &self,149        bounds: Vec<(ty::Clause<'tcx>, Span)>,150        hir_id: HirId,151        span: Span,152    );153154    /// Probe bounds in scope where the bounded type coincides with the given type parameter.155    ///156    /// Rephrased, this returns bounds of the form `T: Trait`, where `T` is a type parameter157    /// with the given `def_id`. This is a subset of the full set of bounds.158    ///159    /// This method may use the given `assoc_name` to disregard bounds whose trait reference160    /// doesn't define an associated item with the provided name.161    ///162    /// This is used for one specific purpose: Resolving “short-hand” associated type references163    /// like `T::Item` where `T` is a type parameter. In principle, we would do that by first164    /// getting the full set of predicates in scope and then filtering down to find those that165    /// apply to `T`, but this can lead to cycle errors. The problem is that we have to do this166    /// resolution *in order to create the predicates in the first place*.167    /// Hence, we have this “special pass”.168    fn probe_ty_param_bounds(169        &self,170        span: Span,171        def_id: LocalDefId,172        assoc_ident: Ident,173    ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]>;174175    fn select_inherent_assoc_candidates(176        &self,177        span: Span,178        self_ty: Ty<'tcx>,179        candidates: Vec<InherentAssocCandidate>,180    ) -> (Vec<InherentAssocCandidate>, Vec<FulfillmentError<'tcx>>);181182    /// Lower a path to an associated item (of a trait) to a projection.183    ///184    /// This method has to be defined by the concrete lowering context because185    /// dealing with higher-ranked trait references depends on its capabilities:186    ///187    /// If the context can make use of type inference, it can simply instantiate188    /// any late-bound vars bound by the trait reference with inference variables.189    /// If it doesn't support type inference, there is nothing reasonable it can190    /// do except reject the associated type.191    ///192    /// The canonical example of this is associated type `T::P` where `T` is a type193    /// param constrained by `T: for<'a> Trait<'a>` and where `Trait` defines `P`.194    fn lower_assoc_item_path(195        &self,196        span: Span,197        item_def_id: DefId,198        item_segment: &hir::PathSegment<'tcx>,199        poly_trait_ref: ty::PolyTraitRef<'tcx>,200    ) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed>;201202    fn lower_fn_sig(203        &self,204        decl: &hir::FnDecl<'tcx>,205        generics: Option<&hir::Generics<'_>>,206        hir_id: HirId,207        hir_ty: Option<&hir::Ty<'_>>,208    ) -> (Vec<Ty<'tcx>>, Ty<'tcx>);209210    /// Returns `AdtDef` if `ty` is an ADT.211    ///212    /// Note that `ty` might be a alias type that needs normalization.213    /// This used to get the enum variants in scope of the type.214    /// For example, `Self::A` could refer to an associated type215    /// or to an enum variant depending on the result of this function.216    fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>>;217218    /// Record the lowered type of a HIR node in this context.219    fn record_ty(&self, hir_id: HirId, ty: Ty<'tcx>, span: Span);220221    /// The inference context of the lowering context if applicable.222    fn infcx(&self) -> Option<&InferCtxt<'tcx>>;223224    /// Convenience method for coercing the lowering context into a trait object type.225    ///226    /// Most lowering routines are defined on the trait object type directly227    /// necessitating a coercion step from the concrete lowering context.228    fn lowerer(&self) -> &dyn HirTyLowerer<'tcx>229    where230        Self: Sized,231    {232        self233    }234235    /// Performs minimalistic dyn compat checks outside of bodies, but full within bodies.236    /// Outside of bodies we could end up in cycles, so we delay most checks to later phases.237    fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec<DynCompatibilityViolation>;238}239240/// The "qualified self" of an associated item path.241///242/// For diagnostic purposes only.243enum AssocItemQSelf {244    Trait(DefId),245    TyParam(LocalDefId, Span),246    SelfTyAlias,247}248249impl AssocItemQSelf {250    fn to_string(&self, tcx: TyCtxt<'_>) -> String {251        match *self {252            Self::Trait(def_id) => tcx.def_path_str(def_id),253            Self::TyParam(def_id, _) => tcx.hir_ty_param_name(def_id).to_string(),254            Self::SelfTyAlias => kw::SelfUpper.to_string(),255        }256    }257}258259#[derive(Debug, Clone, Copy)]260enum LowerTypeRelativePathMode {261    Type(PermitVariants),262    Const,263}264265impl LowerTypeRelativePathMode {266    fn assoc_tag(self) -> ty::AssocTag {267        match self {268            Self::Type(_) => ty::AssocTag::Type,269            Self::Const => ty::AssocTag::Const,270        }271    }272273    ///NOTE: use `assoc_tag` for any important logic274    fn def_kind_for_diagnostics(self) -> DefKind {275        match self {276            Self::Type(_) => DefKind::AssocTy,277            Self::Const => DefKind::AssocConst { is_type_const: false },278        }279    }280281    fn permit_variants(self) -> PermitVariants {282        match self {283            Self::Type(permit_variants) => permit_variants,284            // FIXME(mgca): Support paths like `Option::<T>::None` or `Option::<T>::Some` which285            // resolve to const ctors/fn items respectively.286            Self::Const => PermitVariants::No,287        }288    }289}290291/// Whether to permit a path to resolve to an enum variant.292#[derive(Debug, Clone, Copy)]293pub enum PermitVariants {294    Yes,295    No,296}297298#[derive(Debug, Clone, Copy)]299enum TypeRelativePath<'tcx> {300    AssocItem(ty::AliasTerm<'tcx>),301    Variant { adt: Ty<'tcx>, variant_did: DefId },302    Ctor { ctor_def_id: DefId, args: GenericArgsRef<'tcx> },303}304305/// New-typed boolean indicating whether explicit late-bound lifetimes306/// are present in a set of generic arguments.307///308/// For example if we have some method `fn f<'a>(&'a self)` implemented309/// for some type `T`, although `f` is generic in the lifetime `'a`, `'a`310/// is late-bound so should not be provided explicitly. Thus, if `f` is311/// instantiated with some generic arguments providing `'a` explicitly,312/// we taint those arguments with `ExplicitLateBound::Yes` so that we313/// can provide an appropriate diagnostic later.314#[derive(Copy, Clone, PartialEq, Debug)]315pub enum ExplicitLateBound {316    Yes,317    No,318}319320#[derive(Debug, Copy, Clone, PartialEq)]321pub enum IsMethodCall {322    Yes,323    No,324}325326/// Denotes the "position" of a generic argument, indicating if it is a generic type,327/// generic function or generic method call.328#[derive(Debug, Copy, Clone, PartialEq)]329pub(crate) enum GenericArgPosition {330    Type,331    Value(IsMethodCall),332}333334/// Whether to allow duplicate associated iten constraints in a trait ref, e.g.335/// `Trait<Assoc = Ty, Assoc = Ty>`. This is forbidden in `dyn Trait<...>`336/// but allowed everywhere else.337#[derive(Clone, Copy, Debug, PartialEq)]338pub(crate) enum OverlappingAsssocItemConstraints {339    Allowed,340    Forbidden,341}342343/// A marker denoting that the generic arguments that were344/// provided did not match the respective generic parameters.345#[derive(Clone, Debug)]346pub struct GenericArgCountMismatch {347    pub reported: ErrorGuaranteed,348    /// A list of indices of arguments provided that were not valid.349    pub invalid_args: Vec<usize>,350}351352/// Decorates the result of a generic argument count mismatch353/// check with whether explicit late bounds were provided.354#[derive(Clone, Debug)]355pub struct GenericArgCountResult {356    pub explicit_late_bound: ExplicitLateBound,357    pub correct: Result<(), GenericArgCountMismatch>,358}359360/// A context which can lower HIR's [`GenericArg`] to `rustc_middle`'s [`ty::GenericArg`].361///362/// Its only consumer is [`generics::lower_generic_args`].363/// Read its documentation to learn more.364pub trait GenericArgsLowerer<'a, 'tcx> {365    fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool);366367    fn provided_kind(368        &mut self,369        preceding_args: &[ty::GenericArg<'tcx>],370        param: &ty::GenericParamDef,371        arg: &GenericArg<'tcx>,372    ) -> ty::GenericArg<'tcx>;373374    fn inferred_kind(375        &mut self,376        preceding_args: &[ty::GenericArg<'tcx>],377        param: &ty::GenericParamDef,378        infer_args: bool,379    ) -> ty::GenericArg<'tcx>;380}381382/// Context in which `ForbidParamUsesFolder` is being used, to emit appropriate diagnostics.383enum ForbidParamContext {384    /// Anon const in a const argument position.385    ConstArgument,386    /// Enum discriminant expression.387    EnumDiscriminant,388}389390struct ForbidParamUsesFolder<'tcx> {391    tcx: TyCtxt<'tcx>,392    anon_const_def_id: LocalDefId,393    span: Span,394    is_self_alias: bool,395    context: ForbidParamContext,396}397398impl<'tcx> ForbidParamUsesFolder<'tcx> {399    fn error(&self) -> ErrorGuaranteed {400        let msg = match self.context {401            ForbidParamContext::EnumDiscriminant if self.is_self_alias => {402                "generic `Self` types are not permitted in enum discriminant values"403            }404            ForbidParamContext::EnumDiscriminant => {405                "generic parameters may not be used in enum discriminant values"406            }407            ForbidParamContext::ConstArgument if self.is_self_alias => {408                "generic `Self` types are currently not permitted in anonymous constants"409            }410            ForbidParamContext::ConstArgument => {411                if self.tcx.features().generic_const_args() {412                    "generic parameters in const blocks are not allowed; use a named `const` item instead"413                } else {414                    "generic parameters may not be used in const operations"415                }416            }417        };418        let mut diag = self.tcx.dcx().struct_span_err(self.span, msg);419        if self.is_self_alias && matches!(self.context, ForbidParamContext::ConstArgument) {420            let anon_const_hir_id: HirId = HirId::make_owner(self.anon_const_def_id);421            let parent_impl = self.tcx.hir_parent_owner_iter(anon_const_hir_id).find_map(422                |(_, node)| match node {423                    hir::OwnerNode::Item(hir::Item {424                        kind: hir::ItemKind::Impl(impl_), ..425                    }) => Some(impl_),426                    _ => None,427                },428            );429            if let Some(impl_) = parent_impl {430                diag.span_note(impl_.self_ty.span, "not a concrete type");431            }432        }433        if matches!(self.context, ForbidParamContext::ConstArgument)434            && self.tcx.features().min_generic_const_args()435        {436            if !self.tcx.features().generic_const_args() {437                diag.help("add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items");438            } else {439                diag.help("consider factoring the expression into a `type const` item and use it as the const argument instead");440            }441        }442        diag.emit()443    }444}445446impl<'tcx> ty::TypeFolder<TyCtxt<'tcx>> for ForbidParamUsesFolder<'tcx> {447    fn cx(&self) -> TyCtxt<'tcx> {448        self.tcx449    }450451    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {452        if matches!(t.kind(), ty::Param(..)) {453            return Ty::new_error(self.tcx, self.error());454        }455        t.super_fold_with(self)456    }457458    fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {459        if matches!(c.kind(), ty::ConstKind::Param(..)) {460            return Const::new_error(self.tcx, self.error());461        }462        c.super_fold_with(self)463    }464465    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {466        if matches!(r.kind(), ty::RegionKind::ReEarlyParam(..) | ty::RegionKind::ReLateParam(..)) {467            return ty::Region::new_error(self.tcx, self.error());468        }469        r470    }471}472473impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {474    /// See `check_param_uses_if_mcg`.475    ///476    /// FIXME(mgca): this is pub only for instantiate_value_path and would be nice to avoid altogether477    pub fn check_param_res_if_mcg_for_instantiate_value_path(478        &self,479        res: Res,480        span: Span,481    ) -> Result<(), ErrorGuaranteed> {482        let tcx = self.tcx();483        let parent_def_id = self.item_def_id();484        if let Res::Def(DefKind::ConstParam, _) = res485            && tcx.def_kind(parent_def_id) == DefKind::AnonConst486            && let ty::AnonConstKind::MCG = tcx.anon_const_kind(parent_def_id)487        {488            let folder = ForbidParamUsesFolder {489                tcx,490                anon_const_def_id: parent_def_id,491                span,492                is_self_alias: false,493                context: ForbidParamContext::ConstArgument,494            };495            return Err(folder.error());496        }497        Ok(())498    }499500    /// Returns the `ForbidParamContext` for the current anon const if it is a context that501    /// forbids uses of generic parameters. `None` if the current item is not such a context.502    ///503    /// Name resolution handles most invalid generic parameter uses in these contexts, but it504    /// cannot reject `Self` that aliases a generic type, nor generic parameters introduced by505    /// type-dependent name resolution (e.g. `<Self as Trait>::Assoc` resolving to a type that506    /// contains params). Those cases are handled by `check_param_uses_if_mcg`.507    fn anon_const_forbids_generic_params(&self) -> Option<ForbidParamContext> {508        let tcx = self.tcx();509        let parent_def_id = self.item_def_id();510511        // Inline consts and closures can be nested inside anon consts that forbid generic512        // params (e.g. an enum discriminant). Walk up the def parent chain to find the513        // nearest enclosing AnonConst and use that to determine the context.514        let anon_const_def_id = match tcx.def_kind(parent_def_id) {515            DefKind::AnonConst => parent_def_id,516            DefKind::InlineConst | DefKind::Closure => {517                let root = tcx.typeck_root_def_id(parent_def_id.into());518                match tcx.def_kind(root) {519                    DefKind::AnonConst => root.expect_local(),520                    _ => return None,521                }522            }523            _ => return None,524        };525526        match tcx.anon_const_kind(anon_const_def_id) {527            ty::AnonConstKind::MCG => Some(ForbidParamContext::ConstArgument),528            ty::AnonConstKind::NonTypeSystem => {529                // NonTypeSystem anon consts only have accessible generic parameters in specific530                // positions (ty patterns and field defaults — see `generics_of`). In all other531                // positions (e.g. enum discriminants) generic parameters are not in scope.532                if tcx.generics_of(anon_const_def_id).count() == 0 {533                    Some(ForbidParamContext::EnumDiscriminant)534                } else {535                    None536                }537            }538            ty::AnonConstKind::GCE | ty::AnonConstKind::RepeatExprCount => None,539        }540    }541542    /// Check for uses of generic parameters that are not in scope due to this being543    /// in a non-generic anon const context (e.g. MCG or an enum discriminant).544    ///545    /// Name resolution rejects most invalid uses, but cannot handle `Self` aliasing a546    /// generic type or generic parameters introduced by type-dependent name resolution.547    #[must_use = "need to use transformed output"]548    fn check_param_uses_if_mcg<T>(&self, term: T, span: Span, is_self_alias: bool) -> T549    where550        T: ty::TypeFoldable<TyCtxt<'tcx>>,551    {552        let tcx = self.tcx();553        if let Some(context) = self.anon_const_forbids_generic_params()554            // Fast path if contains no params/escaping bound vars.555            && (term.has_param() || term.has_escaping_bound_vars())556        {557            let anon_const_def_id = self.item_def_id();558            let mut folder =559                ForbidParamUsesFolder { tcx, anon_const_def_id, span, is_self_alias, context };560            term.fold_with(&mut folder)561        } else {562            term563        }564    }565566    /// Lower a lifetime from the HIR to our internal notion of a lifetime called a *region*.567    #[instrument(level = "debug", skip(self), ret)]568    pub fn lower_lifetime(569        &self,570        lifetime: &hir::Lifetime,571        reason: RegionInferReason<'_>,572    ) -> ty::Region<'tcx> {573        if let Some(resolved) = self.tcx().named_bound_var(lifetime.hir_id) {574            let region = self.lower_resolved_lifetime(resolved);575            self.check_param_uses_if_mcg(region, lifetime.ident.span, false)576        } else {577            self.re_infer(lifetime.ident.span, reason)578        }579    }580581    /// Lower a lifetime from the HIR to our internal notion of a lifetime called a *region*.582    #[instrument(level = "debug", skip(self), ret)]583    fn lower_resolved_lifetime(&self, resolved: rbv::ResolvedArg) -> ty::Region<'tcx> {584        let tcx = self.tcx();585586        match resolved {587            rbv::ResolvedArg::StaticLifetime => tcx.lifetimes.re_static,588589            rbv::ResolvedArg::LateBound(debruijn, index, def_id) => {590                let br = ty::BoundRegion {591                    var: ty::BoundVar::from_u32(index),592                    kind: ty::BoundRegionKind::Named(def_id.to_def_id()),593                };594                ty::Region::new_bound(tcx, debruijn, br)595            }596597            rbv::ResolvedArg::EarlyBound(def_id) => {598                let name = tcx.hir_ty_param_name(def_id);599                let item_def_id = tcx.hir_ty_param_owner(def_id);600                let generics = tcx.generics_of(item_def_id);601                let index = generics.param_def_id_to_index[&def_id.to_def_id()];602                ty::Region::new_early_param(tcx, ty::EarlyParamRegion { index, name })603            }604605            rbv::ResolvedArg::Free(scope, id) => {606                ty::Region::new_late_param(607                    tcx,608                    scope.to_def_id(),609                    ty::LateParamRegionKind::Named(id.to_def_id()),610                )611612                // (*) -- not late-bound, won't change613            }614615            rbv::ResolvedArg::Error(guar) => ty::Region::new_error(tcx, guar),616        }617    }618619    pub fn lower_generic_args_of_path_segment(620        &self,621        span: Span,622        def_id: DefId,623        item_segment: &hir::PathSegment<'tcx>,624    ) -> GenericArgsRef<'tcx> {625        let (args, _) = self.lower_generic_args_of_path(span, def_id, &[], item_segment, None);626        if let Some(c) = item_segment.args().constraints.first() {627            prohibit_assoc_item_constraint(self, c, Some((def_id, item_segment, span)));628        }629        args630    }631632    /// Lower the generic arguments provided to some path.633    ///634    /// If this is a trait reference, you also need to pass the self type `self_ty`.635    /// The lowering process may involve applying defaulted type parameters.636    ///637    /// Associated item constraints are not handled here! They are either lowered via638    /// `lower_assoc_item_constraint` or rejected via `prohibit_assoc_item_constraint`.639    ///640    /// ### Example641    ///642    /// ```ignore (illustrative)643    ///    T: std::ops::Index<usize, Output = u32>644    /// // ^1 ^^^^^^^^^^^^^^2 ^^^^3  ^^^^^^^^^^^4645    /// ```646    ///647    /// 1. The `self_ty` here would refer to the type `T`.648    /// 2. The path in question is the path to the trait `std::ops::Index`,649    ///    which will have been resolved to a `def_id`650    /// 3. The `generic_args` contains info on the `<...>` contents. The `usize` type651    ///    parameters are returned in the `GenericArgsRef`652    /// 4. Associated item constraints like `Output = u32` are contained in `generic_args.constraints`.653    ///654    /// Note that the type listing given here is *exactly* what the user provided.655    ///656    /// For (generic) associated types657    ///658    /// ```ignore (illustrative)659    /// <Vec<u8> as Iterable<u8>>::Iter::<'a>660    /// ```661    ///662    /// We have the parent args are the args for the parent trait:663    /// `[Vec<u8>, u8]` and `generic_args` are the arguments for the associated664    /// type itself: `['a]`. The returned `GenericArgsRef` concatenates these two665    /// lists: `[Vec<u8>, u8, 'a]`.666    #[instrument(level = "debug", skip(self, span), ret)]667    pub(crate) fn lower_generic_args_of_path(668        &self,669        span: Span,670        def_id: DefId,671        parent_args: &[ty::GenericArg<'tcx>],672        segment: &hir::PathSegment<'tcx>,673        self_ty: Option<Ty<'tcx>>,674    ) -> (GenericArgsRef<'tcx>, GenericArgCountResult) {675        // If the type is parameterized by this region, then replace this676        // region with the current anon region binding (in other words,677        // whatever & would get replaced with).678679        let tcx = self.tcx();680        let generics = tcx.generics_of(def_id);681        debug!(?generics);682683        if generics.has_self {684            if generics.parent.is_some() {685                // The parent is a trait so it should have at least one686                // generic parameter for the `Self` type.687                assert!(!parent_args.is_empty())688            } else {689                // This item (presumably a trait) needs a self-type.690                assert!(self_ty.is_some());691            }692        } else {693            assert!(self_ty.is_none());694        }695696        let arg_count = check_generic_arg_count(697            self,698            def_id,699            segment,700            generics,701            GenericArgPosition::Type,702            self_ty.is_some(),703        );704705        // Skip processing if type has no generic parameters.706        // Traits always have `Self` as a generic parameter, which means they will not return early707        // here and so associated item constraints will be handled regardless of whether there are708        // any non-`Self` generic parameters.709        if generics.is_own_empty() {710            return (tcx.mk_args(parent_args), arg_count);711        }712713        struct GenericArgsCtxt<'a, 'tcx> {714            lowerer: &'a dyn HirTyLowerer<'tcx>,715            def_id: DefId,716            generic_args: &'a GenericArgs<'tcx>,717            span: Span,718            infer_args: bool,719            incorrect_args: &'a Result<(), GenericArgCountMismatch>,720        }721722        impl<'a, 'tcx> GenericArgsLowerer<'a, 'tcx> for GenericArgsCtxt<'a, 'tcx> {723            fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool) {724                if did == self.def_id {725                    (Some(self.generic_args), self.infer_args)726                } else {727                    // The last component of this tuple is unimportant.728                    (None, false)729                }730            }731732            fn provided_kind(733                &mut self,734                preceding_args: &[ty::GenericArg<'tcx>],735                param: &ty::GenericParamDef,736                arg: &GenericArg<'tcx>,737            ) -> ty::GenericArg<'tcx> {738                let tcx = self.lowerer.tcx();739740                if let Err(incorrect) = self.incorrect_args {741                    if incorrect.invalid_args.contains(&(param.index as usize)) {742                        return param.to_error(tcx);743                    }744                }745746                let handle_ty_args = |has_default, ty: &hir::Ty<'tcx>| {747                    if has_default {748                        tcx.check_optional_stability(749                            param.def_id,750                            Some(arg.hir_id()),751                            arg.span(),752                            None,753                            AllowUnstable::No,754                            |_, _| {755                                // Default generic parameters may not be marked756                                // with stability attributes, i.e. when the757                                // default parameter was defined at the same time758                                // as the rest of the type. As such, we ignore missing759                                // stability attributes.760                            },761                        );762                    }763                    self.lowerer.lower_ty(ty).into()764                };765766                match (&param.kind, arg) {767                    (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {768                        self.lowerer.lower_lifetime(lt, RegionInferReason::Param(param)).into()769                    }770                    (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => {771                        // We handle the other parts of `Ty` in the match arm below772                        handle_ty_args(has_default, ty.as_unambig_ty())773                    }774                    (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => {775                        handle_ty_args(has_default, &inf.to_ty())776                    }777                    (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => self778                        .lowerer779                        // Ambig portions of `ConstArg` are handled in the match arm below780                        .lower_const_arg(781                            ct.as_unambig_ct(),782                            tcx.type_of(param.def_id)783                                .instantiate(tcx, preceding_args)784                                .skip_norm_wip(),785                        )786                        .into(),787                    (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {788                        self.lowerer.ct_infer(Some(param), inf.span).into()789                    }790                    (kind, arg) => span_bug!(791                        self.span,792                        "mismatched path argument for kind {kind:?}: found arg {arg:?}"793                    ),794                }795            }796797            fn inferred_kind(798                &mut self,799                preceding_args: &[ty::GenericArg<'tcx>],800                param: &ty::GenericParamDef,801                infer_args: bool,802            ) -> ty::GenericArg<'tcx> {803                let tcx = self.lowerer.tcx();804805                if let Err(incorrect) = self.incorrect_args {806                    if incorrect.invalid_args.contains(&(param.index as usize)) {807                        return param.to_error(tcx);808                    }809                }810                match param.kind {811                    GenericParamDefKind::Lifetime => {812                        self.lowerer.re_infer(self.span, RegionInferReason::Param(param)).into()813                    }814                    GenericParamDefKind::Type { has_default, synthetic } => {815                        if !infer_args && has_default {816                            // No type parameter provided, but a default exists.817                            if let Some(prev) =818                                preceding_args.iter().find_map(|arg| match arg.kind() {819                                    GenericArgKind::Type(ty) => ty.error_reported().err(),820                                    _ => None,821                                })822                            {823                                // Avoid ICE #86756 when type error recovery goes awry.824                                return Ty::new_error(tcx, prev).into();825                            }826                            tcx.at(self.span)827                                .type_of(param.def_id)828                                .instantiate(tcx, preceding_args)829                                .skip_norm_wip()830                                .into()831                        } else if synthetic {832                            Ty::new_param(tcx, param.index, param.name).into()833                        } else if infer_args {834                            self.lowerer.ty_infer(Some(param), self.span).into()835                        } else {836                            // We've already errored above about the mismatch.837                            Ty::new_misc_error(tcx).into()838                        }839                    }840                    GenericParamDefKind::Const { has_default, .. } => {841                        let ty = tcx842                            .at(self.span)843                            .type_of(param.def_id)844                            .instantiate(tcx, preceding_args)845                            .skip_norm_wip();846                        if let Err(guar) = ty.error_reported() {847                            return ty::Const::new_error(tcx, guar).into();848                        }849                        if !infer_args && has_default {850                            tcx.const_param_default(param.def_id)851                                .instantiate(tcx, preceding_args)852                                .skip_norm_wip()853                                .into()854                        } else if infer_args {855                            self.lowerer.ct_infer(Some(param), self.span).into()856                        } else {857                            // We've already errored above about the mismatch.858                            ty::Const::new_misc_error(tcx).into()859                        }860                    }861                }862            }863        }864865        let mut args_ctx = GenericArgsCtxt {866            lowerer: self,867            def_id,868            span,869            generic_args: segment.args(),870            infer_args: segment.infer_args,871            incorrect_args: &arg_count.correct,872        };873874        let args = lower_generic_args(875            self,876            def_id,877            parent_args,878            self_ty.is_some(),879            self_ty,880            &arg_count,881            &mut args_ctx,882        );883884        (args, arg_count)885    }886887    #[instrument(level = "debug", skip(self))]888    pub fn lower_generic_args_of_assoc_item(889        &self,890        span: Span,891        item_def_id: DefId,892        item_segment: &hir::PathSegment<'tcx>,893        parent_args: GenericArgsRef<'tcx>,894    ) -> GenericArgsRef<'tcx> {895        let (args, _) =896            self.lower_generic_args_of_path(span, item_def_id, parent_args, item_segment, None);897        if let Some(c) = item_segment.args().constraints.first() {898            prohibit_assoc_item_constraint(self, c, Some((item_def_id, item_segment, span)));899        }900        args901    }902903    /// Lower a trait reference as found in an impl header as the implementee.904    ///905    /// The self type `self_ty` is the implementer of the trait.906    pub fn lower_impl_trait_ref(907        &self,908        trait_ref: &hir::TraitRef<'tcx>,909        self_ty: Ty<'tcx>,910    ) -> ty::TraitRef<'tcx> {911        let [leading_segments @ .., segment] = trait_ref.path.segments else { bug!() };912913        let _ = self.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);914915        self.lower_mono_trait_ref(916            trait_ref.path.span,917            trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),918            self_ty,919            segment,920            true,921        )922    }923924    /// Lower a polymorphic trait reference given a self type into `bounds`.925    ///926    /// *Polymorphic* in the sense that it may bind late-bound vars.927    ///928    /// This may generate auxiliary bounds iff the trait reference contains associated item constraints.929    ///930    /// ### Example931    ///932    /// Given the trait ref `Iterator<Item = u32>` and the self type `Ty`, this will add the933    ///934    /// 1. *trait predicate* `<Ty as Iterator>` (known as `Ty: Iterator` in the surface syntax) and the935    /// 2. *projection predicate* `<Ty as Iterator>::Item = u32`936    ///937    /// to `bounds`.938    ///939    /// ### A Note on Binders940    ///941    /// Against our usual convention, there is an implied binder around the `self_ty` and the942    /// `trait_ref` here. So they may reference late-bound vars.943    ///944    /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>`945    /// where `'a` is a bound region at depth 0. Similarly, the `trait_ref` would be `Bar<'a>`.946    /// The lowered poly-trait-ref will track this binder explicitly, however.947    #[instrument(level = "debug", skip(self, bounds))]948    pub(crate) fn lower_poly_trait_ref(949        &self,950        &hir::PolyTraitRef {951            bound_generic_params,952            modifiers: hir::TraitBoundModifiers { constness, polarity },953            trait_ref,954            span,955        }: &hir::PolyTraitRef<'tcx>,956        self_ty: Ty<'tcx>,957        bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,958        predicate_filter: PredicateFilter,959        overlapping_assoc_item_constraints: OverlappingAsssocItemConstraints,960    ) -> GenericArgCountResult {961        let tcx = self.tcx();962963        // We use the *resolved* bound vars later instead of the HIR ones since the former964        // also include the bound vars of the overarching predicate if applicable.965        let _ = bound_generic_params;966967        let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());968969        // Relaxed bounds `?Trait` and `PointeeSized` bounds aren't represented in the middle::ty IR970        // as they denote the *absence* of a default bound. However, we can't bail out early here since971        // we still need to perform several validation steps (see below). Instead, simply "pour" all972        // resulting bounds "down the drain", i.e., into a new `Vec` that just gets dropped at the end.973        let transient = match polarity {974            hir::BoundPolarity::Positive => {975                // To elaborate on the comment directly above, regarding `PointeeSized` specifically,976                // we don't "reify" such bounds to avoid trait system limitations -- namely,977                // non-global where-clauses being preferred over item bounds (where `PointeeSized`978                // bounds would be proven) -- which can result in errors when a `PointeeSized`979                // supertrait / bound / predicate is added to some items.980                tcx.is_lang_item(trait_def_id, hir::LangItem::PointeeSized)981            }982            hir::BoundPolarity::Negative(_) => false,983            hir::BoundPolarity::Maybe(_) => {984                self.require_bound_to_relax_default_trait(trait_ref, span);985                true986            }987        };988        let bounds = if transient { &mut Vec::new() } else { bounds };989990        let polarity = match polarity {991            hir::BoundPolarity::Positive | hir::BoundPolarity::Maybe(_) => {992                ty::PredicatePolarity::Positive993            }994            hir::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,995        };996997        let [leading_segments @ .., segment] = trait_ref.path.segments else { bug!() };998999        let _ = self.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);1000        self.report_internal_fn_trait(span, trait_def_id, segment, false);10011002        let (generic_args, arg_count) = self.lower_generic_args_of_path(1003            trait_ref.path.span,1004            trait_def_id,1005            &[],1006            segment,1007            Some(self_ty),1008        );10091010        let constraints = segment.args().constraints;10111012        if transient && (!generic_args[1..].is_empty() || !constraints.is_empty()) {1013            // Since the bound won't be present in the middle::ty IR as established above, any1014            // arguments or constraints won't be checked for well-formedness in later passes.1015            //1016            // This is only an issue if the trait ref is otherwise valid which can only happen if1017            // the corresponding default trait has generic parameters or associated items. Such a1018            // trait would be degenerate. We delay a bug to detect and guard us against these.1019            //1020            // E.g: Given `/*default*/ trait Bound<'a: 'static, T, const N: usize> {}`,1021            // `?Bound<Vec<str>, { panic!() }>` won't be wfchecked.1022            self.dcx()1023                .span_delayed_bug(span, "transient bound should not have args or constraints");1024        }10251026        let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);1027        debug!(?bound_vars);10281029        let poly_trait_ref = ty::Binder::bind_with_vars(1030            ty::TraitRef::new_from_args(tcx, trait_def_id, generic_args),1031            bound_vars,1032        );10331034        debug!(?poly_trait_ref);10351036        // We deal with const conditions later.1037        match predicate_filter {1038            PredicateFilter::All1039            | PredicateFilter::SelfOnly1040            | PredicateFilter::SelfTraitThatDefines(..)1041            | PredicateFilter::SelfAndAssociatedTypeBounds => {1042                let bound = poly_trait_ref.map_bound(|trait_ref| {1043                    ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity })1044                });1045                let bound = (bound.upcast(tcx), span);1046                // FIXME(-Znext-solver): We can likely remove this hack once the1047                // new trait solver lands. This fixed an overflow in the old solver.1048                // This may have performance implications, so please check perf when1049                // removing it.1050                // This was added in <https://github.com/rust-lang/rust/pull/123302>.1051                if tcx.is_lang_item(trait_def_id, rustc_hir::LangItem::Sized) {1052                    bounds.insert(0, bound);1053                } else {1054                    bounds.push(bound);1055                }1056            }1057            PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}1058        }10591060        if let hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) = constness1061            && !tcx.is_const_trait(trait_def_id)1062        {1063            let (def_span, suggestion, suggestion_pre) =1064                match (trait_def_id.as_local(), tcx.sess.is_nightly_build()) {1065                    (Some(trait_def_id), true) => {1066                        let span = tcx.hir_expect_item(trait_def_id).vis_span;1067                        let span = tcx.sess.source_map().span_extend_while_whitespace(span);10681069                        (1070                            None,1071                            Some(span.shrink_to_hi()),1072                            if self.tcx().features().const_trait_impl() {1073                                ""1074                            } else {1075                                "enable `#![feature(const_trait_impl)]` in your crate and "1076                            },1077                        )1078                    }1079                    (None, _) | (_, false) => (Some(tcx.def_span(trait_def_id)), None, ""),1080                };1081            self.dcx().emit_err(crate::diagnostics::ConstBoundForNonConstTrait {1082                span,1083                modifier: constness.as_str(),1084                def_span,1085                trait_name: tcx.def_path_str(trait_def_id),1086                suggestion,1087                suggestion_pre,1088            });1089        } else {1090            match predicate_filter {1091                // This is only concerned with trait predicates.1092                PredicateFilter::SelfTraitThatDefines(..) => {}1093                PredicateFilter::All1094                | PredicateFilter::SelfOnly1095                | PredicateFilter::SelfAndAssociatedTypeBounds => {1096                    match constness {1097                        hir::BoundConstness::Always(_) => {1098                            if polarity == ty::PredicatePolarity::Positive {1099                                bounds.push((1100                                    poly_trait_ref1101                                        .to_host_effect_clause(tcx, ty::BoundConstness::Const),1102                                    span,1103                                ));1104                            }1105                        }1106                        hir::BoundConstness::Maybe(_) => {1107                            // We don't emit a const bound here, since that would mean that we1108                            // unconditionally need to prove a `HostEffect` predicate, even when1109                            // the predicates are being instantiated in a non-const context. This1110                            // is instead handled in the `const_conditions` query.1111                        }1112                        hir::BoundConstness::Never => {}1113                    }1114                }1115                // On the flip side, when filtering `ConstIfConst` bounds, we only need to convert1116                // `[const]` bounds. All other predicates are handled in their respective queries.1117                //1118                // Note that like `PredicateFilter::SelfOnly`, we don't need to do any filtering1119                // here because we only call this on self bounds, and deal with the recursive case1120                // in `lower_assoc_item_constraint`.1121                PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {1122                    match constness {1123                        hir::BoundConstness::Maybe(_) => {1124                            if polarity == ty::PredicatePolarity::Positive {1125                                bounds.push((1126                                    poly_trait_ref1127                                        .to_host_effect_clause(tcx, ty::BoundConstness::Maybe),1128                                    span,1129                                ));1130                            }1131                        }1132                        hir::BoundConstness::Always(_) | hir::BoundConstness::Never => {}1133                    }1134                }1135            }1136        }11371138        let mut dup_constraints = (overlapping_assoc_item_constraints1139            == OverlappingAsssocItemConstraints::Forbidden)1140            .then_some(FxIndexMap::default());11411142        for constraint in constraints {1143            // Don't register any associated item constraints for negative bounds,1144            // since we should have emitted an error for them earlier, and they1145            // would not be well-formed!1146            if polarity == ty::PredicatePolarity::Negative {1147                self.dcx().span_delayed_bug(1148                    constraint.span,1149                    "negative trait bounds should not have assoc item constraints",1150                );1151                break;1152            }11531154            // Specify type to assert that error was already reported in `Err` case.1155            let _: Result<_, ErrorGuaranteed> = self.lower_assoc_item_constraint(1156                trait_ref.hir_ref_id,1157                poly_trait_ref,1158                constraint,1159                bounds,1160                dup_constraints.as_mut(),1161                constraint.span,1162                predicate_filter,1163            );1164            // Okay to ignore `Err` because of `ErrorGuaranteed` (see above).1165        }11661167        arg_count1168    }11691170    /// Lower a monomorphic trait reference given a self type while prohibiting associated item bindings.1171    ///1172    /// *Monomorphic* in the sense that it doesn't bind any late-bound vars.1173    fn lower_mono_trait_ref(1174        &self,1175        span: Span,1176        trait_def_id: DefId,1177        self_ty: Ty<'tcx>,1178        trait_segment: &hir::PathSegment<'tcx>,1179        is_impl: bool,1180    ) -> ty::TraitRef<'tcx> {1181        self.report_internal_fn_trait(span, trait_def_id, trait_segment, is_impl);11821183        let (generic_args, _) =1184            self.lower_generic_args_of_path(span, trait_def_id, &[], trait_segment, Some(self_ty));1185        if let Some(c) = trait_segment.args().constraints.first() {1186            prohibit_assoc_item_constraint(self, c, Some((trait_def_id, trait_segment, span)));1187        }1188        ty::TraitRef::new_from_args(self.tcx(), trait_def_id, generic_args)1189    }11901191    fn probe_trait_that_defines_assoc_item(1192        &self,1193        trait_def_id: DefId,1194        assoc_tag: ty::AssocTag,1195        assoc_ident: Ident,1196    ) -> bool {1197        self.tcx()1198            .associated_items(trait_def_id)1199            .find_by_ident_and_kind(self.tcx(), assoc_ident, assoc_tag, trait_def_id)1200            .is_some()1201    }12021203    fn lower_path_segment(1204        &self,1205        span: Span,1206        def_id: DefId,1207        item_segment: &hir::PathSegment<'tcx>,1208    ) -> Ty<'tcx> {1209        let tcx = self.tcx();1210        let args = self.lower_generic_args_of_path_segment(span, def_id, item_segment);12111212        if let DefKind::TyAlias = tcx.def_kind(def_id)1213            && tcx.type_alias_is_lazy(def_id)1214        {1215            // Type aliases defined in crates that have the1216            // feature `lazy_type_alias` enabled get encoded as a type alias that normalization will1217            // then actually instantiate the where bounds of.1218            let alias_ty = ty::AliasTy::new_from_args(tcx, ty::Free { def_id }, args);1219            Ty::new_alias(tcx, alias_ty)1220        } else {1221            tcx.at(span).type_of(def_id).instantiate(tcx, args).skip_norm_wip()1222        }1223    }12241225    /// Search for a trait bound on a type parameter whose trait defines the associated item1226    /// given by `assoc_ident` and `kind`.1227    ///1228    /// This fails if there is no such bound in the list of candidates or if there are multiple1229    /// candidates in which case it reports ambiguity.1230    ///1231    /// `ty_param_def_id` is the `LocalDefId` of the type parameter.1232    #[instrument(level = "debug", skip_all, ret)]1233    fn probe_single_ty_param_bound_for_assoc_item(1234        &self,1235        ty_param_def_id: LocalDefId,1236        ty_param_span: Span,1237        assoc_tag: ty::AssocTag,1238        assoc_ident: Ident,1239        span: Span,1240    ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {1241        debug!(?ty_param_def_id, ?assoc_ident, ?span);1242        let tcx = self.tcx();12431244        let predicates = &self.probe_ty_param_bounds(span, ty_param_def_id, assoc_ident);1245        debug!("predicates={:#?}", predicates);12461247        self.probe_single_bound_for_assoc_item(1248            || {1249                let trait_refs = predicates1250                    .iter_identity_copied()1251                    .map(Unnormalized::skip_norm_wip)1252                    .filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref)));1253                traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_ident)1254            },1255            AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span),1256            assoc_tag,1257            assoc_ident,1258            span,1259            None,1260        )1261    }12621263    /// Search for a single trait bound whose trait defines the associated item given by1264    /// `assoc_ident`.1265    ///1266    /// This fails if there is no such bound in the list of candidates or if there are multiple1267    /// candidates in which case it reports ambiguity.1268    #[instrument(level = "debug", skip(self, all_candidates, qself, constraint), ret)]1269    fn probe_single_bound_for_assoc_item<I>(1270        &self,1271        all_candidates: impl Fn() -> I,1272        qself: AssocItemQSelf,1273        assoc_tag: ty::AssocTag,1274        assoc_ident: Ident,1275        span: Span,1276        constraint: Option<&hir::AssocItemConstraint<'tcx>>,1277    ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed>1278    where1279        I: Iterator<Item = ty::PolyTraitRef<'tcx>>,1280    {1281        let mut matching_candidates = all_candidates().filter(|r| {1282            self.probe_trait_that_defines_assoc_item(r.def_id(), assoc_tag, assoc_ident)1283        });12841285        let Some(bound1) = matching_candidates.next() else {1286            return Err(self.report_unresolved_assoc_item(1287                all_candidates,1288                qself,1289                assoc_tag,1290                assoc_ident,1291                span,1292                constraint,1293            ));1294        };12951296        if let Some(bound2) = matching_candidates.next() {1297            return Err(self.report_ambiguous_assoc_item(1298                bound1,1299                bound2,1300                matching_candidates,1301                qself,1302                assoc_tag,1303                assoc_ident,1304                span,1305                constraint,1306            ));1307        }13081309        Ok(bound1)1310    }13111312    /// Lower a [type-relative](hir::QPath::TypeRelative) path in type position to a type.1313    ///1314    /// If the path refers to an enum variant and `permit_variants` holds,1315    /// the returned type is simply the provided self type `qself_ty`.1316    ///1317    /// A path like `A::B::C::D` is understood as `<A::B::C>::D`. I.e.,1318    /// `qself_ty` / `qself` is `A::B::C` and `assoc_segment` is `D`.1319    /// We return the lowered type and the `DefId` for the whole path.1320    ///1321    /// We only support associated type paths whose self type is a type parameter or a `Self`1322    /// type alias (in a trait impl) like `T::Ty` (where `T` is a ty param) or `Self::Ty`.1323    /// We **don't** support paths whose self type is an arbitrary type like `Struct::Ty` where1324    /// struct `Struct` impls an in-scope trait that defines an associated type called `Ty`.1325    /// For the latter case, we report ambiguity.1326    /// While desirable to support, the implementation would be non-trivial. Tracked in [#22519].1327    ///1328    /// At the time of writing, *inherent associated types* are also resolved here. This however1329    /// is [problematic][iat]. A proper implementation would be as non-trivial as the one1330    /// described in the previous paragraph and their modeling of projections would likely be1331    /// very similar in nature.1332    ///1333    /// [#22519]: https://github.com/rust-lang/rust/issues/225191334    /// [iat]: https://github.com/rust-lang/rust/issues/8995#issuecomment-15692084031335    //1336    // NOTE: When this function starts resolving `Trait::AssocTy` successfully1337    // it should also start reporting the `BARE_TRAIT_OBJECTS` lint.1338    #[instrument(level = "debug", skip_all, ret)]1339    pub fn lower_type_relative_ty_path(1340        &self,1341        self_ty: Ty<'tcx>,1342        hir_self_ty: &'tcx hir::Ty<'tcx>,1343        segment: &'tcx hir::PathSegment<'tcx>,1344        qpath_hir_id: HirId,1345        span: Span,1346        permit_variants: PermitVariants,1347    ) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorGuaranteed> {1348        let tcx = self.tcx();1349        match self.lower_type_relative_path(1350            self_ty,1351            hir_self_ty,1352            segment,1353            qpath_hir_id,1354            span,1355            LowerTypeRelativePathMode::Type(permit_variants),1356        )? {1357            TypeRelativePath::AssocItem(alias_term) => {1358                let alias_ty = alias_term.expect_ty();1359                let def_id = alias_ty.kind.def_id();1360                let ty = alias_ty.to_ty(tcx);1361                let ty = self.check_param_uses_if_mcg(ty, span, false);1362                Ok((ty, tcx.def_kind(def_id), def_id))1363            }1364            TypeRelativePath::Variant { adt, variant_did } => {1365                let adt = self.check_param_uses_if_mcg(adt, span, false);1366                Ok((adt, DefKind::Variant, variant_did))1367            }1368            TypeRelativePath::Ctor { .. } => {1369                let e = tcx.dcx().span_err(span, "expected type, found tuple constructor");1370                Err(e)1371            }1372        }1373    }13741375    /// Lower a [type-relative][hir::QPath::TypeRelative] path to a (type-level) constant.1376    #[instrument(level = "debug", skip_all, ret)]1377    fn lower_type_relative_const_path(1378        &self,1379        self_ty: Ty<'tcx>,1380        hir_self_ty: &'tcx hir::Ty<'tcx>,1381        segment: &'tcx hir::PathSegment<'tcx>,1382        qpath_hir_id: HirId,1383        span: Span,1384    ) -> Result<Const<'tcx>, ErrorGuaranteed> {1385        let tcx = self.tcx();1386        match self.lower_type_relative_path(1387            self_ty,1388            hir_self_ty,1389            segment,1390            qpath_hir_id,1391            span,1392            LowerTypeRelativePathMode::Const,1393        )? {1394            TypeRelativePath::AssocItem(alias_term) => {1395                let alias_ct = alias_term.expect_ct();1396                if let Some(def_id) = alias_ct.kind.opt_def_id() {1397                    self.require_type_const_attribute(def_id, span)?;1398                }1399                let ct = Const::new_unevaluated(tcx, alias_ct);1400                let ct = self.check_param_uses_if_mcg(ct, span, false);1401                Ok(ct)1402            }1403            TypeRelativePath::Ctor { ctor_def_id, args } => match tcx.def_kind(ctor_def_id) {1404                DefKind::Ctor(_, CtorKind::Fn) => {1405                    Ok(ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, ctor_def_id, args)))1406                }1407                DefKind::Ctor(ctor_of, CtorKind::Const) => {1408                    Ok(self.construct_const_ctor_value(ctor_def_id, ctor_of, args))1409                }1410                _ => unreachable!(),1411            },1412            // FIXME(mgca): implement support for this once ready to support all adt ctor expressions,1413            // not just const ctors1414            TypeRelativePath::Variant { .. } => {1415                span_bug!(span, "unexpected variant res for type associated const path")1416            }1417        }1418    }14191420    /// Lower a [type-relative][hir::QPath::TypeRelative] (and type-level) path.1421    #[instrument(level = "debug", skip_all, ret)]1422    fn lower_type_relative_path(1423        &self,1424        self_ty: Ty<'tcx>,1425        hir_self_ty: &'tcx hir::Ty<'tcx>,1426        segment: &'tcx hir::PathSegment<'tcx>,1427        qpath_hir_id: HirId,1428        span: Span,1429        mode: LowerTypeRelativePathMode,1430    ) -> Result<TypeRelativePath<'tcx>, ErrorGuaranteed> {1431        debug!(%self_ty, ?segment.ident);1432        let tcx = self.tcx();14331434        // Check if we have an enum variant or an inherent associated type.1435        let mut variant_def_id = None;1436        if let Some(adt_def) = self.probe_adt(span, self_ty) {1437            if adt_def.is_enum() {1438                let variant_def = adt_def1439                    .variants()1440                    .iter()1441                    .find(|vd| tcx.hygienic_eq(segment.ident, vd.ident(tcx), adt_def.did()));1442                if let Some(variant_def) = variant_def {1443                    // FIXME(mgca): do we want constructor resolutions to take priority over1444                    // other possible resolutions?1445                    if matches!(mode, LowerTypeRelativePathMode::Const)1446                        && let Some((_, ctor_def_id)) = variant_def.ctor1447                    {1448                        tcx.check_stability(variant_def.def_id, Some(qpath_hir_id), span, None);1449                        let _ = self.prohibit_generic_args(1450                            slice::from_ref(segment).iter(),1451                            GenericsArgsErrExtend::EnumVariant {1452                                qself: hir_self_ty,1453                                assoc_segment: segment,1454                                adt_def,1455                            },1456                        );1457                        let ty::Adt(_, enum_args) = self_ty.kind() else { unreachable!() };1458                        return Ok(TypeRelativePath::Ctor { ctor_def_id, args: enum_args });1459                    }1460                    if let PermitVariants::Yes = mode.permit_variants() {1461                        tcx.check_stability(variant_def.def_id, Some(qpath_hir_id), span, None);1462                        let _ = self.prohibit_generic_args(1463                            slice::from_ref(segment).iter(),1464                            GenericsArgsErrExtend::EnumVariant {1465                                qself: hir_self_ty,1466                                assoc_segment: segment,1467                                adt_def,1468                            },1469                        );1470                        return Ok(TypeRelativePath::Variant {1471                            adt: self_ty,1472                            variant_did: variant_def.def_id,1473                        });1474                    } else {1475                        variant_def_id = Some(variant_def.def_id);1476                    }1477                }1478            }14791480            // FIXME(inherent_associated_types, #106719): Support self types other than ADTs.1481            if let Some(alias_term) = self.probe_inherent_assoc_item(1482                segment,1483                adt_def.did(),1484                self_ty,1485                qpath_hir_id,1486                span,1487                mode.assoc_tag(),1488            )? {1489                return Ok(TypeRelativePath::AssocItem(alias_term));1490            }1491        }14921493        let (item_def_id, bound) = self.resolve_type_relative_path(1494            self_ty,1495            hir_self_ty,1496            mode.assoc_tag(),1497            segment,1498            qpath_hir_id,1499            span,1500            variant_def_id,1501        )?;15021503        let (item_def_id, args) = self.lower_assoc_item_path(span, item_def_id, segment, bound)?;15041505        if let Some(variant_def_id) = variant_def_id {1506            tcx.emit_node_span_lint(1507                AMBIGUOUS_ASSOCIATED_ITEMS,1508                qpath_hir_id,1509                span,1510                errors::AmbiguityBetweenVariantAndAssocItem {1511                    variant_def_id,1512                    item_def_id,1513                    span,1514                    segment_ident: segment.ident,1515                    bound_def_id: bound.def_id(),1516                    self_ty,1517                    tcx,1518                    mode,1519                },1520            );1521        }15221523        Ok(TypeRelativePath::AssocItem(ty::AliasTerm::new_from_def_id(tcx, item_def_id, args)))1524    }15251526    /// Resolve a [type-relative](hir::QPath::TypeRelative) (and type-level) path.1527    fn resolve_type_relative_path(1528        &self,1529        self_ty: Ty<'tcx>,1530        hir_self_ty: &'tcx hir::Ty<'tcx>,1531        assoc_tag: ty::AssocTag,1532        segment: &'tcx hir::PathSegment<'tcx>,1533        qpath_hir_id: HirId,1534        span: Span,1535        variant_def_id: Option<DefId>,1536    ) -> Result<(DefId, ty::PolyTraitRef<'tcx>), ErrorGuaranteed> {1537        let tcx = self.tcx();15381539        let self_ty_res = match hir_self_ty.kind {1540            hir::TyKind::Path(hir::QPath::Resolved(_, path)) => path.res,1541            _ => Res::Err,1542        };15431544        // Find the type of the assoc item, and the trait where the associated item is declared.1545        let bound = match (self_ty.kind(), self_ty_res) {1546            (_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => {1547                // `Self` in an impl of a trait -- we have a concrete self type and a1548                // trait reference.1549                let trait_ref = tcx.impl_trait_ref(impl_def_id);15501551                self.probe_single_bound_for_assoc_item(1552                    || {1553                        let trait_ref =1554                            ty::Binder::dummy(trait_ref.instantiate_identity().skip_norm_wip());1555                        traits::supertraits(tcx, trait_ref)1556                    },1557                    AssocItemQSelf::SelfTyAlias,1558                    assoc_tag,1559                    segment.ident,1560                    span,1561                    None,1562                )?1563            }1564            (1565                &ty::Param(_),1566                Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),1567            ) => self.probe_single_ty_param_bound_for_assoc_item(1568                param_did.expect_local(),1569                hir_self_ty.span,1570                assoc_tag,1571                segment.ident,1572                span,1573            )?,1574            _ => {1575                return Err(self.report_unresolved_type_relative_path(1576                    self_ty,1577                    hir_self_ty,1578                    assoc_tag,1579                    segment.ident,1580                    qpath_hir_id,1581                    span,1582                    variant_def_id,1583                ));1584            }1585        };15861587        let assoc_item = self1588            .probe_assoc_item(segment.ident, assoc_tag, qpath_hir_id, span, bound.def_id())1589            .expect("failed to find associated item");15901591        Ok((assoc_item.def_id, bound))1592    }15931594    /// Search for inherent associated items for use at the type level.1595    fn probe_inherent_assoc_item(1596        &self,1597        segment: &hir::PathSegment<'tcx>,1598        adt_did: DefId,1599        self_ty: Ty<'tcx>,1600        block: HirId,1601        span: Span,1602        assoc_tag: ty::AssocTag,1603    ) -> Result<Option<ty::AliasTerm<'tcx>>, ErrorGuaranteed> {1604        let tcx = self.tcx();16051606        if !tcx.features().inherent_associated_types() {1607            match assoc_tag {1608                // Don't attempt to look up inherent associated types when the feature is not1609                // enabled. Theoretically it'd be fine to do so since we feature-gate their1610                // definition site. However, the current implementation of inherent associated1611                // items is somewhat brittle, so let's not run it by default.1612                ty::AssocTag::Type => return Ok(None),1613                ty::AssocTag::Const => {1614                    // We also gate the mgca codepath for type-level uses of inherent consts1615                    // with the inherent_associated_types feature gate since it relies on the1616                    // same machinery and has similar rough edges.1617                    return Err(feature_err(1618                        &tcx.sess,1619                        sym::inherent_associated_types,1620                        span,1621                        "inherent associated types are unstable",1622                    )1623                    .emit());1624                }1625                ty::AssocTag::Fn => unreachable!(),1626            }1627        }16281629        let name = segment.ident;1630        let candidates: Vec<_> = tcx1631            .inherent_impls(adt_did)1632            .iter()1633            .filter_map(|&impl_| {1634                let (item, scope) =1635                    self.probe_assoc_item_unchecked(name, assoc_tag, block, impl_)?;1636                Some(InherentAssocCandidate { impl_, assoc_item: item.def_id, scope })1637            })1638            .collect();16391640        // At the moment, we actually bail out with a hard error if the selection of an inherent1641        // associated item fails (see below). This means we never consider trait associated items1642        // as potential fallback candidates (#142006). To temporarily mask that issue, let's not1643        // select at all if there are no early inherent candidates.1644        if candidates.is_empty() {1645            return Ok(None);1646        }16471648        let (applicable_candidates, fulfillment_errors) =1649            self.select_inherent_assoc_candidates(span, self_ty, candidates.clone());16501651        // FIXME(#142006): Don't eagerly error here, there might be applicable trait candidates.1652        let InherentAssocCandidate { impl_, assoc_item, scope: def_scope } =1653            match &applicable_candidates[..] {1654                &[] => Err(self.report_unresolved_inherent_assoc_item(1655                    name,1656                    self_ty,1657                    candidates,1658                    fulfillment_errors,1659                    span,1660                    assoc_tag,1661                )),16621663                &[applicable_candidate] => Ok(applicable_candidate),16641665                &[_, ..] => Err(self.report_ambiguous_inherent_assoc_item(1666                    name,1667                    candidates.into_iter().map(|cand| cand.assoc_item).collect(),1668                    span,1669                )),1670            }?;16711672        // FIXME(#142006): Don't eagerly validate here, there might be trait candidates that are1673        // accessible (visible and stable) contrary to the inherent candidate.1674        self.check_assoc_item(assoc_item, name, def_scope, block, span);16751676        // FIXME(fmease): Currently creating throwaway `parent_args` to please1677        // `lower_generic_args_of_assoc_item`. Modify the latter instead (or sth. similar) to1678        // not require the parent args logic.1679        let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);1680        let args = self.lower_generic_args_of_assoc_item(span, assoc_item, segment, parent_args);1681        let args = tcx.mk_args_from_iter(1682            std::iter::once(ty::GenericArg::from(self_ty))1683                .chain(args.into_iter().skip(parent_args.len())),1684        );16851686        let kind = match assoc_tag {1687            ty::AssocTag::Type => ty::AliasTermKind::InherentTy { def_id: assoc_item },1688            ty::AssocTag::Const => {1689                // FIXME(mgca): drop once `InherentConst` accepts IAC-shaped args (issue #156181)1690                // without this, `new_from_args` errors (#155341).1691                self.require_type_const_attribute(assoc_item, span)?;1692                ty::AliasTermKind::InherentConst { def_id: assoc_item }1693            }1694            ty::AssocTag::Fn => unreachable!(),1695        };16961697        Ok(Some(ty::AliasTerm::new_from_args(tcx, kind, args)))1698    }16991700    /// Given name and kind search for the assoc item in the provided scope and check if it's accessible[^1].1701    ///1702    /// [^1]: I.e., accessible in the provided scope wrt. visibility and stability.1703    fn probe_assoc_item(1704        &self,1705        ident: Ident,1706        assoc_tag: ty::AssocTag,1707        block: HirId,1708        span: Span,1709        scope: DefId,1710    ) -> Option<ty::AssocItem> {1711        let (item, scope) = self.probe_assoc_item_unchecked(ident, assoc_tag, block, scope)?;1712        self.check_assoc_item(item.def_id, ident, scope, block, span);1713        Some(item)1714    }17151716    /// Given name and kind search for the assoc item in the provided scope1717    /// *without* checking if it's accessible[^1].1718    ///1719    /// [^1]: I.e., accessible in the provided scope wrt. visibility and stability.1720    fn probe_assoc_item_unchecked(1721        &self,1722        ident: Ident,1723        assoc_tag: ty::AssocTag,1724        block: HirId,1725        scope: DefId,1726    ) -> Option<(ty::AssocItem, /*scope*/ DefId)> {1727        let tcx = self.tcx();17281729        let (ident, def_scope) = tcx.adjust_ident_and_get_scope(ident, scope, block);1730        // We have already adjusted the item name above, so compare with `.normalize_to_macros_2_0()`1731        // instead of calling `filter_by_name_and_kind` which would needlessly normalize the1732        // `ident` again and again.1733        let item = tcx1734            .associated_items(scope)1735            .filter_by_name_unhygienic(ident.name)1736            .find(|i| i.tag() == assoc_tag && i.ident(tcx).normalize_to_macros_2_0() == ident)?;17371738        Some((*item, def_scope))1739    }17401741    /// Check if the given assoc item is accessible in the provided scope wrt. visibility and stability.1742    fn check_assoc_item(1743        &self,1744        item_def_id: DefId,1745        ident: Ident,1746        scope: DefId,1747        block: HirId,1748        span: Span,1749    ) {1750        let tcx = self.tcx();17511752        if !tcx.visibility(item_def_id).is_accessible_from(scope, tcx) {1753            self.dcx().emit_err(crate::diagnostics::AssocItemIsPrivate {1754                span,1755                kind: tcx.def_descr(item_def_id),1756                name: ident,1757                defined_here_label: tcx.def_span(item_def_id),1758            });1759        }17601761        tcx.check_stability(item_def_id, Some(block), span, None);1762    }17631764    fn probe_traits_that_match_assoc_ty(1765        &self,1766        qself_ty: Ty<'tcx>,1767        assoc_ident: Ident,1768    ) -> Vec<String> {1769        let tcx = self.tcx();17701771        // In contexts that have no inference context, just make a new one.1772        // We do need a local variable to store it, though.1773        let infcx_;1774        let infcx = if let Some(infcx) = self.infcx() {1775            infcx1776        } else {1777            assert!(!qself_ty.has_infer());1778            infcx_ = tcx.infer_ctxt().build(TypingMode::non_body_analysis());1779            &infcx_1780        };17811782        tcx.all_traits_including_private()1783            .filter(|trait_def_id| {1784                // Consider only traits with the associated type1785                tcx.associated_items(*trait_def_id)1786                        .in_definition_order()1787                        .any(|i| {1788                            i.is_type()1789                                && !i.is_impl_trait_in_trait()1790                                && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident1791                        })1792                    // Consider only accessible traits1793                    && tcx.visibility(*trait_def_id)1794                        .is_accessible_from(self.item_def_id(), tcx)1795                    && tcx.all_impls(*trait_def_id)1796                        .any(|impl_def_id| {1797                            let header = tcx.impl_trait_header(impl_def_id);1798                            let trait_ref = header.trait_ref.instantiate(tcx, infcx.fresh_args_for_item(DUMMY_SP, impl_def_id)).skip_norm_wip();17991800                            let value = fold_regions(tcx, qself_ty, |_, _| tcx.lifetimes.re_erased);1801                            // FIXME: Don't bother dealing with non-lifetime binders here...1802                            if value.has_escaping_bound_vars() {1803                                return false;1804                            }1805                            infcx1806                                .can_eq(1807                                    ty::ParamEnv::empty(),1808                                    trait_ref.self_ty(),1809                                    value,1810                                ) && header.polarity != ty::ImplPolarity::Negative1811                        })1812            })1813            .map(|trait_def_id| tcx.def_path_str(trait_def_id))1814            .collect()1815    }18161817    /// Lower a [resolved][hir::QPath::Resolved] associated type path to a projection.1818    #[instrument(level = "debug", skip_all)]1819    fn lower_resolved_assoc_ty_path(1820        &self,1821        span: Span,1822        opt_self_ty: Option<Ty<'tcx>>,1823        item_def_id: DefId,1824        trait_segment: Option<&hir::PathSegment<'tcx>>,1825        item_segment: &hir::PathSegment<'tcx>,1826    ) -> Ty<'tcx> {1827        match self.lower_resolved_assoc_item_path(1828            span,1829            opt_self_ty,1830            item_def_id,1831            trait_segment,1832            item_segment,1833            ty::AssocTag::Type,1834        ) {1835            Ok((item_def_id, item_args)) => {1836                Ty::new_projection_from_args(self.tcx(), item_def_id, item_args)1837            }1838            Err(guar) => Ty::new_error(self.tcx(), guar),1839        }1840    }18411842    /// Lower a [resolved][hir::QPath::Resolved] associated const path to a (type-level) constant.1843    #[instrument(level = "debug", skip_all)]1844    fn lower_resolved_assoc_const_path(1845        &self,1846        span: Span,1847        opt_self_ty: Option<Ty<'tcx>>,1848        item_def_id: DefId,1849        trait_segment: Option<&hir::PathSegment<'tcx>>,1850        item_segment: &hir::PathSegment<'tcx>,1851    ) -> Result<Const<'tcx>, ErrorGuaranteed> {1852        let tcx = self.tcx();1853        let (item_def_id, item_args) = self.lower_resolved_assoc_item_path(1854            span,1855            opt_self_ty,1856            item_def_id,1857            trait_segment,1858            item_segment,1859            ty::AssocTag::Const,1860        )?;1861        self.require_type_const_attribute(item_def_id, span)?;1862        let uv = ty::UnevaluatedConst::new(1863            tcx,1864            ty::UnevaluatedConstKind::new_from_def_id(tcx, item_def_id),1865            item_args,1866        );1867        Ok(Const::new_unevaluated(tcx, uv))1868    }18691870    /// Lower a [resolved][hir::QPath::Resolved] (type-level) associated item path.1871    #[instrument(level = "debug", skip_all)]1872    fn lower_resolved_assoc_item_path(1873        &self,1874        span: Span,1875        opt_self_ty: Option<Ty<'tcx>>,1876        item_def_id: DefId,1877        trait_segment: Option<&hir::PathSegment<'tcx>>,1878        item_segment: &hir::PathSegment<'tcx>,1879        assoc_tag: ty::AssocTag,1880    ) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed> {1881        let tcx = self.tcx();18821883        let trait_def_id = tcx.parent(item_def_id);1884        debug!(?trait_def_id);18851886        let Some(self_ty) = opt_self_ty else {1887            return Err(self.report_missing_self_ty_for_resolved_path(1888                trait_def_id,1889                span,1890                item_segment,1891                assoc_tag,1892            ));1893        };1894        debug!(?self_ty);18951896        let trait_ref =1897            self.lower_mono_trait_ref(span, trait_def_id, self_ty, trait_segment.unwrap(), false);1898        debug!(?trait_ref);18991900        let item_args =1901            self.lower_generic_args_of_assoc_item(span, item_def_id, item_segment, trait_ref.args);19021903        Ok((item_def_id, item_args))1904    }19051906    pub fn prohibit_generic_args<'a>(1907        &self,1908        segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,1909        err_extend: GenericsArgsErrExtend<'a>,1910    ) -> Result<(), ErrorGuaranteed> {1911        let args_visitors = segments.clone().flat_map(|segment| segment.args().args);1912        let mut result = Ok(());1913        if let Some(_) = args_visitors.clone().next() {1914            result = Err(self.report_prohibited_generic_args(1915                segments.clone(),1916                args_visitors,1917                err_extend,1918            ));1919        }19201921        for segment in segments {1922            // Only emit the first error to avoid overloading the user with error messages.1923            if let Some(c) = segment.args().constraints.first() {1924                return Err(prohibit_assoc_item_constraint(self, c, None));1925            }1926        }19271928        result1929    }19301931    /// Probe path segments that are semantically allowed to have generic arguments.1932    ///1933    /// ### Example1934    ///1935    /// ```ignore (illustrative)1936    ///    Option::None::<()>1937    /// //         ^^^^ permitted to have generic args1938    ///1939    /// // ==> [GenericPathSegment(Option_def_id, 1)]1940    ///1941    ///    Option::<()>::None1942    /// // ^^^^^^        ^^^^ *not* permitted to have generic args1943    /// // permitted to have generic args1944    ///1945    /// // ==> [GenericPathSegment(Option_def_id, 0)]1946    /// ```1947    // FIXME(eddyb, varkor) handle type paths here too, not just value ones.1948    pub fn probe_generic_path_segments(1949        &self,1950        segments: &[hir::PathSegment<'_>],1951        self_ty: Option<Ty<'tcx>>,1952        kind: DefKind,1953        def_id: DefId,1954        span: Span,1955    ) -> Vec<GenericPathSegment> {1956        // We need to extract the generic arguments supplied by the user in1957        // the path `path`. Due to the current setup, this is a bit of a1958        // tricky process; the problem is that resolve only tells us the1959        // end-point of the path resolution, and not the intermediate steps.1960        // Luckily, we can (at least for now) deduce the intermediate steps1961        // just from the end-point.1962        //1963        // There are basically five cases to consider:1964        //1965        // 1. Reference to a constructor of a struct:1966        //1967        //        struct Foo<T>(...)1968        //1969        //    In this case, the generic arguments are declared in the type space.1970        //1971        // 2. Reference to a constructor of an enum variant:1972        //1973        //        enum E<T> { Foo(...) }1974        //1975        //    In this case, the generic arguments are defined in the type space,1976        //    but may be specified either on the type or the variant.1977        //1978        // 3. Reference to a free function or constant:1979        //1980        //        fn foo<T>() {}1981        //1982        //    In this case, the path will again always have the form1983        //    `a::b::foo::<T>` where only the final segment should have generic1984        //    arguments. However, in this case, those arguments are declared on1985        //    a value, and hence are in the value space.1986        //1987        // 4. Reference to an associated function or constant:1988        //1989        //        impl<A> SomeStruct<A> {1990        //            fn foo<B>(...) {}1991        //        }1992        //1993        //    Here we can have a path like `a::b::SomeStruct::<A>::foo::<B>`,1994        //    in which case generic arguments may appear in two places. The1995        //    penultimate segment, `SomeStruct::<A>`, contains generic arguments1996        //    in the type space, and the final segment, `foo::<B>` contains1997        //    generic arguments in value space.1998        //1999        // The first step then is to categorize the segments appropriately.

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.