Skip to content

Commit d56708a

Browse files
committed
[PoC] Track type-dependent defs in ItemCtxts (minimally)
1 parent b02f424 commit d56708a

File tree

12 files changed

+139
-51
lines changed

12 files changed

+139
-51
lines changed

compiler/rustc_hir_analysis/src/collect.rs

+30-3
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,19 @@ use rustc_data_structures::unord::UnordMap;
2121
use rustc_errors::{
2222
struct_span_code_err, Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, StashKey, E0228,
2323
};
24+
use rustc_hir as hir;
2425
use rustc_hir::def::DefKind;
2526
use rustc_hir::def_id::{DefId, LocalDefId};
2627
use rustc_hir::intravisit::{self, walk_generics, Visitor};
27-
use rustc_hir::{self as hir};
2828
use rustc_hir::{GenericParamKind, Node};
2929
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
3030
use rustc_infer::traits::ObligationCause;
3131
use rustc_middle::hir::nested_filter;
3232
use rustc_middle::query::Providers;
33+
use rustc_middle::ty::typeck_results::{
34+
HasTypeDependentDefs, LocalTableInContext, LocalTableInContextMut, TypeDependentDef,
35+
TypeDependentDefs,
36+
};
3337
use rustc_middle::ty::util::{Discr, IntTypeExt};
3438
use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, Upcast};
3539
use rustc_middle::{bug, span_bug};
@@ -39,7 +43,7 @@ use rustc_target::spec::abi;
3943
use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
4044
use rustc_trait_selection::infer::InferCtxtExt;
4145
use rustc_trait_selection::traits::ObligationCtxt;
42-
use std::cell::Cell;
46+
use std::cell::{Cell, RefCell};
4347
use std::iter;
4448
use std::ops::Bound;
4549

@@ -120,6 +124,7 @@ pub fn provide(providers: &mut Providers) {
120124
pub struct ItemCtxt<'tcx> {
121125
tcx: TyCtxt<'tcx>,
122126
item_def_id: LocalDefId,
127+
type_dependent_defs: RefCell<TypeDependentDefs>,
123128
tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
124129
}
125130

@@ -353,7 +358,12 @@ fn bad_placeholder<'cx, 'tcx>(
353358

354359
impl<'tcx> ItemCtxt<'tcx> {
355360
pub fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
356-
ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) }
361+
ItemCtxt {
362+
tcx,
363+
item_def_id,
364+
type_dependent_defs: Default::default(),
365+
tainted_by_errors: Cell::new(None),
366+
}
357367
}
358368

359369
pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
@@ -519,6 +529,14 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
519529
// There's no place to record types from signatures?
520530
}
521531

532+
fn record_res(&self, hir_id: hir::HirId, result: TypeDependentDef) {
533+
LocalTableInContextMut::new(
534+
self.hir_id().owner,
535+
&mut self.type_dependent_defs.borrow_mut(),
536+
)
537+
.insert(hir_id, result);
538+
}
539+
522540
fn infcx(&self) -> Option<&InferCtxt<'tcx>> {
523541
None
524542
}
@@ -607,6 +625,15 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
607625
}
608626
}
609627

628+
impl HasTypeDependentDefs for ItemCtxt<'_> {
629+
fn type_dependent_def(&self, id: hir::HirId) -> Option<(DefKind, DefId)> {
630+
LocalTableInContext::new(self.hir_id().owner, &self.type_dependent_defs.borrow())
631+
.get(id)
632+
.copied()
633+
.and_then(|result| result.ok())
634+
}
635+
}
636+
610637
/// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.
611638
fn get_new_lifetime_name<'tcx>(
612639
tcx: TyCtxt<'tcx>,

