]> git.lizzy.rs Git - rust.git/commitdiff
AST: Keep distinction between `path` and `::path` in imports and visibilities
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Fri, 9 Mar 2018 23:02:39 +0000 (02:02 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sat, 17 Mar 2018 19:12:21 +0000 (22:12 +0300)
Add the root segment for name resolution purposes only

src/librustc/hir/lowering.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/libsyntax/ast.rs
src/libsyntax/ext/build.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/libsyntax/std_inject.rs

index 1e355bb30cbec0f7e07633075389f3d4943d36cf..dd3b9350d91610c40937efc8707059e19a8af1db 100644 (file)
@@ -1355,17 +1355,11 @@ fn lower_path_extra(&mut self,
                         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)
@@ -1378,10 +1372,9 @@ fn lower_path_extra(&mut self,
     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 @@ fn lower_use_tree(&mut self,
                     }
                 }
 
-                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 @@ fn lower_use_tree(&mut self,
                         .cloned()
                         .collect(),
                     span: path.span,
-                }, ParamMode::Explicit, true));
+                }, ParamMode::Explicit));
                 hir::ItemUse(path, hir::UseKind::Glob)
             }
             UseTreeKind::Nested(ref trees) => {
@@ -2136,7 +2129,7 @@ fn lower_use_tree(&mut self,
                 // 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 @@ fn lower_visibility(&mut self,
             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 {
index e6c8dfa83565450870b2d946c41116fe3cb0eb93..c192f349c2019723f6eb2bba0679db27a4c43220 100644 (file)
@@ -245,9 +245,9 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
 
         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,
                 };
 
index c84caee13e82a0c4233f535661ed12dd35367912..23ad27ec2c3d6ba677c617d26cd564313820e158 100644 (file)
@@ -2164,8 +2164,9 @@ fn resolve_item(&mut self, item: &Item) {
             }
 
             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 @@ fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f:
                 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 @@ fn smart_resolve_path(&mut self,
         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,
@@ -2740,9 +2739,9 @@ fn smart_resolve_path_fragment(&mut self,
                                    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 @@ fn resolve_qpath(&mut self,
             // 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
             ));
@@ -3941,8 +3940,12 @@ fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
                 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 {
index 01c1ded94578ecc1fa45da7521930f70595598e7..4cbebdc3c1c39f9458fb732e4e0da80bf471d2f7 100644 (file)
@@ -667,11 +667,10 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
             }
             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));
                 }
index fdb32486b5de2cdc13023bb3577a4a3e7df79947..4ce6c53d3383bacfd11eb62384ae98885ee63c8d 100644 (file)
@@ -108,17 +108,16 @@ pub fn from_ident(s: Span, identifier: Ident) -> 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 {
index 97f784dd6179e20d49fb7f699e0ed2fc6cdf3bc9..ee646dc91743b8c09838b9a197c6ba4f16286b2f 100644 (file)
@@ -329,9 +329,13 @@ fn path_all(&self,
             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.
index 7a4329304907f2759571b5fdadbdaea8867c690a..ca879765b4efcc5780baa8727aa31888fa9a1e02 100644 (file)
@@ -5869,7 +5869,7 @@ pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibili
                 // `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 @@ pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibili
             {
                 // `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 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
 
         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 @@ fn is_import_coupler_inner(&mut self, token: &token::Token, unprefixed: bool) ->
     ///            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 @@ fn parse_use_tree(&mut self, nested: bool) -> PResult<'a, UseTree> {
             // 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 @@ fn parse_use_tree(&mut self, nested: bool) -> PResult<'a, UseTree> {
         } 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 @@ fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> {
         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))
         })
     }
 
index 097a2eb89fdf4d7d8eca68764e9e1977fceb28dc..3c602f1d1a800c07b476ebb4c43d67c6577cccbf 100644 (file)
@@ -362,6 +362,7 @@ pub fn is_path_segment_keyword(&self) -> bool {
                         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,
         }
index 18a758ba96846480d472dc76215580c266853313..319a9a3bbaebccfea550f90ccd076fa1a560d714 100644 (file)
@@ -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 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
                                  &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 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 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 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
     }
 
     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 @@ pub fn print_visibility(&mut self, vis: &ast::Visibility) -> io::Result<()> {
                 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 @@ pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
             }
             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 @@ pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> {
             }
             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 @@ pub fn print_if_let(&mut self, pats: &[P<ast::Pat>], expr: &ast::Expr, blk: &ast
 
     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 @@ fn print_expr_struct(&mut self,
                          fields: &[ast::Field],
                          wth: &Option<P<ast::Expr>>,
                          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 @@ fn print_expr_outer_attr_style(&mut self,
                 }
             }
             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 @@ pub fn print_for_decl(&mut self, loc: &ast::Local,
     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 @@ fn print_qpath(&mut self,
             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 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
                 }
             }
             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 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
                 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 @@ pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause)
     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 @@ pub fn print_use_tree(&mut self, tree: &ast::UseTree) -> io::Result<()> {
             }
             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 @@ pub fn print_use_tree(&mut self, tree: &ast::UseTree) -> io::Result<()> {
                 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, _)| {
index 59425929f7ed0533aab57bd3d0bfa622cb7c97cc..401183e7c7d5e17d14db4b3d7b61b3412636d2e2 100644 (file)
@@ -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,