Skip to content

Commit 0664285

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

File tree

12 files changed

+138
-51
lines changed

12 files changed

+138
-51
lines changed

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
//! At present, however, we do run collection across all items in the
1515
//! crate as a kind of pass. This should eventually be factored away.
1616
17-
use std::cell::Cell;
17+
use std::cell::{Cell, RefCell};
1818
use std::iter;
1919
use std::ops::Bound;
2020

@@ -33,6 +33,10 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
3333
use rustc_infer::traits::ObligationCause;
3434
use rustc_middle::hir::nested_filter;
3535
use rustc_middle::query::Providers;
36+
use rustc_middle::ty::typeck_results::{
37+
HasTypeDependentDefs, LocalTableInContext, LocalTableInContextMut, TypeDependentDef,
38+
TypeDependentDefs,
39+
};
3640
use rustc_middle::ty::util::{Discr, IntTypeExt};
3741
use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, Upcast};
3842
use rustc_middle::{bug, span_bug};
@@ -122,6 +126,7 @@ pub fn provide(providers: &mut Providers) {
122126
pub struct ItemCtxt<'tcx> {
123127
tcx: TyCtxt<'tcx>,
124128
item_def_id: LocalDefId,
129+
type_dependent_defs: RefCell<TypeDependentDefs>,
125130
tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
126131
}
127132

@@ -355,7 +360,12 @@ fn bad_placeholder<'cx, 'tcx>(
355360

356361
impl<'tcx> ItemCtxt<'tcx> {
357362
pub fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
358-
ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) }
363+
ItemCtxt {
364+
tcx,
365+
item_def_id,
366+
type_dependent_defs: Default::default(),
367+
tainted_by_errors: Cell::new(None),
368+
}
359369
}
360370

361371
pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
@@ -521,6 +531,14 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
521531
// There's no place to record types from signatures?
522532
}
523533

534+
fn record_res(&self, hir_id: hir::HirId, result: TypeDependentDef) {
535+
LocalTableInContextMut::new(
536+
self.hir_id().owner,
537+
&mut self.type_dependent_defs.borrow_mut(),
538+
)
539+
.insert(hir_id, result);
540+
}
541+
524542
fn infcx(&self) -> Option<&InferCtxt<'tcx>> {
525543
None
526544
}
@@ -609,6 +627,15 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
609627
}
610628
}
611629

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

