Skip to content

Commit

Permalink
AST: Keep distinction between path and ::path in imports and visi…
Browse files Browse the repository at this point in the history
…bilities

Add the root segment for name resolution purposes only
  • Loading branch information
petrochenkov committed Mar 17, 2018
1 parent b057c55 commit e5fb138
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 77 deletions.
23 changes: 8 additions & 15 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1355,17 +1355,11 @@ impl<'a> LoweringContext<'a> {
id: NodeId,
p: &Path,
name: Option<Name>,
param_mode: ParamMode,
defaults_to_global: bool)
param_mode: ParamMode)
-> hir::Path {
let mut segments = p.segments.iter();
if defaults_to_global && p.is_global() {
segments.next();
}

hir::Path {
def: self.expect_full_def(id),
segments: segments.map(|segment| {
segments: p.segments.iter().map(|segment| {
self.lower_path_segment(p.span, segment, param_mode, 0,
ParenthesizedGenericArgs::Err,
ImplTraitContext::Disallowed)
Expand All @@ -1378,10 +1372,9 @@ impl<'a> LoweringContext<'a> {
fn lower_path(&mut self,
id: NodeId,
p: &Path,
param_mode: ParamMode,
defaults_to_global: bool)
param_mode: ParamMode)
-> hir::Path {
self.lower_path_extra(id, p, None, param_mode, defaults_to_global)
self.lower_path_extra(id, p, None, param_mode)
}

fn lower_path_segment(&mut self,
Expand Down Expand Up @@ -2069,7 +2062,7 @@ impl<'a> LoweringContext<'a> {
}
}

let path = P(self.lower_path(id, &path, ParamMode::Explicit, true));
let path = P(self.lower_path(id, &path, ParamMode::Explicit));
hir::ItemUse(path, hir::UseKind::Single)
}
UseTreeKind::Glob => {
Expand All @@ -2080,7 +2073,7 @@ impl<'a> LoweringContext<'a> {
.cloned()
.collect(),
span: path.span,
}, ParamMode::Explicit, true));
}, ParamMode::Explicit));
hir::ItemUse(path, hir::UseKind::Glob)
}
UseTreeKind::Nested(ref trees) => {
Expand Down Expand Up @@ -2136,7 +2129,7 @@ impl<'a> LoweringContext<'a> {
// Privatize the degenerate import base, used only to check
// the stability of `use a::{};`, to avoid it showing up as
// a re-export by accident when `pub`, e.g. in documentation.
let path = P(self.lower_path(id, &prefix, ParamMode::Explicit, true));
let path = P(self.lower_path(id, &prefix, ParamMode::Explicit));
*vis = hir::Inherited;
hir::ItemUse(path, hir::UseKind::ListStem)
}
Expand Down Expand Up @@ -3379,7 +3372,7 @@ impl<'a> LoweringContext<'a> {
VisibilityKind::Crate(..) => hir::Visibility::Crate,
VisibilityKind::Restricted { ref path, id, .. } => {
hir::Visibility::Restricted {
path: P(self.lower_path(id, path, ParamMode::Explicit, true)),
path: P(self.lower_path(id, path, ParamMode::Explicit)),
id: if let Some(owner) = explicit_owner {
self.lower_node_id_with_owner(id, owner).node_id
} else {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,9 @@ impl<'a> Resolver<'a> {

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

Expand Down
19 changes: 11 additions & 8 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2164,8 +2164,9 @@ impl<'a> Resolver<'a> {
}

ItemKind::Use(ref use_tree) => {
// Imports are resolved as global by default, add starting root segment.
let path = Path {
segments: vec![],
segments: use_tree.prefix.make_root().into_iter().collect(),
span: use_tree.span,
};
self.resolve_use_tree(item.id, use_tree, &path);
Expand Down Expand Up @@ -2300,7 +2301,6 @@ impl<'a> Resolver<'a> {
None,
&path,
trait_ref.path.span,
trait_ref.path.segments.last().unwrap().span,
PathSource::Trait(AliasPossibility::No)
).base_def();
if def != Def::Err {
Expand Down Expand Up @@ -2731,18 +2731,17 @@ impl<'a> Resolver<'a> {
let segments = &path.segments.iter()
.map(|seg| respan(seg.span, seg.identifier))
.collect::<Vec<_>>();
let ident_span = path.segments.last().map_or(path.span, |seg| seg.span);
self.smart_resolve_path_fragment(id, qself, segments, path.span, ident_span, source)
self.smart_resolve_path_fragment(id, qself, segments, path.span, source)
}

fn smart_resolve_path_fragment(&mut self,
id: NodeId,
qself: Option<&QSelf>,
path: &[SpannedIdent],
span: Span,
ident_span: Span,
source: PathSource)
-> PathResolution {
let ident_span = path.last().map_or(span, |ident| ident.span);
let ns = source.namespace();
let is_expected = &|def| source.is_expected(def);
let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false };
Expand Down Expand Up @@ -3090,7 +3089,7 @@ impl<'a> Resolver<'a> {
// Make sure `A::B` in `<T as A>::B::C` is a trait item.
let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1],
span, span, PathSource::TraitItem(ns));
span, PathSource::TraitItem(ns));
return Some(PathResolution::with_unresolved_segments(
res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1
));
Expand Down Expand Up @@ -3941,8 +3940,12 @@ impl<'a> Resolver<'a> {
ty::Visibility::Restricted(self.current_module.normal_ancestor_id)
}
ast::VisibilityKind::Restricted { ref path, id, .. } => {
let def = self.smart_resolve_path(id, None, path,
PathSource::Visibility).base_def();
// Visibilities are resolved as global by default, add starting root segment.
let segments = path.make_root().iter().chain(path.segments.iter())
.map(|seg| respan(seg.span, seg.identifier))
.collect::<Vec<_>>();
let def = self.smart_resolve_path_fragment(id, None, &segments, path.span,
PathSource::Visibility).base_def();
if def == Def::Err {
ty::Visibility::Public
} else {
Expand Down
9 changes: 4 additions & 5 deletions src/librustc_resolve/resolve_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -667,11 +667,10 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
}
PathResult::Failed(span, msg, true) => {
let (mut self_path, mut self_result) = (module_path.clone(), None);
if !self_path.is_empty() &&
!token::Ident(self_path[0].node).is_path_segment_keyword() &&
!(self_path.len() > 1 &&
token::Ident(self_path[1].node).is_path_segment_keyword())
{
let is_special = |ident| token::Ident(ident).is_path_segment_keyword() &&
ident.name != keywords::CrateRoot.name();
if !self_path.is_empty() && !is_special(self_path[0].node) &&
!(self_path.len() > 1 && is_special(self_path[1].node)) {
self_path[0].node.name = keywords::SelfValue.name();
self_result = Some(self.resolve_path(&self_path, None, false, span));
}
Expand Down
17 changes: 8 additions & 9 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,16 @@ impl Path {
}
}

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

pub fn is_global(&self) -> bool {
Expand Down
10 changes: 7 additions & 3 deletions src/libsyntax/ext/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,13 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
None
};
segments.push(ast::PathSegment { identifier: last_identifier, span, parameters });
let path = ast::Path { span, segments };

if global { path.default_to_global() } else { path }
let mut path = ast::Path { span, segments };
if global {
if let Some(seg) = path.make_root() {
path.segments.insert(0, seg);
}
}
path
}

/// Constructs a qualified path.
Expand Down
15 changes: 5 additions & 10 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5869,7 +5869,7 @@ impl<'a> Parser<'a> {
// `pub(in path)`
self.bump(); // `(`
self.bump(); // `in`
let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `path`
let path = self.parse_path(PathStyle::Mod)?; // `path`
self.expect(&token::CloseDelim(token::Paren))?; // `)`
let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted {
path: P(path),
Expand All @@ -5882,7 +5882,7 @@ impl<'a> Parser<'a> {
{
// `pub(self)` or `pub(super)`
self.bump(); // `(`
let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `super`/`self`
let path = self.parse_path(PathStyle::Mod)?; // `super`/`self`
self.expect(&token::CloseDelim(token::Paren))?; // `)`
let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted {
path: P(path),
Expand Down Expand Up @@ -6480,7 +6480,7 @@ impl<'a> Parser<'a> {

if self.eat_keyword(keywords::Use) {
// USE ITEM
let item_ = ItemKind::Use(P(self.parse_use_tree(false)?));
let item_ = ItemKind::Use(P(self.parse_use_tree()?));
self.expect(&token::Semi)?;

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

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

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

prefix.segments.append(&mut parsed.segments);
prefix.span = prefix.span.to(parsed.span);
Expand Down Expand Up @@ -7051,7 +7046,7 @@ impl<'a> Parser<'a> {
self.parse_unspanned_seq(&token::OpenDelim(token::Brace),
&token::CloseDelim(token::Brace),
SeqSep::trailing_allowed(token::Comma), |this| {
Ok((this.parse_use_tree(true)?, ast::DUMMY_NODE_ID))
Ok((this.parse_use_tree()?, ast::DUMMY_NODE_ID))
})
}

Expand Down
1 change: 1 addition & 0 deletions src/libsyntax/parse/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ impl Token {
id.name == keywords::SelfType.name() ||
id.name == keywords::Extern.name() ||
id.name == keywords::Crate.name() ||
id.name == keywords::CrateRoot.name() ||
id.name == keywords::DollarCrate.name(),
None => false,
}
Expand Down
Loading

0 comments on commit e5fb138

Please sign in to comment.