Skip to content

Commit ef902af

Browse files
make HIR paths store Defs per-namespace
1 parent e27e988 commit ef902af

File tree

29 files changed

+315
-171
lines changed

29 files changed

+315
-171
lines changed

src/librustc/hir/def.rs

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ pub enum Def {
7171
Err,
7272
}
7373

74+
impl Default for Def {
75+
fn default() -> Self {
76+
Def::Err
77+
}
78+
}
79+
7480
/// The result of resolving a path before lowering to HIR.
7581
/// `base_def` is definition of resolved part of the
7682
/// path, `unresolved_segments` is the number of unresolved
@@ -131,7 +137,7 @@ pub enum Namespace {
131137
}
132138

133139
/// Just a helper ‒ separate structure for each namespace.
134-
#[derive(Clone, Default, Debug)]
140+
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
135141
pub struct PerNS<T> {
136142
pub value_ns: T,
137143
pub type_ns: T,
@@ -156,6 +162,35 @@ impl<T> PerNS<Option<T>> {
156162
}
157163
}
158164

165+
impl PerNS<Def> {
166+
/// Ensures that no more than one namespace has a valid `Def`, then returns that `Def` (or
167+
/// `Err` if no namespaces had valid `Def`s).
168+
pub fn assert_single_ns(self) -> Def {
169+
let mut valid_defs = self.into_iter().filter(|d| *d != Def::Err).collect::<Vec<Def>>();
170+
if valid_defs.len() > 1 {
171+
bug!("single Def was requested but multiple were available: {:?}", valid_defs);
172+
}
173+
valid_defs.pop().unwrap_or(Def::Err)
174+
}
175+
176+
/// Returns whether all the `Def`s in this collection are `Err`.
177+
pub fn all_err(self) -> bool {
178+
self.into_iter().all(|d| d == Def::Err)
179+
}
180+
181+
/// Returns an iterator over the valid `Def`s in this collection. If all the `Def`s are `Err`,
182+
/// the iterator will yield a single `Err`.
183+
pub fn valid_defs(self) -> impl Iterator<Item=Def> {
184+
if self.all_err() {
185+
vec![Def::Err].into_iter()
186+
} else {
187+
let mut ret = Vec::with_capacity(3);
188+
ret.extend(self.into_iter().filter(|&d| d != Def::Err));
189+
ret.into_iter()
190+
}
191+
}
192+
}
193+
159194
impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
160195
type Output = T;
161196
fn index(&self, ns: Namespace) -> &T {
@@ -187,6 +222,18 @@ impl<T> IntoIterator for PerNS<T> {
187222
}
188223
}
189224

225+
impl From<Def> for PerNS<Def> {
226+
fn from(src: Def) -> PerNS<Def> {
227+
let mut ret = PerNS::<Def>::default();
228+
229+
if let Some(ns) = src.namespace() {
230+
ret[ns] = src;
231+
}
232+
233+
ret
234+
}
235+
}
236+
190237
/// Definition mapping
191238
pub type DefMap = NodeMap<PerNS<Option<PathResolution>>>;
192239

@@ -283,4 +330,39 @@ impl Def {
283330
Def::Err => "unresolved item",
284331
}
285332
}
333+
334+
/// The namespace associated with this Def. Returns `None` for `Err`.
335+
pub fn namespace(&self) -> Option<Namespace> {
336+
match *self {
337+
Def::Mod(..) |
338+
Def::Struct(..) |
339+
Def::Union(..) |
340+
Def::Enum(..) |
341+
Def::Variant(..) |
342+
Def::Trait(..) |
343+
Def::TyAlias(..) |
344+
Def::TyForeign(..) |
345+
Def::TraitAlias(..) |
346+
Def::AssociatedTy(..) |
347+
Def::PrimTy(..) |
348+
Def::TyParam(..) |
349+
Def::SelfTy(..) => Some(TypeNS),
350+
351+
Def::Fn(..) |
352+
Def::Const(..) |
353+
Def::Static(..) |
354+
Def::StructCtor(..) |
355+
Def::VariantCtor(..) |
356+
Def::Method(..) |
357+
Def::AssociatedConst(..) |
358+
Def::Local(..) |
359+
Def::Upvar(..) |
360+
Def::Label(..) => Some(ValueNS),
361+
362+
Def::Macro(..) |
363+
Def::GlobalAsm(..) => Some(MacroNS),
364+
365+
Def::Err => None,
366+
}
367+
}
286368
}

src/librustc/hir/intravisit.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,9 @@ pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath, id: Nod
625625
}
626626

627627
pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
628-
visitor.visit_def_mention(path.def);
628+
for def in path.defs {
629+
visitor.visit_def_mention(def);
630+
}
629631
for segment in &path.segments {
630632
visitor.visit_path_segment(path.span, segment);
631633
}

src/librustc/hir/lowering.rs

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,8 @@ impl<'a> LoweringContext<'a> {
567567
}
568568

