Skip to content

Commit e5fb138

Browse files
committed
AST: Keep distinction between path and ::path in imports and visibilities
Add the root segment for name resolution purposes only
1 parent b057c55 commit e5fb138

File tree

10 files changed

+66
-77
lines changed

10 files changed

+66
-77
lines changed

src/librustc/hir/lowering.rs

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,17 +1355,11 @@ impl<'a> LoweringContext<'a> {
13551355
id: NodeId,
13561356
p: &Path,
13571357
name: Option<Name>,
1358-
param_mode: ParamMode,
1359-
defaults_to_global: bool)
1358+
param_mode: ParamMode)
13601359
-> hir::Path {
1361-
let mut segments = p.segments.iter();
1362-
if defaults_to_global && p.is_global() {
1363-
segments.next();
1364-
}
1365-
13661360
hir::Path {
13671361
def: self.expect_full_def(id),
1368-
segments: segments.map(|segment| {
1362+
segments: p.segments.iter().map(|segment| {
13691363
self.lower_path_segment(p.span, segment, param_mode, 0,
13701364
ParenthesizedGenericArgs::Err,
13711365
ImplTraitContext::Disallowed)
@@ -1378,10 +1372,9 @@ impl<'a> LoweringContext<'a> {
13781372
fn lower_path(&mut self,
13791373
id: NodeId,
13801374
p: &Path,
1381-
param_mode: ParamMode,
1382-
defaults_to_global: bool)
1375+
param_mode: ParamMode)
13831376
-> hir::Path {
1384-
self.lower_path_extra(id, p, None, param_mode, defaults_to_global)
1377+
self.lower_path_extra(id, p, None, param_mode)
13851378
}
13861379

13871380
fn lower_path_segment(&mut self,
@@ -2069,7 +2062,7 @@ impl<'a> LoweringContext<'a> {
20692062
}
20702063
}
20712064

2072-
let path = P(self.lower_path(id, &path, ParamMode::Explicit, true));
2065+
let path = P(self.lower_path(id, &path, ParamMode::Explicit));
20732066
hir::ItemUse(path, hir::UseKind::Single)
20742067
}
20752068
UseTreeKind::Glob => {
@@ -2080,7 +2073,7 @@ impl<'a> LoweringContext<'a> {
20802073
.cloned()
20812074
.collect(),
20822075
span: path.span,
2083-
}, ParamMode::Explicit, true));
2076+
}, ParamMode::Explicit));
20842077
hir::ItemUse(path, hir::UseKind::Glob)
20852078
}
20862079
UseTreeKind::Nested(ref trees) => {
@@ -2136,7 +2129,7 @@ impl<'a> LoweringContext<'a> {
21362129
// Privatize the degenerate import base, used only to check
21372130
// the stability of `use a::{};`, to avoid it showing up as
21382131
// a re-export by accident when `pub`, e.g. in documentation.
2139-
let path = P(self.lower_path(id, &prefix, ParamMode::Explicit, true));
2132+
let path = P(self.lower_path(id, &prefix, ParamMode::Explicit));
21402133
*vis = hir::Inherited;
21412134
hir::ItemUse(path, hir::UseKind::ListStem)
21422135
}
@@ -3379,7 +3372,7 @@ impl<'a> LoweringContext<'a> {
33793372
VisibilityKind::Crate(..) => hir::Visibility::Crate,
33803373
VisibilityKind::Restricted { ref path, id, .. } => {
33813374
hir::Visibility::Restricted {
3382-
path: P(self.lower_path(id, path, ParamMode::Explicit, true)),
3375+
path: P(self.lower_path(id, path, ParamMode::Explicit)),
33833376
id: if let Some(owner) = explicit_owner {
33843377
self.lower_node_id_with_owner(id, owner).node_id
33853378
} else {

src/librustc_resolve/build_reduced_graph.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,9 @@ impl<'a> Resolver<'a> {
245245

246246
match item.node {
247247
ItemKind::Use(ref use_tree) => {
248-
// Just an empty prefix to start out
248+
// Imports are resolved as global by default, add starting root segment.
249249
let prefix = ast::Path {
250-
segments: vec![],
250+
segments: use_tree.prefix.make_root().into_iter().collect(),
251251
span: use_tree.span,
252252
};
253253

src/librustc_resolve/lib.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2164,8 +2164,9 @@ impl<'a> Resolver<'a> {
21642164
}
21652165

21662166
ItemKind::Use(ref use_tree) => {
2167+
// Imports are resolved as global by default, add starting root segment.
21672168
let path = Path {
2168-
segments: vec![],
2169+
segments: use_tree.prefix.make_root().into_iter().collect(),
21692170
span: use_tree.span,
21702171
};
21712172
self.resolve_use_tree(item.id, use_tree, &path);
@@ -2300,7 +2301,6 @@ impl<'a> Resolver<'a> {
23002301
None,
23012302
&path,
23022303
trait_ref.path.span,
2303-
trait_ref.path.segments.last().unwrap().span,
23042304
PathSource::Trait(AliasPossibility::No)
23052305
).base_def();
23062306
if def != Def::Err {
@@ -2731,18 +2731,17 @@ impl<'a> Resolver<'a> {
27312731
let segments = &path.segments.iter()
27322732
.map(|seg| respan(seg.span, seg.identifier))
27332733
.collect::<Vec<_>>();
2734-
let ident_span = path.segments.last().map_or(path.span, |seg| seg.span);
2735-
self.smart_resolve_path_fragment(id, qself, segments, path.span, ident_span, source)
2734+
self.smart_resolve_path_fragment(id, qself, segments, path.span, source)
27362735
}
27372736

27382737
fn smart_resolve_path_fragment(&mut self,
27392738
id: NodeId,
27402739
qself: Option<&QSelf>,
27412740
path: &[SpannedIdent],
27422741
span: Span,
2743-
ident_span: Span,
27442742
source: PathSource)
27452743
-> PathResolution {
2744+
let ident_span = path.last().map_or(span, |ident| ident.span);
27462745
let ns = source.namespace();
27472746
let is_expected = &|def| source.is_expected(def);
27482747
let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false };
@@ -3090,7 +3089,7 @@ impl<'a> Resolver<'a> {
30903089
// Make sure `A::B` in `<T as A>::B::C` is a trait item.
30913090
let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
30923091
let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1],
3093-
span, span, PathSource::TraitItem(ns));
3092+
span, PathSource::TraitItem(ns));
30943093
return Some(PathResolution::with_unresolved_segments(
30953094
res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1
30963095
));
@@ -3941,8 +3940,12 @@ impl<'a> Resolver<'a> {
39413940
ty::Visibility::Restricted(self.current_module.normal_ancestor_id)
39423941
}
39433942
ast::VisibilityKind::Restricted { ref path, id, .. } => {
3944-
let def = self.smart_resolve_path(id, None, path,
3945-
PathSource::Visibility).base_def();
3943+
// Visibilities are resolved as global by default, add starting root segment.
3944+
let segments = path.make_root().iter().chain(path.segments.iter())
3945+
.map(|seg| respan(seg.span, seg.identifier))
3946+
.collect::<Vec<_>>();
3947+
let def = self.smart_resolve_path_fragment(id, None, &segments, path.span,
3948+
PathSource::Visibility).base_def();
39463949
if def == Def::Err {
39473950
ty::Visibility::Public
39483951
} else {

src/librustc_resolve/resolve_imports.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -667,11 +667,10 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
667667
}
668668
PathResult::Failed(span, msg, true) => {
669669
let (mut self_path, mut self_result) = (module_path.clone(), None);
670-
if !self_path.is_empty() &&
671-
!token::Ident(self_path[0].node).is_path_segment_keyword() &&
672-
!(self_path.len() > 1 &&
673-
token::Ident(self_path[1].node).is_path_segment_keyword())
674-
{
670+
let is_special = |ident| token::Ident(ident).is_path_segment_keyword() &&
671+
ident.name != keywords::CrateRoot.name();
672+
if !self_path.is_empty() && !is_special(self_path[0].node) &&
673+
!(self_path.len() > 1 && is_special(self_path[1].node)) {
675674
self_path[0].node.name = keywords::SelfValue.name();
676675
self_result = Some(self.resolve_path(&self_path, None, false, span));
677676
}

src/libsyntax/ast.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,17 +108,16 @@ impl Path {
108108
}
109109
}
110110

111-
// Add starting "crate root" segment to all paths except those that
112-
// already have it or start with `self`, `super`, `Self` or `$crate`.
113-
pub fn default_to_global(mut self) -> Path {
114-
if !self.is_global() {
115-
let ident = self.segments[0].identifier;
116-
if !::parse::token::Ident(ident).is_path_segment_keyword() ||
117-
ident.name == keywords::Crate.name() {
118-
self.segments.insert(0, PathSegment::crate_root(self.span));
111+
// Make a "crate root" segment for this path unless it already has it
112+
// or starts with something like `self`/`super`/`$crate`/etc.
113+
pub fn make_root(&self) -> Option<PathSegment> {
114+
if let Some(ident) = self.segments.get(0).map(|seg| seg.identifier) {
115+
if ::parse::token::Ident(ident).is_path_segment_keyword() &&
116+
ident.name != keywords::Crate.name() {
117+
return None;
119118
}
120119
}
121-
self
120+
Some(PathSegment::crate_root(self.span.with_hi(self.span.lo())))
122121
}
123122

124123
pub fn is_global(&self) -> bool {

src/libsyntax/ext/build.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -329,9 +329,13 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
329329
None
330330
};
331331
segments.push(ast::PathSegment { identifier: last_identifier, span, parameters });
332-
let path = ast::Path { span, segments };
333-
334-
if global { path.default_to_global() } else { path }
332+
let mut path = ast::Path { span, segments };
333+
if global {
334+
if let Some(seg) = path.make_root() {
335+
path.segments.insert(0, seg);
336+
}
337+
}
338+
path
335339
}
336340

337341
/// Constructs a qualified path.

src/libsyntax/parse/parser.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5869,7 +5869,7 @@ impl<'a> Parser<'a> {
58695869
// `pub(in path)`
58705870
self.bump(); // `(`
58715871
self.bump(); // `in`
5872-
let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `path`
5872+
let path = self.parse_path(PathStyle::Mod)?; // `path`
58735873
self.expect(&token::CloseDelim(token::Paren))?; // `)`
58745874
let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted {
58755875
path: P(path),
@@ -5882,7 +5882,7 @@ impl<'a> Parser<'a> {
58825882
{
58835883
// `pub(self)` or `pub(super)`
58845884
self.bump(); // `(`
5885-
let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `super`/`self`
5885+
let path = self.parse_path(PathStyle::Mod)?; // `super`/`self`
58865886
self.expect(&token::CloseDelim(token::Paren))?; // `)`
58875887
let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted {
58885888
path: P(path),
@@ -6480,7 +6480,7 @@ impl<'a> Parser<'a> {
64806480

64816481
if self.eat_keyword(keywords::Use) {
64826482
// USE ITEM
6483-
let item_ = ItemKind::Use(P(self.parse_use_tree(false)?));
6483+
let item_ = ItemKind::Use(P(self.parse_use_tree()?));
64846484
self.expect(&token::Semi)?;
64856485

64866486
let prev_span = self.prev_span;
@@ -6984,7 +6984,7 @@ impl<'a> Parser<'a> {
69846984
/// PATH `::` `*` |
69856985
/// PATH `::` `{` USE_TREE_LIST `}` |
69866986
/// PATH [`as` IDENT]
6987-
fn parse_use_tree(&mut self, nested: bool) -> PResult<'a, UseTree> {
6987+
fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {
69886988
let lo = self.span;
69896989

69906990
let mut prefix = ast::Path {
@@ -6998,8 +6998,6 @@ impl<'a> Parser<'a> {
69986998
// Remove the first `::`
69996999
if self.eat(&token::ModSep) {
70007000
prefix.segments.push(PathSegment::crate_root(self.prev_span));
7001-
} else if !nested {
7002-
prefix.segments.push(PathSegment::crate_root(self.span));
70037001
}
70047002

70057003
if self.eat(&token::BinOp(token::Star)) {
@@ -7014,9 +7012,6 @@ impl<'a> Parser<'a> {
70147012
} else {
70157013
// `use path::...;`
70167014
let mut parsed = self.parse_path(PathStyle::Mod)?;
7017-
if !nested {
7018-
parsed = parsed.default_to_global();
7019-
}
70207015

70217016
prefix.segments.append(&mut parsed.segments);
70227017
prefix.span = prefix.span.to(parsed.span);
@@ -7051,7 +7046,7 @@ impl<'a> Parser<'a> {
70517046
self.parse_unspanned_seq(&token::OpenDelim(token::Brace),
70527047
&token::CloseDelim(token::Brace),
70537048
SeqSep::trailing_allowed(token::Comma), |this| {
7054-
Ok((this.parse_use_tree(true)?, ast::DUMMY_NODE_ID))
7049+
Ok((this.parse_use_tree()?, ast::DUMMY_NODE_ID))
70557050
})
70567051
}
70577052

src/libsyntax/parse/token.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ impl Token {
362362
id.name == keywords::SelfType.name() ||
363363
id.name == keywords::Extern.name() ||
364364
id.name == keywords::Crate.name() ||
365+
id.name == keywords::CrateRoot.name() ||
365366
id.name == keywords::DollarCrate.name(),
366367
None => false,
367368
}

0 commit comments

Comments
 (0)