Skip to content

Commit 3e96f15

Browse files
committed
[PoC] Track type-dependent defs in ItemCtxts (minimally)
1 parent 415905a commit 3e96f15

File tree

11 files changed

+136
-50
lines changed

11 files changed

+136
-50
lines changed

Diff for: compiler/rustc_hir_analysis/src/collect.rs

+29-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
//! crate as a kind of pass. This should eventually be factored away.
1616
1717
use std::assert_matches::assert_matches;
18-
use std::cell::Cell;
18+
use std::cell::{Cell, RefCell};
1919
use std::iter;
2020
use std::ops::Bound;
2121

@@ -34,6 +34,10 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
3434
use rustc_infer::traits::ObligationCause;
3535
use rustc_middle::hir::nested_filter;
3636
use rustc_middle::query::Providers;
37+
use rustc_middle::ty::typeck_results::{
38+
HasTypeDependentDefs, LocalTableInContext, LocalTableInContextMut, TypeDependentDef,
39+
TypeDependentDefs,
40+
};
3741
use rustc_middle::ty::util::{Discr, IntTypeExt};
3842
use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMode, fold_regions};
3943
use rustc_middle::{bug, span_bug};
@@ -125,6 +129,7 @@ pub(crate) fn provide(providers: &mut Providers) {
125129
pub(crate) struct ItemCtxt<'tcx> {
126130
tcx: TyCtxt<'tcx>,
127131
item_def_id: LocalDefId,
132+
type_dependent_defs: RefCell<TypeDependentDefs>,
128133
tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
129134
}
130135

@@ -365,7 +370,12 @@ fn bad_placeholder<'cx, 'tcx>(
365370

366371
impl<'tcx> ItemCtxt<'tcx> {
367372
pub(crate) fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
368-
ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) }
373+
ItemCtxt {
374+
tcx,
375+
item_def_id,
376+
type_dependent_defs: Default::default(),
377+
tainted_by_errors: Cell::new(None),
378+
}
369379
}
370380

371381
pub(crate) fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
@@ -539,6 +549,14 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
539549
// There's no place to record types from signatures?
540550
}
541551

552+
fn record_res(&self, hir_id: hir::HirId, result: TypeDependentDef) {
553+
LocalTableInContextMut::new(
554+
self.hir_id().owner,
555+
&mut self.type_dependent_defs.borrow_mut(),
556+
)
557+
.insert(hir_id, result);
558+
}
559+
542560
fn infcx(&self) -> Option<&InferCtxt<'tcx>> {
543561
None
544562
}
@@ -628,6 +646,15 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
628646
}
629647
}
630648

649+
impl HasTypeDependentDefs for ItemCtxt<'_> {
650+
fn type_dependent_def(&self, id: hir::HirId) -> Option<(DefKind, DefId)> {
651+
LocalTableInContext::new(self.hir_id().owner, &self.type_dependent_defs.borrow())
652+
.get(id)
653+
.copied()
654+
.and_then(|result| result.ok())
655+
}
656+
}
657+
631658
/// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.
632659
fn get_new_lifetime_name<'tcx>(
633660
tcx: TyCtxt<'tcx>,

Diff for: compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+31-14
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::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, AssocTag, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty,
4243
TyCtxt, TypeVisitableExt, TypingMode, Upcast, fold_regions,
@@ -105,7 +106,7 @@ pub enum RegionInferReason<'a> {
105106
/// the [`rustc_middle::ty`] representation.
106107
///
107108
/// This trait used to be called `AstConv`.
108-
pub trait HirTyLowerer<'tcx> {
109+
pub trait HirTyLowerer<'tcx>: HasTypeDependentDefs {
109110
fn tcx(&self) -> TyCtxt<'tcx>;
110111

