-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement consecutive shorthand projections (associated type paths) like T::AssocA::AssocB
#126651
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,6 +39,7 @@ use rustc_middle::middle::stability::AllowUnstable; | |
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; | ||
use rustc_middle::ty::fold::fold_regions; | ||
use rustc_middle::ty::print::PrintPolyTraitRefExt as _; | ||
use rustc_middle::ty::typeck_results::{HasTypeDependentDefs, TypeDependentDef}; | ||
use rustc_middle::ty::{ | ||
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt, | ||
TypeVisitableExt, TypingMode, | ||
|
@@ -107,7 +108,7 @@ pub enum RegionInferReason<'a> { | |
/// the [`rustc_middle::ty`] representation. | ||
/// | ||
/// This trait used to be called `AstConv`. | ||
pub trait HirTyLowerer<'tcx> { | ||
pub trait HirTyLowerer<'tcx>: HasTypeDependentDefs { | ||
fn tcx(&self) -> TyCtxt<'tcx>; | ||
|
||
fn dcx(&self) -> DiagCtxtHandle<'_>; | ||
|
@@ -184,6 +185,8 @@ pub trait HirTyLowerer<'tcx> { | |
/// Record the lowered type of a HIR node in this context. | ||
fn record_ty(&self, hir_id: HirId, ty: Ty<'tcx>, span: Span); | ||
|
||
fn record_res(&self, hir_id: hir::HirId, result: TypeDependentDef); | ||
|
||
/// The inference context of the lowering context if applicable. | ||
fn infcx(&self) -> Option<&InferCtxt<'tcx>>; | ||
|
||
|
@@ -202,18 +205,20 @@ pub trait HirTyLowerer<'tcx> { | |
/// The "qualified self" of an associated item path. | ||
/// | ||
/// For diagnostic purposes only. | ||
enum AssocItemQSelf { | ||
enum AssocItemQSelf<'tcx> { | ||
Trait(DefId), | ||
TyParam(LocalDefId, Span), | ||
SelfTyAlias, | ||
AssocTy(Ty<'tcx>), | ||
} | ||
|
||
impl AssocItemQSelf { | ||
fn to_string(&self, tcx: TyCtxt<'_>) -> String { | ||
impl<'tcx> AssocItemQSelf<'tcx> { | ||
fn to_string(&self, tcx: TyCtxt<'tcx>) -> String { | ||
match *self { | ||
Self::Trait(def_id) => tcx.def_path_str(def_id), | ||
Self::TyParam(def_id, _) => tcx.hir().ty_param_name(def_id).to_string(), | ||
Self::SelfTyAlias => kw::SelfUpper.to_string(), | ||
Self::AssocTy(ty) => ty.to_string(), | ||
} | ||
} | ||
} | ||
|
@@ -925,7 +930,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | |
fn probe_single_bound_for_assoc_item<I>( | ||
&self, | ||
all_candidates: impl Fn() -> I, | ||
qself: AssocItemQSelf, | ||
qself: AssocItemQSelf<'tcx>, | ||
assoc_kind: ty::AssocKind, | ||
assoc_name: Ident, | ||
span: Span, | ||
|
@@ -1062,6 +1067,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | |
/// [type-relative]: hir::QPath::TypeRelative | ||
/// [#22519]: https://github.com/rust-lang/rust/issues/22519 | ||
/// [iat]: https://github.com/rust-lang/rust/issues/8995#issuecomment-1569208403 | ||
// FIXME(fmease): Update docs | ||
// | ||
// NOTE: When this function starts resolving `Trait::AssocTy` successfully | ||
// it should also start reporting the `BARE_TRAIT_OBJECTS` lint. | ||
|
@@ -1076,8 +1082,28 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | |
permit_variants: bool, | ||
) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorGuaranteed> { | ||
debug!(%qself_ty, ?assoc_segment.ident); | ||
let tcx = self.tcx(); | ||
let result = self.lower_assoc_path_inner( | ||
hir_ref_id, | ||
span, | ||
qself_ty, | ||
qself, | ||
assoc_segment, | ||
permit_variants, | ||
); | ||
self.record_res(hir_ref_id, result.map(|(_, def_kind, def_id)| (def_kind, def_id))); | ||
result | ||
} | ||
|
||
fn lower_assoc_path_inner( | ||
&self, | ||
hir_ref_id: HirId, | ||
span: Span, | ||
qself_ty: Ty<'tcx>, | ||
qself: &'tcx hir::Ty<'tcx>, | ||
assoc_segment: &'tcx hir::PathSegment<'tcx>, | ||
permit_variants: bool, | ||
) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorGuaranteed> { | ||
let tcx = self.tcx(); | ||
let assoc_ident = assoc_segment.ident; | ||
|
||
// Check if we have an enum variant or an inherent associated type. | ||
|
@@ -1103,22 +1129,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | |
} | ||
|
||
// FIXME(inherent_associated_types, #106719): Support self types other than ADTs. | ||
if let Some((ty, did)) = self.probe_inherent_assoc_ty( | ||
if let Some((ty, def_id)) = self.probe_inherent_assoc_ty( | ||
assoc_ident, | ||
assoc_segment, | ||
adt_def.did(), | ||
qself_ty, | ||
hir_ref_id, | ||
span, | ||
)? { | ||
return Ok((ty, DefKind::AssocTy, did)); | ||
return Ok((ty, DefKind::AssocTy, def_id)); | ||
} | ||
} | ||
|
||
let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind { | ||
path.res | ||
} else { | ||
Res::Err | ||
let qself_res = match &qself.kind { | ||
hir::TyKind::Path(qpath) => self.qpath_res(qpath, qself.hir_id), | ||
_ => Res::Err, | ||
}; | ||
|
||
// Find the type of the associated item, and the trait where the associated | ||
|
@@ -1147,15 +1172,38 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | |
)? | ||
} | ||
( | ||
&ty::Param(_), | ||
Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did), | ||
ty::Param(_), | ||
Res::SelfTyParam { trait_: param_def_id } | ||
| Res::Def(DefKind::TyParam, param_def_id), | ||
) => self.probe_single_ty_param_bound_for_assoc_item( | ||
param_did.expect_local(), | ||
param_def_id.expect_local(), | ||
qself.span, | ||
ty::AssocKind::Type, | ||
assoc_ident, | ||
span, | ||
)?, | ||
(ty::Alias(ty::Projection, alias_ty), Res::Def(DefKind::AssocTy, _)) => { | ||
// FIXME: Utilizing `item_bounds` for this is cycle-prone. | ||
let predicates = tcx.item_bounds(alias_ty.def_id).instantiate(tcx, alias_ty.args); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does this cycle for trait Foo {
type FooAssoc;
}
trait Bar<T> {}
trait Trait {
type Assoc: Foo + Bar<Self::Assoc::FooAssoc>;
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, it does. I guess there's no way around introducing a specialized variant of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that may work 🤔 an easier alternative may be to forbid the consecutive shorthand in item bounds and super traits. It's not great, but it does avoid the issue |
||
|
||
self.probe_single_bound_for_assoc_item( | ||
|| { | ||
let trait_refs = predicates.iter().filter_map(|pred| { | ||
pred.as_trait_clause().map(|t| t.map_bound(|t| t.trait_ref)) | ||
}); | ||
traits::transitive_bounds_that_define_assoc_item( | ||
tcx, | ||
trait_refs, | ||
assoc_ident, | ||
) | ||
}, | ||
AssocItemQSelf::AssocTy(qself_ty), | ||
ty::AssocKind::Type, | ||
assoc_ident, | ||
span, | ||
None, | ||
)? | ||
} | ||
_ => { | ||
let reported = if variant_resolution.is_some() { | ||
// Variant in type position | ||
|
@@ -1303,6 +1351,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | |
); | ||
}); | ||
} | ||
|
||
Ok((ty, DefKind::AssocTy, assoc_ty.def_id)) | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unrelated: are there ever cases where we have a
ty::Param
with a different res? and if so, do we want to support them? we can go from the index of the param to its def_id after allThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Self params dont resolve to DefKind::TyParam, they resolve to the trait defid and DefKind::Trait iirc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually wait im blind thats SelfTyParam already