compiler/rustc_hir_analysis/src/collect/type_of.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,11 +224,12 @@ fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span
224224
..
225225
}) => {
226226
let body_owner = tcx.hir().enclosing_body_owner(arg_hir_id);
227-
let tables = tcx.typeck(body_owner);
227+
let typeck_results = tcx.typeck(body_owner);
228228
// This may fail in case the method/path does not actually exist.
229229
// As there is no relevant param for `def_id`, we simply return
230230
// `None` here.
231-
let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else {
231+
let Some(type_dependent_def) = typeck_results.type_dependent_def_id(parent_node_id)
232+
else {
232233
return Ty::new_error_with_message(
233234
tcx,
234235
span,

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ use rustc_infer::traits::ObligationCause;
3737
use rustc_middle::middle::stability::AllowUnstable;
3838
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
3939
use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
40+
use rustc_middle::ty::typeck_results::{HasTypeDependentDefs, TypeDependentDef};
4041
use rustc_middle::ty::{
4142
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
4243
TypeVisitableExt,
@@ -101,7 +102,7 @@ pub enum RegionInferReason<'a> {
101102
/// the [`rustc_middle::ty`] representation.
102103
///
103104
/// This trait used to be called `AstConv`.
104-
pub trait HirTyLowerer<'tcx> {
105+
pub trait HirTyLowerer<'tcx>: HasTypeDependentDefs {
105106
fn tcx(&self) -> TyCtxt<'tcx>;
106107

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

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

@@ -995,6 +998,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
995998
/// [type-relative]: hir::QPath::TypeRelative
996999
/// [#22519]: https://github.com/rust-lang/rust/issues/22519
9971000
/// [iat]: https://github.com/rust-lang/rust/issues/8995#issuecomment-1569208403
1001+
// FIXME(fmease): Update docs
9981002
//
9991003
// NOTE: When this function starts resolving `Trait::AssocTy` successfully
10001004
// it should also start reporting the `BARE_TRAIT_OBJECTS` lint.
@@ -1009,8 +1013,28 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10091013
permit_variants: bool,
10101014
) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorGuaranteed> {
10111015
debug!(%qself_ty, ?assoc_segment.ident);
1012-
let tcx = self.tcx();
1016+
let result = self.lower_assoc_path_inner(
1017+
hir_ref_id,
1018+
span,
1019+
qself_ty,
1020+
qself,
1021+
assoc_segment,
1022+
permit_variants,
1023+
);
1024+
self.record_res(hir_ref_id, result.map(|(_, def_kind, def_id)| (def_kind, def_id)));
1025+
result
1026+
}
10131027

1028+
fn lower_assoc_path_inner(
1029+
&self,
1030+
hir_ref_id: HirId,
1031+
span: Span,
1032+
qself_ty: Ty<'tcx>,
1033+
qself: &'tcx hir::Ty<'tcx>,
1034+
assoc_segment: &'tcx hir::PathSegment<'tcx>,
1035+
permit_variants: bool,
1036+
) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorGuaranteed> {
1037+
let tcx = self.tcx();
10141038
let assoc_ident = assoc_segment.ident;
10151039

10161040
// Check if we have an enum variant or an inherent associated type.
@@ -1036,22 +1060,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10361060
}
10371061

10381062
// FIXME(inherent_associated_types, #106719): Support self types other than ADTs.
1039-
if let Some((ty, did)) = self.probe_inherent_assoc_ty(
1063+
if let Some((ty, def_id)) = self.probe_inherent_assoc_ty(
10401064
assoc_ident,
10411065
assoc_segment,
10421066
adt_def.did(),
10431067
qself_ty,
10441068
hir_ref_id,
10451069
span,
10461070
)? {
1047-
return Ok((ty, DefKind::AssocTy, did));
1071+
return Ok((ty, DefKind::AssocTy, def_id));
10481072
}
10491073
}
10501074

1051-
let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
1052-
path.res
1053-
} else {
1054-
Res::Err
1075+
let qself_res = match &qself.kind {
1076+
hir::TyKind::Path(qpath) => self.qpath_res(qpath, qself.hir_id),
1077+
_ => Res::Err,
10551078
};
10561079

10571080
// Find the type of the associated item, and the trait where the associated
@@ -1089,14 +1112,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10891112
assoc_ident,
10901113
span,
10911114
)?,
1092-
// FIXME(fmease):
1093-
// Require the pre-lowered projectee (the HIR QSelf) to have `DefKind::AssocTy`. Rephrased,
1094-
// `T::Assoc::Assoc` typeck'ing shouldn't imply `Identity<T::Assoc>::Assoc` typeck'ing where
1095-
// `Identity` is an eager (i.e., non-lazy) type alias. We should do this
1096-
// * for consistency with lazy type aliases (`ty::Weak`)
1097-
// * for consistency with the fact that `T::Assoc` typeck'ing doesn't imply `Identity<T>::Assoc`
1098-
// typeck'ing
1099-
(ty::Alias(ty::Projection, alias_ty), _ /* Res::Def(DefKind::AssocTy, _) */) => {
1115+
(ty::Alias(ty::Projection, alias_ty), Res::Def(DefKind::AssocTy, _)) => {
11001116
// FIXME: Utilizing `item_bounds` for this is cycle-prone.
11011117
let predicates = tcx.item_bounds(alias_ty.def_id).instantiate(tcx, alias_ty.args);
11021118

compiler/rustc_hir_analysis/src/lib.rs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
181181
pub(crate) fn write_resolution(
182182
&self,
183183
hir_id: HirId,
184-
r: Result<(DefKind, DefId), ErrorGuaranteed>,
184+
result: Result<(DefKind, DefId), ErrorGuaranteed>,
185185
) {
186-
self.typeck_results.borrow_mut().type_dependent_defs_mut().insert(hir_id, r);
186+
self.typeck_results.borrow_mut().type_dependent_defs_mut().insert(hir_id, result);
187187
}
188188

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

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2051,12 +2051,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20512051
.map(|(ty, _, _)| ty)
20522052
.unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));
20532053
let ty = LoweredTy::from_raw(self, path_span, ty);
2054-
let result = result.map(|(_, kind, def_id)| (kind, def_id));
20552054

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

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ mod suggestions;
88
use std::cell::{Cell, RefCell};
99
use std::ops::Deref;
1010

11-
use hir::def_id::CRATE_DEF_ID;
1211
use rustc_errors::DiagCtxtHandle;
1312
use rustc_hir as hir;
14-
use rustc_hir::def_id::{DefId, LocalDefId};
13+
use rustc_hir::def::DefKind;
14+
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
1515
use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
1616
use rustc_infer::infer;
17+
use rustc_middle::ty::typeck_results::{HasTypeDependentDefs, TypeDependentDef};
1718
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
1819
use rustc_session::Session;
1920
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ pub mod pattern;
132132
pub mod print;
133133
pub mod relate;
134134
pub mod trait_def;
135+
pub mod typeck_results;
135136
pub mod util;
136137
pub mod visit;
137138
pub mod vtable;
@@ -159,7 +160,6 @@ mod rvalue_scopes;
159160
mod structural_impls;
160161
#[allow(hidden_glob_reexports)]
161162
mod sty;
162-
mod typeck_results;
163163

164164
// Data types
165165

compiler/rustc_middle/src/ty/typeck_results.rs

Lines changed: 40 additions & 17 deletions
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)