111112
fn dcx(&self) -> DiagCtxtHandle<'_>;
@@ -190,6 +191,9 @@ pub trait HirTyLowerer<'tcx> {
190191
/// Record the lowered type of a HIR node in this context.
191192
fn record_ty(&self, hir_id: HirId, ty: Ty<'tcx>, span: Span);
192193

194+
/// Record the resolution of a HIR node corresponding to a type-dependent definition in this context.
195+
fn record_res(&self, hir_id: hir::HirId, result: TypeDependentDef);
196+
193197
/// The inference context of the lowering context if applicable.
194198
fn infcx(&self) -> Option<&InferCtxt<'tcx>>;
195199

@@ -1153,6 +1157,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11531157
/// [type-relative]: hir::QPath::TypeRelative
11541158
/// [#22519]: https://github.com/rust-lang/rust/issues/22519
11551159
/// [iat]: https://github.com/rust-lang/rust/issues/8995#issuecomment-1569208403
1160+
// FIXME(fmease): Update docs
11561161
//
11571162
// NOTE: When this function starts resolving `Trait::AssocTy` successfully
11581163
// it should also start reporting the `BARE_TRAIT_OBJECTS` lint.
@@ -1233,8 +1238,28 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
12331238
mode: LowerAssocMode,
12341239
) -> Result<LoweredAssoc<'tcx>, ErrorGuaranteed> {
12351240
debug!(%qself_ty, ?assoc_segment.ident);
1236-
let tcx = self.tcx();
1241+
let result =
1242+
self.lower_assoc_path_inner(hir_ref_id, span, qself_ty, qself, assoc_segment, mode);
1243+
self.record_res(
1244+
hir_ref_id,
1245+
result.map(|assoc| match assoc {
1246+
LoweredAssoc::Term(def_id, _) => (self.tcx().def_kind(def_id), def_id),
1247+
LoweredAssoc::Variant { .. } => todo!(), // FIXME: Properly handle
1248+
}),
1249+
);
1250+
result
1251+
}
12371252

1253+
fn lower_assoc_path_inner(
1254+
&self,
1255+
hir_ref_id: HirId,
1256+
span: Span,
1257+
qself_ty: Ty<'tcx>,
1258+
qself: &'tcx hir::Ty<'tcx>,
1259+
assoc_segment: &'tcx hir::PathSegment<'tcx>,
1260+
mode: LowerAssocMode,
1261+
) -> Result<LoweredAssoc<'tcx>, ErrorGuaranteed> {
1262+
let tcx = self.tcx();
12381263
let assoc_ident = assoc_segment.ident;
12391264

12401265
// Check if we have an enum variant or an inherent associated type.
@@ -1275,10 +1300,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
12751300
}
12761301
}
12771302

1278-
let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
1279-
path.res
1280-
} else {
1281-
Res::Err
1303+
let qself_res = match &qself.kind {
1304+
hir::TyKind::Path(qpath) => self.qpath_res(qpath, qself.hir_id),
1305+
_ => Res::Err,
12821306
};
12831307

12841308
// Find the type of the associated item, and the trait where the associated
@@ -1317,14 +1341,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13171341
assoc_ident,
13181342
span,
13191343
)?,
1320-
// FIXME(fmease):
1321-
// Require the pre-lowered projectee (the HIR QSelf) to have `DefKind::AssocTy`. Rephrased,
1322-
// `T::Assoc::Assoc` typeck'ing shouldn't imply `Identity<T::Assoc>::Assoc` typeck'ing where
1323-
// `Identity` is an eager (i.e., non-lazy) type alias. We should do this
1324-
// * for consistency with lazy type aliases (`ty::Weak`)
1325-
// * for consistency with the fact that `T::Assoc` typeck'ing doesn't imply `Identity<T>::Assoc`
1326-
// typeck'ing
1327-
(ty::Alias(ty::Projection, alias_ty), _ /* Res::Def(DefKind::AssocTy, _) */) => {
1344+
(ty::Alias(ty::Projection, alias_ty), Res::Def(DefKind::AssocTy, _)) => {
13281345
// FIXME: Utilizing `item_bounds` for this is cycle-prone.
13291346
let predicates = tcx.item_bounds(alias_ty.def_id).instantiate(tcx, alias_ty.args);
13301347

Diff for: compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
176176
pub(crate) fn write_resolution(
177177
&self,
178178
hir_id: HirId,
179-
r: Result<(DefKind, DefId), ErrorGuaranteed>,
179+
result: Result<(DefKind, DefId), ErrorGuaranteed>,
180180
) {
181-
self.typeck_results.borrow_mut().type_dependent_defs_mut().insert(hir_id, r);
181+
self.typeck_results.borrow_mut().type_dependent_defs_mut().insert(hir_id, result);
182182
}
183183

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

Diff for: compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -2178,12 +2178,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21782178
.map(|(ty, _, _)| ty)
21792179
.unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));
21802180
let ty = LoweredTy::from_raw(self, path_span, ty);
2181-
let result = result.map(|(_, kind, def_id)| (kind, def_id));
21822181

