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 (¶m.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.