569569
fn expect_full_def(&mut self, id: NodeId) -> Def {
570+
//FIXME: this grabs the first valid resolution - should all users of this function ask for
571+
//a specific namespace?
570572
self.resolver.get_resolution(id).map_or(Def::Err, |pr| {
571573
if pr.unresolved_segments() != 0 {
572574
bug!("path not fully resolved: {:?}", pr);
@@ -575,6 +577,15 @@ impl<'a> LoweringContext<'a> {
575577
})
576578
}
577579

580+
fn expect_full_def_per_ns(&mut self, id: NodeId) -> PerNS<Def> {
581+
self.resolver.get_all_resolutions(id).map(|res| res.map_or(Def::Err, |pr| {
582+
if pr.unresolved_segments() != 0 {
583+
bug!("path not fully resolved: {:?}", pr);
584+
}
585+
pr.base_def()
586+
}))
587+
}
588+
578589
fn diagnostic(&self) -> &errors::Handler {
579590
self.sess.diagnostic()
580591
}
@@ -1074,7 +1085,7 @@ impl<'a> LoweringContext<'a> {
10741085
TyKind::ImplicitSelf => hir::TyPath(hir::QPath::Resolved(
10751086
None,
10761087
P(hir::Path {
1077-
def: self.expect_full_def(t.id),
1088+
defs: self.expect_full_def_per_ns(t.id),
10781089
segments: hir_vec![hir::PathSegment::from_name(keywords::SelfType.name())],
10791090
span: t.span,
10801091
}),
@@ -1164,7 +1175,7 @@ impl<'a> LoweringContext<'a> {
11641175
None,
11651176
P(hir::Path {
11661177
span,
1167-
def: Def::TyParam(DefId::local(def_index)),
1178+
defs: Def::TyParam(DefId::local(def_index)).into(),
11681179
segments: hir_vec![hir::PathSegment::from_name(name)],
11691180
}),
11701181
))
@@ -1383,13 +1394,17 @@ impl<'a> LoweringContext<'a> {
13831394
let qself_position = qself.as_ref().map(|q| q.position);
13841395
let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
13851396

1386-
let resolution = self.resolver
1387-
.get_resolution(id)
1388-
.unwrap_or(PathResolution::new(Def::Err));
1397+
let resolutions = self.resolver
1398+
.get_all_resolutions(id)
1399+
.map(|res| res.unwrap_or(PathResolution::new(Def::Err)));
1400+
1401+
//FIXME(misdreavus): when constructing the segments below, the code assumes only one
1402+
//resolution/def
1403+
let first_res = self.resolver.get_resolution(id).unwrap_or(PathResolution::new(Def::Err));
13891404

1390-
let proj_start = p.segments.len() - resolution.unresolved_segments();
1405+
let proj_start = p.segments.len() - first_res.unresolved_segments();
13911406
let path = P(hir::Path {
1392-
def: resolution.base_def(),
1407+
defs: resolutions.map(|pr| pr.base_def()),
13931408
segments: p.segments[..proj_start]
13941409
.iter()
13951410
.enumerate()
@@ -1410,7 +1425,7 @@ impl<'a> LoweringContext<'a> {
14101425
krate: def_id.krate,
14111426
index: this.def_key(def_id).parent.expect("missing parent"),
14121427
};
1413-
let type_def_id = match resolution.base_def() {
1428+
let type_def_id = match first_res.base_def() {
14141429
Def::AssociatedTy(def_id) if i + 2 == proj_start => {
14151430
Some(parent_def_id(self, def_id))
14161431
}
@@ -1427,7 +1442,7 @@ impl<'a> LoweringContext<'a> {
14271442
}
14281443
_ => None,
14291444
};
1430-
let parenthesized_generic_args = match resolution.base_def() {
1445+
let parenthesized_generic_args = match first_res.base_def() {
14311446
// `a::b::Trait(Args)`
14321447
Def::Trait(..) if i + 1 == proj_start => ParenthesizedGenericArgs::Ok,
14331448
// `a::b::Trait(Args)::TraitItem`
@@ -1477,7 +1492,7 @@ impl<'a> LoweringContext<'a> {
14771492

14781493
// Simple case, either no projections, or only fully-qualified.
14791494
// E.g. `std::mem::size_of` or `<I as Iterator>::Item`.
1480-
if resolution.unresolved_segments() == 0 {
1495+
if first_res.unresolved_segments() == 0 {
14811496
return hir::QPath::Resolved(qself, path);
14821497
}
14831498

@@ -1542,7 +1557,7 @@ impl<'a> LoweringContext<'a> {
15421557
param_mode: ParamMode,
15431558
) -> hir::Path {
15441559
hir::Path {
1545-
def: self.expect_full_def(id),
1560+
defs: self.expect_full_def_per_ns(id),
15461561
segments: p.segments
15471562
.iter()
15481563
.map(|segment| {
@@ -2296,7 +2311,7 @@ impl<'a> LoweringContext<'a> {
22962311
});
22972312

22982313
if let Some(ref trait_ref) = trait_ref {
2299-
if let Def::Trait(def_id) = trait_ref.path.def {
2314+
if let Def::Trait(def_id) = trait_ref.path.defs.type_ns {
23002315
this.trait_impls.entry(def_id).or_insert(vec![]).push(id);
23012316
}
23022317
}
@@ -2839,7 +2854,7 @@ impl<'a> LoweringContext<'a> {
28392854
None,
28402855
P(hir::Path {
28412856
span: ident.span,
2842-
def,
2857+
defs: def.into(),
28432858
segments: hir_vec![hir::PathSegment::from_name(ident.name)],
28442859
}),
28452860
)),
@@ -3820,7 +3835,7 @@ impl<'a> LoweringContext<'a> {
38203835
None,
38213836
P(hir::Path {
38223837
span,
3823-
def: Def::Local(binding),
3838+
defs: Def::Local(binding).into(),
38243839
segments: hir_vec![hir::PathSegment::from_name(id)],
38253840
}),
38263841
));
@@ -4020,7 +4035,7 @@ impl<'a> LoweringContext<'a> {
40204035
let node = match qpath {
40214036
hir::QPath::Resolved(None, path) => {
40224037
// Turn trait object paths into `TyTraitObject` instead.
4023-
if let Def::Trait(_) = path.def {
4038+
if let Def::Trait(_) = path.defs.type_ns {
40244039
let principal = hir::PolyTraitRef {
40254040
bound_generic_params: hir::HirVec::new(),
40264041
trait_ref: hir::TraitRef {

src/librustc/hir/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub use self::UnOp::*;
2727
pub use self::UnsafeSource::*;
2828
pub use self::Visibility::{Public, Inherited};
2929

30-
use hir::def::Def;
30+
use hir::def::{Def, PerNS};
3131
use hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
3232
use util::nodemap::{NodeMap, FxHashSet};
3333
use mir::mono::Linkage;
@@ -291,8 +291,10 @@ pub struct LifetimeDef {
291291
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
292292
pub struct Path {
293293
pub span: Span,
294-
/// The definition that the path resolved to.
295-
pub def: Def,
294+
/// The definitions that the path resolved to. Since the same path can reference items in
295+
/// different namespaces, that information is stored here. Any namespaces without a resolution
296+
/// will contain `Def::Err`.
297+
pub defs: PerNS<Def>,
296298
/// The segments in the path: the things separated by `::`.
297299
pub segments: HirVec<PathSegment>,
298300
}

src/librustc/hir/pat_util.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,9 @@ impl hir::Pat {
6565
PatKind::Path(hir::QPath::Resolved(_, ref path)) |
6666
PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
6767
PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
68-
match path.def {
69-
Def::Variant(..) | Def::VariantCtor(..) => true,
70-
_ => false
71-
}
68+
if let Def::Variant(..) = path.defs.type_ns { true }
69+
else if let Def::VariantCtor(..) = path.defs.value_ns { true }
70+
else { false }
7271
}
7372
PatKind::Slice(..) => true,
7473
_ => false
@@ -79,7 +78,7 @@ impl hir::Pat {
7978
match self.node {
8079
PatKind::Path(hir::QPath::TypeRelative(..)) => true,
8180
PatKind::Path(hir::QPath::Resolved(_, ref path)) => {
82-
match path.def {
81+
match path.defs.value_ns {
8382
Def::Const(..) | Def::AssociatedConst(..) => true,
8483
_ => false
8584
}
@@ -158,10 +157,10 @@ impl hir::Pat {
158157
PatKind::Path(hir::QPath::Resolved(_, ref path)) |
159158
PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
160159
PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
161-
match path.def {
162-
Def::Variant(id) |
163-
Def::VariantCtor(id, ..) => variants.push(id),
164-
_ => ()
160+
if let Def::Variant(id) = path.defs.type_ns {
161+
variants.push(id);
162+
} else if let Def::VariantCtor(id, ..) = path.defs.value_ns {
163+
variants.push(id);
165164
}
166165
}
167166
_ => ()

src/librustc/ich/impls_hir.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ impl_stable_hash_for!(struct hir::LifetimeDef {
170170

171171
impl_stable_hash_for!(struct hir::Path {
172172
span,
173-
def,
173+
defs,
174174
segments
175175
});
176176

@@ -1070,6 +1070,12 @@ impl_stable_hash_for!(enum hir::def::Def {
10701070
Err
10711071
});
10721072

1073+
impl_stable_hash_for!(struct hir::def::PerNS<hir::def::Def> {
1074+
value_ns,
1075+
type_ns,
1076+
macro_ns
1077+
});
1078+
10731079
impl_stable_hash_for!(enum hir::Mutability {
10741080
MutMutable,
10751081
MutImmutable

0 commit comments

Comments
 (0)