2183-
// Write back the new resolution.
2184-
self.write_resolution(hir_id, result);
2185-
2186-
(result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
2182+
(result.map_or(Res::Err, |(_, kind, def_id)| Res::Def(kind, def_id)), ty)
21872183
}
21882184
QPath::LangItem(lang_item, span) => {
21892185
let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id);

Diff for: compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

+15-4
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ 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;
13-
use rustc_hir::def_id::{DefId, LocalDefId};
12+
use rustc_hir::def::DefKind;
13+
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
1414
use rustc_hir::{self as hir, HirId, ItemLocalMap};
1515
use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
1616
use rustc_infer::infer;
1717
use rustc_infer::traits::Obligation;
18+
use rustc_middle::ty::typeck_results::{HasTypeDependentDefs, TypeDependentDef};
1819
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
1920
use rustc_session::Session;
2021
use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span, sym};
@@ -350,7 +351,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
350351
}
351352
}
352353

353-
fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span) {
354+
fn record_ty(&self, hir_id: HirId, ty: Ty<'tcx>, span: Span) {
354355
// FIXME: normalization and escaping regions
355356
let ty = if !ty.has_escaping_bound_vars() {
356357
// NOTE: These obligations are 100% redundant and are implied by
@@ -370,6 +371,10 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
370371
self.write_ty(hir_id, ty)
371372
}
372373

374+
fn record_res(&self, hir_id: HirId, result: TypeDependentDef) {
375+
self.write_resolution(hir_id, result);
376+
}
377+
373378
fn infcx(&self) -> Option<&infer::InferCtxt<'tcx>> {
374379
Some(&self.infcx)
375380
}
@@ -378,7 +383,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
378383
&self,
379384
decl: &rustc_hir::FnDecl<'tcx>,
380385
_generics: Option<&rustc_hir::Generics<'_>>,
381-
_hir_id: rustc_hir::HirId,
386+
_hir_id: HirId,
382387
_hir_ty: Option<&hir::Ty<'_>>,
383388
) -> (Vec<Ty<'tcx>>, Ty<'tcx>) {
384389
let input_tys = decl.inputs.iter().map(|a| self.lowerer().lower_arg_ty(a, None)).collect();
@@ -391,6 +396,12 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
391396
}
392397
}
393398

399+
impl HasTypeDependentDefs for FnCtxt<'_, '_> {
400+
fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
401+
self.typeck_results.borrow().type_dependent_def(id)
402+
}
403+
}
404+
394405
/// The `ty` representation of a user-provided type. Depending on the use-site
395406
/// we want to either use the unnormalized or the normalized form of this type.
396407
///

Diff for: compiler/rustc_middle/src/ty/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ pub mod print;
125125
pub mod relate;
126126
pub mod significant_drop_order;
127127
pub mod trait_def;
128+
pub mod typeck_results;
128129
pub mod util;
129130
pub mod vtable;
130131

@@ -151,7 +152,6 @@ mod rvalue_scopes;
151152
mod structural_impls;
152153
#[allow(hidden_glob_reexports)]
153154
mod sty;
154-
mod typeck_results;
155155
mod visit;
156156

157157
// Data types

Diff for: 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
@@ -247,32 +245,22 @@ impl<'tcx> TypeckResults<'tcx> {
247245

248246
/// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
249247
pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: HirId) -> Res {
250-
match *qpath {
251-
hir::QPath::Resolved(_, path) => path.res,
252-
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
253-
.type_dependent_def(id)
254-
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
255-
}
248+
HasTypeDependentDefs::qpath_res(self, qpath, id)
256249
}
257250