compiler/rustc_hir_analysis/src/collect/type_of.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,12 @@ fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span
173173
..
174174
}) => {
175175
let body_owner = tcx.hir().enclosing_body_owner(arg_hir_id);
176-
let tables = tcx.typeck(body_owner);
176+
let typeck_results = tcx.typeck(body_owner);
177177
// This may fail in case the method/path does not actually exist.
178178
// As there is no relevant param for `def_id`, we simply return
179179
// `None` here.
180-
let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else {
180+
let Some(type_dependent_def) = typeck_results.type_dependent_def_id(parent_node_id)
181+
else {
181182
return Ty::new_error_with_message(
182183
tcx,
183184
span,

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+32-15
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ use rustc_infer::traits::ObligationCause;
4040
use rustc_middle::middle::stability::AllowUnstable;
4141
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
4242
use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
43+
use rustc_middle::ty::typeck_results::{HasTypeDependentDefs, TypeDependentDef};
4344
use rustc_middle::ty::{
4445
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
4546
TypeVisitableExt,
@@ -100,7 +101,7 @@ pub enum RegionInferReason<'a> {
100101
/// the [`rustc_middle::ty`] representation.
101102
///
102103
/// This trait used to be called `AstConv`.
103-
pub trait HirTyLowerer<'tcx> {
104+
pub trait HirTyLowerer<'tcx>: HasTypeDependentDefs {
104105
fn tcx(&self) -> TyCtxt<'tcx>;
105106

106107
fn dcx(&self) -> DiagCtxtHandle<'_>;
@@ -177,6 +178,8 @@ pub trait HirTyLowerer<'tcx> {
177178
/// Record the lowered type of a HIR node in this context.
178179
fn record_ty(&self, hir_id: HirId, ty: Ty<'tcx>, span: Span);
179180

181+
fn record_res(&self, hir_id: hir::HirId, result: TypeDependentDef);
182+
180183
/// The inference context of the lowering context if applicable.
181184
fn infcx(&self) -> Option<&InferCtxt<'tcx>>;
182185

@@ -979,6 +982,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
979982
/// [type-relative]: hir::QPath::TypeRelative
980983
/// [#22519]: https://github.com/rust-lang/rust/issues/22519
981984
/// [iat]: https://github.com/rust-lang/rust/issues/8995#issuecomment-1569208403
985+
// FIXME(fmease): Update docs
982986
//
983987
// NOTE: When this function starts resolving `Trait::AssocTy` successfully
984988
// it should also start reporting the `BARE_TRAIT_OBJECTS` lint.
@@ -993,13 +997,33 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
993997
permit_variants: bool,
994998
) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorGuaranteed> {
995999
debug!(%qself_ty, ?assoc_segment.ident);
1000+
let result = self.lower_assoc_path_inner(
1001+
hir_ref_id,
1002+
span,
1003+
qself_ty,
1004+
qself,
1005+
assoc_segment,
1006+
permit_variants,
1007+
);
1008+
self.record_res(hir_ref_id, result.map(|(_, def_kind, def_id)| (def_kind, def_id)));
1009+
result
1010+
}
1011+
1012+
fn lower_assoc_path_inner(
1013+
&self,
1014+
hir_ref_id: HirId,
1015+
span: Span,
1016+
qself_ty: Ty<'tcx>,
1017+
qself: &'tcx hir::Ty<'tcx>,
1018+
assoc_segment: &'tcx hir::PathSegment<'tcx>,
1019+
permit_variants: bool,
1020+
) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorGuaranteed> {
9961021
let tcx = self.tcx();
9971022

9981023
let assoc_ident = assoc_segment.ident;
999-
let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
1000-
path.res
1001-
} else {
1002-
Res::Err
1024+
let qself_res = match &qself.kind {
1025+
hir::TyKind::Path(qpath) => self.qpath_res(qpath, qself.hir_id),
1026+
_ => Res::Err,
10031027
};
10041028

10051029
// Check if we have an enum variant or an inherent associated type.
@@ -1025,15 +1049,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10251049
}
10261050

10271051
// FIXME(inherent_associated_types, #106719): Support self types other than ADTs.
1028-
if let Some((ty, did)) = self.probe_inherent_assoc_ty(
1052+
if let Some((ty, def_id)) = self.probe_inherent_assoc_ty(
10291053
assoc_ident,
10301054
assoc_segment,
10311055
adt_def.did(),
10321056
qself_ty,
10331057
hir_ref_id,
10341058
span,
10351059
)? {
1036-
return Ok((ty, DefKind::AssocTy, did));
1060+
return Ok((ty, DefKind::AssocTy, def_id));
10371061
}
10381062
}
10391063

@@ -1072,14 +1096,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10721096
assoc_ident,
10731097
span,
10741098
)?,
1075-
// FIXME(fmease):
1076-
// Require the pre-lowered projectee (the HIR QSelf) to have `DefKind::AssocTy`. Rephrased,
1077-
// `T::Assoc::Assoc` typeck'ing shouldn't imply `Identity<T::Assoc>::Assoc` typeck'ing where
1078-
// `Identity` is an eager (i.e., non-lazy) type alias. We should do this
1079-
// * for consistency with lazy type aliases (`ty::Weak`)
1080-
// * for consistency with the fact that `T::Assoc` typeck'ing doesn't imply `Identity<T>::Assoc`
1081-
// typeck'ing
1082-
(ty::Alias(ty::Projection, alias_ty), _ /* Res::Def(DefKind::AssocTy, _) */) => {
1099+
(ty::Alias(ty::Projection, alias_ty), Res::Def(DefKind::AssocTy, _)) => {
10831100
// FIXME: Utilizing `item_bounds` for this is cycle-prone.
10841101
let predicates = tcx.item_bounds(alias_ty.def_id).instantiate(tcx, alias_ty.args);
10851102

compiler/rustc_hir_analysis/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ This API is completely unstable and subject to change.
7070
#![feature(never_type)]
7171
#![feature(rustdoc_internals)]
7272
#![feature(slice_partition_dedup)]
73+
#![feature(trait_upcasting)]
7374
#![feature(try_blocks)]
7475
#![feature(unwrap_infallible)]
7576
// tidy-alphabetical-end

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
170170
pub(crate) fn write_resolution(
171171
&self,
172172
hir_id: HirId,
173-
r: Result<(DefKind, DefId), ErrorGuaranteed>,
173+
result: Result<(DefKind, DefId), ErrorGuaranteed>,
174174
) {
175-
self.typeck_results.borrow_mut().type_dependent_defs_mut().insert(hir_id, r);
175+
self.typeck_results.borrow_mut().type_dependent_defs_mut().insert(hir_id, result);
176176
}
177177

178178
#[instrument(level = "debug", skip(self))]

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -2049,12 +2049,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20492049
.map(|(ty, _, _)| ty)
20502050
.unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));
20512051
let ty = LoweredTy::from_raw(self, path_span, ty);
2052-
let result = result.map(|(_, kind, def_id)| (kind, def_id));
20532052

2054-
// Write back the new resolution.
2055-
self.write_resolution(hir_id, result);
2056-
2057-
(result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
2053+
(result.map_or(Res::Err, |(_, kind, def_id)| Res::Def(kind, def_id)), ty)
20582054
}
20592055
QPath::LangItem(lang_item, span) => {
20602056
let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id);

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ use crate::coercion::DynamicCoerceMany;
1111
use crate::fallback::DivergingFallbackBehavior;
1212
use crate::fn_ctxt::checks::DivergingBlockBehavior;
1313
use crate::{CoroutineTypes, Diverges, EnclosingBreakables, TypeckRootCtxt};
14-
use hir::def_id::CRATE_DEF_ID;
1514
use rustc_hir as hir;
16-
use rustc_hir::def_id::{DefId, LocalDefId};
15+
use rustc_hir::def::DefKind;
16+
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
1717
use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
1818
use rustc_infer::error_reporting::infer::sub_relations::SubRelations;
1919
use rustc_infer::error_reporting::infer::TypeErrCtxt;
2020
use rustc_infer::infer;
21+
use rustc_middle::ty::typeck_results::{HasTypeDependentDefs, TypeDependentDef};
2122
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
2223
use rustc_session::Session;
2324
use rustc_span::symbol::Ident;
@@ -338,6 +339,10 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
338339
self.write_ty(hir_id, ty)
339340
}
340341

342+
fn record_res(&self, hir_id: hir::HirId, result: TypeDependentDef) {
343+
self.write_resolution(hir_id, result);
344+
}
345+
341346
fn infcx(&self) -> Option<&infer::InferCtxt<'tcx>> {
342347
Some(&self.infcx)
343348
}
@@ -359,6 +364,12 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
359364
}
360365
}
361366

