about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-12-05 03:51:11 +0000
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-12-22 06:14:35 +0000
commitf10f50b42639718b2580d10802f05f2b6ff209d5 (patch)
tree19b61435b37e14f97a74e18b6db32c507e7b1a58 /src/libsyntax
parent164619a8cfe6d376d25bd3a6a9a5f2856c8de64d (diff)
downloadrust-f10f50b42639718b2580d10802f05f2b6ff209d5.tar.gz
rust-f10f50b42639718b2580d10802f05f2b6ff209d5.zip
Refactor how global paths are represented (for both ast and hir).
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs27
-rw-r--r--src/libsyntax/ext/build.rs8
-rw-r--r--src/libsyntax/ext/placeholders.rs2
-rw-r--r--src/libsyntax/fold.rs3
-rw-r--r--src/libsyntax/parse/mod.rs10
-rw-r--r--src/libsyntax/parse/parser.rs16
-rw-r--r--src/libsyntax/print/pprust.rs67
-rw-r--r--src/libsyntax/std_inject.rs3
-rw-r--r--src/libsyntax/symbol.rs3
-rw-r--r--src/libsyntax/test.rs1
10 files changed, 83 insertions, 57 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index fdd82225b97..648a82ffb76 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -111,10 +111,8 @@ pub struct LifetimeDef {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
 pub struct Path {
     pub span: Span,
-    /// A `::foo` path, is relative to the crate root rather than current
-    /// module (like paths in an import).
-    pub global: bool,
     /// The segments in the path: the things separated by `::`.
+    /// Global paths begin with `keywords::CrateRoot`.
     pub segments: Vec<PathSegment>,
 }
 
@@ -136,10 +134,22 @@ impl Path {
     pub fn from_ident(s: Span, identifier: Ident) -> Path {
         Path {
             span: s,
-            global: false,
             segments: vec![identifier.into()],
         }
     }
+
+    pub fn default_to_global(mut self) -> Path {
+        let name = self.segments[0].identifier.name;
+        if !self.is_global() && name != "$crate" &&
+           name != keywords::SelfValue.name() && name != keywords::Super.name() {
+            self.segments.insert(0, PathSegment::crate_root());
+        }
+        self
+    }
+
+    pub fn is_global(&self) -> bool {
+        !self.segments.is_empty() && self.segments[0].identifier.name == keywords::CrateRoot.name()
+    }
 }
 
 /// A segment of a path: an identifier, an optional lifetime, and a set of types.
@@ -166,6 +176,15 @@ impl From<Ident> for PathSegment {
     }
 }
 
