diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 1e355bb30cbec..dd3b9350d9161 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1355,17 +1355,11 @@ impl<'a> LoweringContext<'a> { id: NodeId, p: &Path, name: Option, - 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) @@ -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, @@ -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 => { @@ -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) => { @@ -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) } @@ -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 { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index e6c8dfa835654..c192f349c2019 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -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, }; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c84caee13e82a..23ad27ec2c3d6 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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); @@ -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 { @@ -2731,8 +2731,7 @@ impl<'a> Resolver<'a> { let segments = &path.segments.iter() .map(|seg| respan(seg.span, seg.identifier)) .collect::>(); - 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, @@ -2740,9 +2739,9 @@ impl<'a> Resolver<'a> { 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 }; @@ -3090,7 +3089,7 @@ impl<'a> Resolver<'a> { // Make sure `A::B` in `::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 )); @@ -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::>(); + let def = self.smart_resolve_path_fragment(id, None, &segments, path.span, + PathSource::Visibility).base_def(); if def == Def::Err { ty::Visibility::Public } else { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 01c1ded94578e..4cbebdc3c1c39 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -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)); } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index fdb32486b5de2..4ce6c53d3383b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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 { + 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 { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 97f784dd6179e..ee646dc91743b 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -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. diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 7a4329304907f..ca879765b4efc 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -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), @@ -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), @@ -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; @@ -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 { @@ -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)) { @@ -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); @@ -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)) }) } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 097a2eb89fdf4..3c602f1d1a800 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -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, } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 18a758ba96846..319a9a3bbaebc 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -353,7 +353,7 @@ pub fn fn_block_to_string(p: &ast::FnDecl) -> String { } pub fn path_to_string(p: &ast::Path) -> String { - to_string(|s| s.print_path(p, false, 0, false)) + to_string(|s| s.print_path(p, false, 0)) } pub fn path_segment_to_string(p: &ast::PathSegment) -> String { @@ -1051,7 +1051,7 @@ impl<'a> State<'a> { &f.generic_params)?; } ast::TyKind::Path(None, ref path) => { - self.print_path(path, false, 0, false)?; + self.print_path(path, false, 0)?; } ast::TyKind::Path(Some(ref qself), ref path) => { self.print_qpath(path, qself, false)? @@ -1378,7 +1378,7 @@ impl<'a> State<'a> { self.s.word(";")?; } ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => { - self.print_path(&node.path, false, 0, false)?; + self.print_path(&node.path, false, 0)?; self.s.word("! ")?; self.print_ident(item.ident)?; self.cbox(INDENT_UNIT)?; @@ -1403,7 +1403,7 @@ impl<'a> State<'a> { } fn print_trait_ref(&mut self, t: &ast::TraitRef) -> io::Result<()> { - self.print_path(&t.path, false, 0, false) + self.print_path(&t.path, false, 0) } fn print_formal_generic_params( @@ -1460,7 +1460,7 @@ impl<'a> State<'a> { ast::CrateSugar::JustCrate => self.word_nbsp("crate") } ast::VisibilityKind::Restricted { ref path, .. } => { - let path = to_string(|s| s.print_path(path, false, 0, true)); + let path = to_string(|s| s.print_path(path, false, 0)); if path == "self" || path == "super" { self.word_nbsp(&format!("pub({})", path)) } else { @@ -1594,7 +1594,7 @@ impl<'a> State<'a> { } ast::TraitItemKind::Macro(codemap::Spanned { ref node, .. }) => { // code copied from ItemKind::Mac: - self.print_path(&node.path, false, 0, false)?; + self.print_path(&node.path, false, 0)?; self.s.word("! ")?; self.cbox(INDENT_UNIT)?; self.popen()?; @@ -1628,7 +1628,7 @@ impl<'a> State<'a> { } ast::ImplItemKind::Macro(codemap::Spanned { ref node, .. }) => { // code copied from ItemKind::Mac: - self.print_path(&node.path, false, 0, false)?; + self.print_path(&node.path, false, 0)?; self.s.word("! ")?; self.cbox(INDENT_UNIT)?; self.popen()?; @@ -1814,7 +1814,7 @@ impl<'a> State<'a> { pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken) -> io::Result<()> { - self.print_path(&m.node.path, false, 0, false)?; + self.print_path(&m.node.path, false, 0)?; self.s.word("!")?; match delim { token::Paren => self.popen()?, @@ -1915,7 +1915,7 @@ impl<'a> State<'a> { fields: &[ast::Field], wth: &Option>, attrs: &[Attribute]) -> io::Result<()> { - self.print_path(path, true, 0, false)?; + self.print_path(path, true, 0)?; self.s.word("{")?; self.print_inner_attributes_inline(attrs)?; self.commasep_cmnt( @@ -2236,7 +2236,7 @@ impl<'a> State<'a> { } } ast::ExprKind::Path(None, ref path) => { - self.print_path(path, true, 0, false)? + self.print_path(path, true, 0)? } ast::ExprKind::Path(Some(ref qself), ref path) => { self.print_qpath(path, qself, true)? @@ -2396,17 +2396,12 @@ impl<'a> State<'a> { fn print_path(&mut self, path: &ast::Path, colons_before_params: bool, - depth: usize, - defaults_to_global: bool) + depth: usize) -> io::Result<()> { self.maybe_print_comment(path.span.lo())?; - let mut segments = path.segments[..path.segments.len()-depth].iter(); - if defaults_to_global && path.is_global() { - segments.next(); - } - for (i, segment) in segments.enumerate() { + for (i, segment) in path.segments[..path.segments.len() - depth].iter().enumerate() { if i > 0 { self.s.word("::")? } @@ -2445,7 +2440,7 @@ impl<'a> State<'a> { self.s.space()?; self.word_space("as")?; let depth = path.segments.len() - qself.position; - self.print_path(path, false, depth, false)?; + self.print_path(path, false, depth)?; } self.s.word(">")?; self.s.word("::")?; @@ -2548,7 +2543,7 @@ impl<'a> State<'a> { } } PatKind::TupleStruct(ref path, ref elts, ddpos) => { - self.print_path(path, true, 0, false)?; + self.print_path(path, true, 0)?; self.popen()?; if let Some(ddpos) = ddpos { self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p))?; @@ -2566,13 +2561,13 @@ impl<'a> State<'a> { self.pclose()?; } PatKind::Path(None, ref path) => { - self.print_path(path, true, 0, false)?; + self.print_path(path, true, 0)?; } PatKind::Path(Some(ref qself), ref path) => { self.print_qpath(path, qself, false)?; } PatKind::Struct(ref path, ref fields, etc) => { - self.print_path(path, true, 0, false)?; + self.print_path(path, true, 0)?; self.nbsp()?; self.word_space("{")?; self.commasep_cmnt( @@ -2950,7 +2945,7 @@ impl<'a> State<'a> { pub fn print_use_tree(&mut self, tree: &ast::UseTree) -> io::Result<()> { match tree.kind { ast::UseTreeKind::Simple(rename) => { - self.print_path(&tree.prefix, false, 0, true)?; + self.print_path(&tree.prefix, false, 0)?; if let Some(rename) = rename { self.s.space()?; self.word_space("as")?; @@ -2959,7 +2954,7 @@ impl<'a> State<'a> { } ast::UseTreeKind::Glob => { if !tree.prefix.segments.is_empty() { - self.print_path(&tree.prefix, false, 0, true)?; + self.print_path(&tree.prefix, false, 0)?; self.s.word("::")?; } self.s.word("*")?; @@ -2968,7 +2963,7 @@ impl<'a> State<'a> { if tree.prefix.segments.is_empty() { self.s.word("{")?; } else { - self.print_path(&tree.prefix, false, 0, true)?; + self.print_path(&tree.prefix, false, 0)?; self.s.word("::{")?; } self.commasep(Inconsistent, &items[..], |this, &(ref tree, _)| { diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 59425929f7ed0..401183e7c7d5e 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -79,7 +79,7 @@ pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<&str> vis: respan(span.empty(), ast::VisibilityKind::Inherited), node: ast::ItemKind::Use(P(ast::UseTree { prefix: ast::Path { - segments: ["{{root}}", name, "prelude", "v1"].into_iter().map(|name| { + segments: [name, "prelude", "v1"].into_iter().map(|name| { ast::PathSegment::from_ident(ast::Ident::from_str(name), DUMMY_SP) }).collect(), span,