367+
impl HasTypeDependentDefs for FnCtxt<'_, '_> {
368+
fn type_dependent_def(&self, id: hir::HirId) -> Option<(DefKind, DefId)> {
369+
self.typeck_results.borrow().type_dependent_def(id)
370+
}
371+
}
372+
362373
/// The `ty` representation of a user-provided type. Depending on the use-site
363374
/// we want to either use the unnormalized or the normalized form of this type.
364375
///

compiler/rustc_middle/src/ty/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ pub mod pattern;
137137
pub mod print;
138138
pub mod relate;
139139
pub mod trait_def;
140+
pub mod typeck_results;
140141
pub mod util;
141142
pub mod visit;
142143
pub mod vtable;
@@ -164,7 +165,6 @@ mod rvalue_scopes;
164165
mod structural_impls;
165166
#[allow(hidden_glob_reexports)]
166167
mod sty;
167-
mod typeck_results;
168168

169169
// Data types
170170

compiler/rustc_middle/src/ty/typeck_results.rs

+40-17
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ pub struct TypeckResults<'tcx> {
3232
/// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
3333
pub hir_owner: OwnerId,
3434

35-
/// Resolved definitions for `<T>::X` associated paths and
36-
/// method calls, including those of overloaded operators.
37-
type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
35+
type_dependent_defs: TypeDependentDefs,
3836