+impl PathSegment {
+    pub fn crate_root() -> Self {
+        PathSegment {
+            identifier: keywords::CrateRoot.ident(),
+            parameters: None,
+        }
+    }
+}
+
 /// Parameters of a path segment.
 ///
 /// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index c3dc64f9124..7584fa3916d 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -322,7 +322,12 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                 bindings: Vec<ast::TypeBinding> )
                 -> ast::Path {
         let last_identifier = idents.pop().unwrap();
-        let mut segments: Vec<ast::PathSegment> = idents.into_iter().map(Into::into).collect();
+        let mut segments: Vec<ast::PathSegment> = Vec::new();
+        if global {
+            segments.push(ast::PathSegment::crate_root());
+        }
+
+        segments.extend(idents.into_iter().map(Into::into));
         let parameters = if lifetimes.is_empty() && types.is_empty() && bindings.is_empty() {
             None
         } else {
@@ -335,7 +340,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         segments.push(ast::PathSegment { identifier: last_identifier, parameters: parameters });
         ast::Path {
             span: sp,
-            global: global,
             segments: segments,
         }
     }
diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs
index eb4b6144c8d..66555d7d95d 100644
--- a/src/libsyntax/ext/placeholders.rs
+++ b/src/libsyntax/ext/placeholders.rs
@@ -25,7 +25,7 @@ use std::mem;
 pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion {
     fn mac_placeholder() -> ast::Mac {
         dummy_spanned(ast::Mac_ {
-            path: ast::Path { span: DUMMY_SP, global: false, segments: Vec::new() },
+            path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
             tts: Vec::new(),
         })
     }
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index b3753e3e977..bf10d45add4 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -433,9 +433,8 @@ pub fn noop_fold_usize<T: Folder>(i: usize, _: &mut T) -> usize {
     i
 }
 
-pub fn noop_fold_path<T: Folder>(Path {global, segments, span}: Path, fld: &mut T) -> Path {
+pub fn noop_fold_path<T: Folder>(Path { segments, span }: Path, fld: &mut T) -> Path {
     Path {
-        global: global,
         segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment {
             identifier: fld.fold_ident(identifier),
             parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))),
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index b9e6605639e..24178e1f675 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -633,7 +633,6 @@ mod tests {
                     id: ast::DUMMY_NODE_ID,
                     node: ast::ExprKind::Path(None, ast::Path {
                         span: sp(0, 1),
-                        global: false,
                         segments: vec![Ident::from_str("a").into()],
                     }),
                     span: sp(0, 1),
@@ -647,8 +646,9 @@ mod tests {
                     id: ast::DUMMY_NODE_ID,
                     node: ast::ExprKind::Path(None, ast::Path {
                         span: sp(0, 6),
-                        global: true,
-                        segments: vec![Ident::from_str("a").into(), Ident::from_str("b").into()],
+                        segments: vec![ast::PathSegment::crate_root(),
+                                       Ident::from_str("a").into(),
+                                       Ident::from_str("b").into()]
                     }),
                     span: sp(0, 6),
                     attrs: ThinVec::new(),
@@ -757,7 +757,6 @@ mod tests {
                         id: ast::DUMMY_NODE_ID,
                         node:ast::ExprKind::Path(None, ast::Path{
                             span: sp(7, 8),
-                            global: false,
                             segments: vec![Ident::from_str("d").into()],
                         }),
                         span:sp(7,8),
@@ -775,7 +774,6 @@ mod tests {
                            id: ast::DUMMY_NODE_ID,
                            node: ast::ExprKind::Path(None, ast::Path {
                                span:sp(0,1),
-                               global:false,
                                segments: vec![Ident::from_str("b").into()],
                             }),
                            span: sp(0,1),
@@ -817,7 +815,6 @@ mod tests {
                                     ty: P(ast::Ty{id: ast::DUMMY_NODE_ID,
                                                   node: ast::TyKind::Path(None, ast::Path{
                                         span:sp(10,13),
-                                        global:false,
                                         segments: vec![Ident::from_str("i32").into()],
                                         }),
                                         span:sp(10,13)
@@ -860,7 +857,6 @@ mod tests {
                                                 node: ast::ExprKind::Path(None,
                                                       ast::Path{
                                                         span:sp(17,18),
-                                                        global:false,
                                                         segments: vec![Ident::from_str("b").into()],
                                                       }),
                                                 span: sp(17,18),
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 72462b74e68..cd4f255b5e3 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1614,7 +1614,6 @@ impl<'a> Parser<'a> {
         } else {
             ast::Path {
                 span: span,
-                global: false,
                 segments: vec![]
             }
         };
@@ -1658,7 +1657,7 @@ impl<'a> Parser<'a> {
         // Parse any number of segments and bound sets. A segment is an
         // identifier followed by an optional lifetime and a set of types.
         // A bound set is a set of type parameter bounds.
-        let segments = match mode {
+        let mut segments = match mode {
             PathStyle::Type => {
                 self.parse_path_segments_without_colons()?
             }
@@ -1670,13 +1669,16 @@ impl<'a> Parser<'a> {
             }
         };
 
+        if is_global {
+            segments.insert(0, ast::PathSegment::crate_root());
+        }
+
         // Assemble the span.
         let span = mk_sp(lo, self.prev_span.hi);
 
         // Assemble the result.
         Ok(ast::Path {
             span: span,
-            global: is_global,
             segments: segments,
         })
     }
@@ -5180,7 +5182,7 @@ impl<'a> Parser<'a> {
         } else if self.eat_keyword(keywords::Crate) {
             pub_crate(self)
         } else {
-            let path = self.parse_path(PathStyle::Mod)?;
+            let path = self.parse_path(PathStyle::Mod)?.default_to_global();
             self.expect(&token::CloseDelim(token::Paren))?;
             Ok(Visibility::Restricted { path: P(path), id: ast::DUMMY_NODE_ID })
         }
@@ -6068,9 +6070,9 @@ impl<'a> Parser<'a> {
         if self.check(&token::OpenDelim(token::Brace)) || self.check(&token::BinOp(token::Star)) ||
            self.is_import_coupler() {
             // `{foo, bar}`, `::{foo, bar}`, `*`, or `::*`.
+            self.eat(&token::ModSep);
             let prefix = ast::Path {
-                global: self.eat(&token::ModSep),
-                segments: Vec::new(),
+                segments: vec![ast::PathSegment::crate_root()],
                 span: mk_sp(lo, self.span.hi),
             };
             let view_path_kind = if self.eat(&token::BinOp(token::Star)) {
@@ -6080,7 +6082,7 @@ impl<'a> Parser<'a> {
             };
             Ok(P(spanned(lo, self.span.hi, view_path_kind)))
         } else {
-            let prefix = self.parse_path(PathStyle::Mod)?;
+            let prefix = self.parse_path(PathStyle::Mod)?.default_to_global();
             if self.is_import_coupler() {
                 // `foo::bar::{a, b}` or `foo::bar::*`
                 self.bump();
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 22e8391de93..e9c1cbcba61 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -371,7 +371,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))
+    to_string(|s| s.print_path(p, false, 0, false))
 }
 
 pub fn ident_to_string(id: ast::Ident) -> String {
@@ -435,7 +435,8 @@ pub fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String {
     match *vis {
         ast::Visibility::Public => format!("pub {}", s),
         ast::Visibility::Crate(_) => format!("pub(crate) {}", s),
-        ast::Visibility::Restricted { ref path, .. } => format!("pub({}) {}", path, s),
+        ast::Visibility::Restricted { ref path, .. } =>
+            format!("pub({}) {}", to_string(|s| s.print_path(path, false, 0, true)), s),
         ast::Visibility::Inherited => s.to_string()
     }
 }
@@ -1021,7 +1022,7 @@ impl<'a> State<'a> {
                                  &generics));
             }
             ast::TyKind::Path(None, ref path) => {
-                try!(self.print_path(path, false, 0));
+                try!(self.print_path(path, false, 0, false));
             }
             ast::TyKind::Path(Some(ref qself), ref path) => {
                 try!(self.print_qpath(path, qself, false))
@@ -1332,7 +1333,7 @@ impl<'a> State<'a> {
             }
             ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => {
                 try!(self.print_visibility(&item.vis));
-                try!(self.print_path(&node.path, false, 0));
+                try!(self.print_path(&node.path, false, 0, false));
                 try!(word(&mut self.s, "! "));
                 try!(self.print_ident(item.ident));
                 try!(self.cbox(INDENT_UNIT));
@@ -1347,7 +1348,7 @@ impl<'a> State<'a> {
     }
 
     fn print_trait_ref(&mut self, t: &ast::TraitRef) -> io::Result<()> {
-        self.print_path(&t.path, false, 0)
+        self.print_path(&t.path, false, 0, false)
     }
 
     fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> io::Result<()> {
@@ -1405,8 +1406,10 @@ impl<'a> State<'a> {
         match *vis {
             ast::Visibility::Public => self.word_nbsp("pub"),
             ast::Visibility::Crate(_) => self.word_nbsp("pub(crate)"),
-            ast::Visibility::Restricted { ref path, .. } =>
-                self.word_nbsp(&format!("pub({})", path)),
+            ast::Visibility::Restricted { ref path, .. } => {
+                let path = to_string(|s| s.print_path(path, false, 0, true));
+                self.word_nbsp(&format!("pub({})", path))
+            }
             ast::Visibility::Inherited => Ok(())
         }
     }
@@ -1571,7 +1574,7 @@ impl<'a> State<'a> {
             }
             ast::TraitItemKind::Macro(codemap::Spanned { ref node, .. }) => {
                 // code copied from ItemKind::Mac:
-                self.print_path(&node.path, false, 0)?;
+                self.print_path(&node.path, false, 0, false)?;
                 word(&mut self.s, "! ")?;
                 self.cbox(INDENT_UNIT)?;
                 self.popen()?;
@@ -1607,7 +1610,7 @@ impl<'a> State<'a> {
             }
             ast::ImplItemKind::Macro(codemap::Spanned { ref node, .. }) => {
                 // code copied from ItemKind::Mac:
-                try!(self.print_path(&node.path, false, 0));
+                try!(self.print_path(&node.path, false, 0, false));
                 try!(word(&mut self.s, "! "));
                 try!(self.cbox(INDENT_UNIT));
                 try!(self.popen());
@@ -1793,7 +1796,7 @@ impl<'a> State<'a> {
 
     pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken)
                      -> io::Result<()> {
-        try!(self.print_path(&m.node.path, false, 0));
+        try!(self.print_path(&m.node.path, false, 0, false));
         try!(word(&mut self.s, "!"));
         match delim {
             token::Paren => try!(self.popen()),
@@ -1885,7 +1888,7 @@ impl<'a> State<'a> {
                          fields: &[ast::Field],
                          wth: &Option<P<ast::Expr>>,
                          attrs: &[Attribute]) -> io::Result<()> {
-        try!(self.print_path(path, true, 0));
+        try!(self.print_path(path, true, 0, false));
         try!(word(&mut self.s, "{"));
         try!(self.print_inner_attributes_inline(attrs));
         try!(self.commasep_cmnt(
@@ -2186,7 +2189,7 @@ impl<'a> State<'a> {
                 }
             }
             ast::ExprKind::Path(None, ref path) => {
-                try!(self.print_path(path, true, 0))
+                try!(self.print_path(path, true, 0, false))
             }
             ast::ExprKind::Path(Some(ref qself), ref path) => {
                 try!(self.print_qpath(path, qself, true))
@@ -2334,23 +2337,25 @@ impl<'a> State<'a> {
     fn print_path(&mut self,
                   path: &ast::Path,
                   colons_before_params: bool,
-                  depth: usize)
+                  depth: usize,
+                  defaults_to_global: bool)
                   -> io::Result<()>
     {
         try!(self.maybe_print_comment(path.span.lo));
 
-        let mut first = !path.global;
-        for segment in &path.segments[..path.segments.len()-depth] {
-            if first {
-                first = false
-            } else {
+        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() {
+            if i > 0 {
                 try!(word(&mut self.s, "::"))
             }
-
-            try!(self.print_ident(segment.identifier));
-
-            if let Some(ref parameters) = segment.parameters {
-                try!(self.print_path_parameters(parameters, colons_before_params))
+            if segment.identifier.name != keywords::CrateRoot.name() {
+                try!(self.print_ident(segment.identifier));
+                if let Some(ref parameters) = segment.parameters {
+                    try!(self.print_path_parameters(parameters, colons_before_params));
+                }
             }
         }
 
@@ -2369,7 +2374,7 @@ impl<'a> State<'a> {
             try!(space(&mut self.s));
             try!(self.word_space("as"));
             let depth = path.segments.len() - qself.position;
-            try!(self.print_path(&path, false, depth));
+            try!(self.print_path(&path, false, depth, false));
         }
         try!(word(&mut self.s, ">"));
         try!(word(&mut self.s, "::"));
@@ -2472,7 +2477,7 @@ impl<'a> State<'a> {
                 }
             }
             PatKind::TupleStruct(ref path, ref elts, ddpos) => {
-                try!(self.print_path(path, true, 0));
+                try!(self.print_path(path, true, 0, false));
                 try!(self.popen());
                 if let Some(ddpos) = ddpos {
                     try!(self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p)));
@@ -2490,13 +2495,13 @@ impl<'a> State<'a> {
                 try!(self.pclose());
             }
             PatKind::Path(None, ref path) => {
-                try!(self.print_path(path, true, 0));
+                try!(self.print_path(path, true, 0, false));
             }
             PatKind::Path(Some(ref qself), ref path) => {
                 try!(self.print_qpath(path, qself, false));
             }
             PatKind::Struct(ref path, ref fields, etc) => {
-                try!(self.print_path(path, true, 0));
+                try!(self.print_path(path, true, 0, false));
                 try!(self.nbsp());
                 try!(self.word_space("{"));
                 try!(self.commasep_cmnt(
@@ -2843,7 +2848,7 @@ impl<'a> State<'a> {
                     try!(self.print_lifetime_bounds(lifetime, bounds));
                 }
                 ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
-                    try!(self.print_path(path, false, 0));
+                    try!(self.print_path(path, false, 0, false));
                     try!(space(&mut self.s));
                     try!(self.word_space("="));
                     try!(self.print_type(&ty));
@@ -2857,7 +2862,7 @@ impl<'a> State<'a> {
     pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> io::Result<()> {
         match vp.node {
             ast::ViewPathSimple(ident, ref path) => {
-                try!(self.print_path(path, false, 0));
+                try!(self.print_path(path, false, 0, true));
 
                 if path.segments.last().unwrap().identifier.name !=
                         ident.name {
@@ -2870,7 +2875,7 @@ impl<'a> State<'a> {
             }
 
             ast::ViewPathGlob(ref path) => {
-                try!(self.print_path(path, false, 0));
+                try!(self.print_path(path, false, 0, true));
                 word(&mut self.s, "::*")
             }
 
@@ -2878,7 +2883,7 @@ impl<'a> State<'a> {
                 if path.segments.is_empty() {
                     try!(word(&mut self.s, "{"));
                 } else {
-                    try!(self.print_path(path, false, 0));
+                    try!(self.print_path(path, false, 0, true));
                     try!(word(&mut self.s, "::{"));
                 }
                 try!(self.commasep(Inconsistent, &idents[..], |s, w| {
diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs
index 4ad760a3caf..68d807b24a7 100644
--- a/src/libsyntax/std_inject.rs
+++ b/src/libsyntax/std_inject.rs
@@ -80,8 +80,7 @@ pub fn maybe_inject_crates_ref(sess: &ParseSess,
         }],
         vis: ast::Visibility::Inherited,
         node: ast::ItemKind::Use(P(codemap::dummy_spanned(ast::ViewPathGlob(ast::Path {
-            global: false,
-            segments: vec![name, "prelude", "v1"].into_iter().map(|name| {
+            segments: ["{{root}}", name, "prelude", "v1"].into_iter().map(|name| {
                 ast::Ident::from_str(name).into()
             }).collect(),
             span: span,
diff --git a/src/libsyntax/symbol.rs b/src/libsyntax/symbol.rs
index fe9a176179c..c2123ea5a07 100644
--- a/src/libsyntax/symbol.rs
+++ b/src/libsyntax/symbol.rs
@@ -221,6 +221,9 @@ declare_keywords! {
     (53, Default,        "default")
     (54, StaticLifetime, "'static")
     (55, Union,          "union")
+
+    // A virtual keyword that resolves to the crate root when used in a lexical scope.
+    (56, CrateRoot, "{{root}}")
 }
 
 // If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index 7709d3bd1cf..b8e0b938814 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -579,7 +579,6 @@ fn nospan<T>(t: T) -> codemap::Spanned<T> {
 fn path_node(ids: Vec<Ident>) -> ast::Path {
     ast::Path {
         span: DUMMY_SP,
-        global: false,
         segments: ids.into_iter().map(Into::into).collect(),
     }
 }