258-
pub fn type_dependent_defs(
259-
&self,
260-
) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
251+
pub fn type_dependent_defs(&self) -> LocalTableInContext<'_, TypeDependentDef> {
261252
LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
262253
}
263254

264255
pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
265-
validate_hir_id_for_typeck_results(self.hir_owner, id);
266-
self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
256+
self.type_dependent_defs().get(id).copied().and_then(|result| result.ok())
267257
}
268258

269259
pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
270260
self.type_dependent_def(id).map(|(_, def_id)| def_id)
271261
}
272262

273-
pub fn type_dependent_defs_mut(
274-
&mut self,
275-
) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
263+
pub fn type_dependent_defs_mut(&mut self) -> LocalTableInContextMut<'_, TypeDependentDef> {
276264
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
277265
}
278266

@@ -540,6 +528,33 @@ impl<'tcx> TypeckResults<'tcx> {
540528
}
541529
}
542530

531+
/// Resolved definitions for `<T>::X` associated paths and
532+
/// method calls, including those of overloaded operators.
533+
pub type TypeDependentDefs = ItemLocalMap<TypeDependentDef>;
534+
535+
pub type TypeDependentDef = Result<(DefKind, DefId), ErrorGuaranteed>;
536+
537+
// FIXME(fmease): Yuck!
538+
pub trait HasTypeDependentDefs {
539+
fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)>;
540+
541+
/// Returns the final resolution of a `QPath`.
542+
fn qpath_res(&self, qpath: &hir::QPath<'_>, id: HirId) -> Res {
543+
match qpath {
544+
hir::QPath::Resolved(_, path) => path.res,
545+
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
546+
.type_dependent_def(id)
547+
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
548+
}
549+
}
550+
}
551+
552+
impl HasTypeDependentDefs for TypeckResults<'_> {
553+
fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
554+
self.type_dependent_def(id)
555+
}
556+
}
557+
543558
/// Validate that the given HirId (respectively its `local_id` part) can be
544559
/// safely used as a key in the maps of a TypeckResults. For that to be
545560
/// the case, the HirId must have the same `owner` as all the other IDs in
@@ -572,6 +587,10 @@ pub struct LocalTableInContext<'a, V> {
572587
}
573588

574589
impl<'a, V> LocalTableInContext<'a, V> {
590+
pub fn new(hir_owner: OwnerId, data: &'a ItemLocalMap<V>) -> Self {
591+
Self { hir_owner, data }
592+
}
593+
575594
pub fn contains_key(&self, id: HirId) -> bool {
576595
validate_hir_id_for_typeck_results(self.hir_owner, id);
577596
self.data.contains_key(&id.local_id)
@@ -610,6 +629,10 @@ pub struct LocalTableInContextMut<'a, V> {
610629
}
611630

612631
impl<'a, V> LocalTableInContextMut<'a, V> {
632+
pub fn new(hir_owner: OwnerId, data: &'a mut ItemLocalMap<V>) -> Self {
633+
Self { hir_owner, data }
634+
}
635+
613636
pub fn get_mut(&mut self, id: HirId) -> Option<&mut V> {
614637
validate_hir_id_for_typeck_results(self.hir_owner, id);
615638
self.data.get_mut(&id.local_id)

Diff for: src/tools/tidy/src/ui_tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use ignore::Walk;
1717
const ENTRY_LIMIT: u32 = 901;
1818
// FIXME: The following limits should be reduced eventually.
1919

20-
const ISSUES_ENTRY_LIMIT: u32 = 1626;
20+
const ISSUES_ENTRY_LIMIT: u32 = 1624;
2121

2222
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
2323
"rs", // test source files
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0223]: ambiguous associated type
2+
--> $DIR/non-consecutive-shorthand-projections.rs:14:12
3+
|
4+
LL | let _: Identity<T::Project>::Project;
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
help: if there were a trait named `Example` with associated type `Project` implemented for `<T as Trait>::Project`, you could use the fully-qualified path
8+
|
9+
LL | let _: <<T as Trait>::Project as Example>::Project;
10+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0223`.

0 commit comments

Comments
 (0)