3937
/// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
4038
/// or patterns (`S { field }`). The index is often useful by itself, but to learn more
@@ -254,32 +252,22 @@ impl<'tcx> TypeckResults<'tcx> {
254252

255253
/// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
256254
pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: HirId) -> Res {
257-
match *qpath {
258-
hir::QPath::Resolved(_, path) => path.res,
259-
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
260-
.type_dependent_def(id)
261-
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
262-
}
255+
HasTypeDependentDefs::qpath_res(self, qpath, id)
263256
}
264257

265-
pub fn type_dependent_defs(
266-
&self,
267-
) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
258+
pub fn type_dependent_defs(&self) -> LocalTableInContext<'_, TypeDependentDef> {
268259
LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
269260
}
270261

271262
pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
272-
validate_hir_id_for_typeck_results(self.hir_owner, id);
273-
self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
263+
self.type_dependent_defs().get(id).copied().and_then(|result| result.ok())
274264
}
275265

276266
pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
277267
self.type_dependent_def(id).map(|(_, def_id)| def_id)
278268
}
279269

280-
pub fn type_dependent_defs_mut(
281-
&mut self,
282-
) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
270+
pub fn type_dependent_defs_mut(&mut self) -> LocalTableInContextMut<'_, TypeDependentDef> {
283271
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
284272
}
285273

@@ -549,6 +537,33 @@ impl<'tcx> TypeckResults<'tcx> {
549537
}
550538
}
551539

540+
/// Resolved definitions for `<T>::X` associated paths and
541+
/// method calls, including those of overloaded operators.
542+
pub type TypeDependentDefs = ItemLocalMap<TypeDependentDef>;
543+
544+
pub type TypeDependentDef = Result<(DefKind, DefId), ErrorGuaranteed>;
545+
546+
// FIXME(fmease): Yuck!
547+
pub trait HasTypeDependentDefs {
548+
fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)>;
549+
550+
/// Returns the final resolution of a `QPath`.
551+
fn qpath_res(&self, qpath: &hir::QPath<'_>, id: HirId) -> Res {
552+
match qpath {
553+
hir::QPath::Resolved(_, path) => path.res,
554+
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
555+
.type_dependent_def(id)
556+
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
557+
}
558+
}
559+
}
560+
561+
impl HasTypeDependentDefs for TypeckResults<'_> {
562+
fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
563+
self.type_dependent_def(id)
564+
}
565+
}
566+
552567
/// Validate that the given HirId (respectively its `local_id` part) can be
553568
/// safely used as a key in the maps of a TypeckResults. For that to be
554569
/// the case, the HirId must have the same `owner` as all the other IDs in
@@ -581,6 +596,10 @@ pub struct LocalTableInContext<'a, V> {
581596
}
582597

583598
impl<'a, V> LocalTableInContext<'a, V> {
599+
pub fn new(hir_owner: OwnerId, data: &'a ItemLocalMap<V>) -> Self {
600+
Self { hir_owner, data }
601+
}
602+
584603
pub fn contains_key(&self, id: HirId) -> bool {
585604
validate_hir_id_for_typeck_results(self.hir_owner, id);
586605
self.data.contains_key(&id.local_id)
@@ -619,6 +638,10 @@ pub struct LocalTableInContextMut<'a, V> {
619638
}
620639

621640
impl<'a, V> LocalTableInContextMut<'a, V> {
641+
pub fn new(hir_owner: OwnerId, data: &'a mut ItemLocalMap<V>) -> Self {
642+
Self { hir_owner, data }
643+
}
644+
622645
pub fn get_mut(&mut self, id: HirId) -> Option<&mut V> {
623646
validate_hir_id_for_typeck_results(self.hir_owner, id);
624647
self.data.get_mut(&id.local_id)

0 commit comments

Comments
 (0)