]> git.lizzy.rs Git - rust.git/commitdiff
Refactor how global paths are represented (for both ast and hir).
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Mon, 5 Dec 2016 03:51:11 +0000 (03:51 +0000)
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Thu, 22 Dec 2016 06:14:35 +0000 (06:14 +0000)
27 files changed:
src/librustc/hir/lowering.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/infer/error_reporting.rs
src/librustc_const_eval/_match.rs
src/librustc_incremental/calculate_svh/svh_visitor.rs
src/librustc_lint/bad_style.rs
src/librustc_passes/ast_validation.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustdoc/clean/mod.rs
src/libsyntax/ast.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/placeholders.rs
src/libsyntax/fold.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/std_inject.rs
src/libsyntax/symbol.rs
src/libsyntax/test.rs
src/libsyntax_ext/concat_idents.rs
src/libsyntax_ext/deriving/generic/mod.rs
src/test/compile-fail/resolve-primitive-fallback.rs

index e8c3492705a3f95da1e4886b661479e9748a27c6..1cf5e35a0957fa4341a1f148bf101cef36d9e584 100644 (file)
@@ -81,7 +81,7 @@ pub struct LoweringContext<'a> {
 }
 
 pub trait Resolver {
-    // Resolve a global hir path generated by the lowerer when expanding `for`, `if let`, etc.
+    // Resolve a hir path generated by the lowerer when expanding `for`, `if let`, etc.
     fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool);
 
     // Obtain the resolution for a node id
@@ -337,7 +337,6 @@ fn lower_qpath(&mut self,
 
         let proj_start = p.segments.len() - resolution.depth;
         let path = P(hir::Path {
-            global: p.global,
             def: resolution.base_def,
             segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| {
                 let param_mode = match (qself_position, param_mode) {
@@ -404,12 +403,17 @@ fn lower_path_extra(&mut self,
                         id: NodeId,
                         p: &Path,
                         name: Option<Name>,
-                        param_mode: ParamMode)
+                        param_mode: ParamMode,
+                        defaults_to_global: bool)
                         -> hir::Path {
+        let mut segments = p.segments.iter();
+        if defaults_to_global && p.is_global() {
+            segments.next();
+        }
+
         hir::Path {
-            global: p.global,
             def: self.expect_full_def(id),
-            segments: p.segments.iter().map(|segment| {
+            segments: segments.map(|segment| {
                 self.lower_path_segment(segment, param_mode)
             }).chain(name.map(|name| {
                 hir::PathSegment {
@@ -424,9 +428,10 @@ fn lower_path_extra(&mut self,
     fn lower_path(&mut self,
                   id: NodeId,
                   p: &Path,
-                  param_mode: ParamMode)
+                  param_mode: ParamMode,
+                  defaults_to_global: bool)
                   -> hir::Path {
-        self.lower_path_extra(id, p, None, param_mode)
+        self.lower_path_extra(id, p, None, param_mode, defaults_to_global)
     }
 
     fn lower_path_segment(&mut self,
@@ -602,8 +607,8 @@ fn lower_generics(&mut self, g: &Generics) -> hir::Generics {
                         // Check if the where clause type is a plain type parameter.
                         match bound_pred.bounded_ty.node {
                             TyKind::Path(None, ref path)
-                                    if !path.global && path.segments.len() == 1 &&
-                                        bound_pred.bound_lifetimes.is_empty() => {
+                                    if path.segments.len() == 1 &&
+                                       bound_pred.bound_lifetimes.is_empty() => {
                                 if let Some(Def::TyParam(def_id)) =
                                         self.resolver.get_resolution(bound_pred.bounded_ty.id)
                                                      .map(|d| d.base_def) {
@@ -677,7 +682,7 @@ fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicat
                                                           span}) => {
                 hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
                     id: id,
-                    path: self.lower_path(id, path, ParamMode::Explicit),
+                    path: self.lower_path(id, path, ParamMode::Explicit, false),
                     ty: self.lower_ty(ty),
                     span: span,
                 })
@@ -707,7 +712,7 @@ fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
 
     fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef {
         hir::TraitRef {
-            path: self.lower_path(p.ref_id, &p.path, ParamMode::Explicit),
+            path: self.lower_path(p.ref_id, &p.path, ParamMode::Explicit, false),
             ref_id: p.ref_id,
         }
     }
@@ -800,7 +805,7 @@ fn lower_item_kind(&mut self,
                             };
 
                             let mut path = self.lower_path_extra(import.id, path, suffix,
-                                                                 ParamMode::Explicit);
+                                                                 ParamMode::Explicit, true);
                             path.span = span;
                             self.items.insert(import.id, hir::Item {
                                 id: import.id,
@@ -814,7 +819,7 @@ fn lower_item_kind(&mut self,
                         path
                     }
                 };
-                let path = P(self.lower_path(id, path, ParamMode::Explicit));
+                let path = P(self.lower_path(id, path, ParamMode::Explicit, true));
                 let kind = match view_path.node {
                     ViewPathSimple(ident, _) => {
                         *name = ident.name;
@@ -1135,7 +1140,6 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                             Some(def) => {
                                 hir::PatKind::Path(hir::QPath::Resolved(None, P(hir::Path {
                                     span: pth1.span,
-                                    global: false,
                                     def: def,
                                     segments: hir_vec![
                                         hir::PathSegment::from_name(pth1.node.name)
@@ -1878,7 +1882,7 @@ fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility {
             Visibility::Crate(_) => hir::Visibility::Crate,
             Visibility::Restricted { ref path, id } => {
                 hir::Visibility::Restricted {
-                    path: P(self.lower_path(id, path, ParamMode::Explicit)),
+                    path: P(self.lower_path(id, path, ParamMode::Explicit, true)),
                     id: id
                 }
             }
@@ -1971,7 +1975,6 @@ fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> hir::Expr {
 
         let expr_path = hir::ExprPath(hir::QPath::Resolved(None, P(hir::Path {
             span: span,
-            global: false,
             def: def,
             segments: hir_vec![hir::PathSegment::from_name(id)],
         })));
@@ -2139,17 +2142,12 @@ fn pat(&mut self, span: Span, pat: hir::PatKind) -> P<hir::Pat> {
     /// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
     /// The path is also resolved according to `is_value`.
     fn std_path(&mut self, span: Span, components: &[&str], is_value: bool) -> hir::Path {
-        let idents = self.crate_root.iter().chain(components);
-
-        let segments: Vec<_> = idents.map(|name| {
-            hir::PathSegment::from_name(Symbol::intern(name))
-        }).collect();
-
         let mut path = hir::Path {
             span: span,
-            global: true,
             def: Def::Err,
-            segments: segments.into(),
+            segments: iter::once(keywords::CrateRoot.name()).chain({
+                self.crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern)
+            }).map(hir::PathSegment::from_name).collect(),
         };
 
         self.resolver.resolve_hir_path(&mut path, is_value);
index f52ee35e1757306ae0605e1dd774db9d770398b4..a0039f612b985be5861c3f1a25f9c59d5986ffe0 100644 (file)
@@ -105,15 +105,18 @@ 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 definition that the path resolved to.
     pub def: Def,
     /// The segments in the path: the things separated by `::`.
     pub segments: HirVec<PathSegment>,
 }
 
+impl Path {
+    pub fn is_global(&self) -> bool {
+        !self.segments.is_empty() && self.segments[0].name == keywords::CrateRoot.name()
+    }
+}
+
 impl fmt::Debug for Path {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "path({})", print::path_to_string(self))
index 74920b1328076d392dd9212fe903cd8ea0e80993..de4047df81c5d6b60f428eb3bddfe519f207a13b 100644 (file)
@@ -1643,17 +1643,14 @@ fn print_path(&mut self,
                   -> io::Result<()> {
         self.maybe_print_comment(path.span.lo)?;
 
-        let mut first = !path.global;
-        for segment in &path.segments {
-            if first {
-                first = false
-            } else {
+        for (i, segment) in path.segments.iter().enumerate() {
+            if i > 0 {
                 word(&mut self.s, "::")?
             }
-
-            self.print_name(segment.name)?;
-
-            self.print_path_parameters(&segment.parameters, colons_before_params)?;
+            if segment.name != keywords::CrateRoot.name() {
+                self.print_name(segment.name)?;
+                self.print_path_parameters(&segment.parameters, colons_before_params)?;
+            }
         }
 
         Ok(())
@@ -1673,15 +1670,14 @@ fn print_qpath(&mut self,
                 space(&mut self.s)?;
                 self.word_space("as")?;
 
-                let mut first = !path.global;
-                for segment in &path.segments[..path.segments.len() - 1] {
-                    if first {
-                        first = false
-                    } else {
+                for (i, segment) in path.segments[..path.segments.len() - 1].iter().enumerate() {
+                    if i > 0 {
                         word(&mut self.s, "::")?
                     }
-                    self.print_name(segment.name)?;
-                    self.print_path_parameters(&segment.parameters, colons_before_params)?;
+                    if segment.name != keywords::CrateRoot.name() {
+                        self.print_name(segment.name)?;
+                        self.print_path_parameters(&segment.parameters, colons_before_params)?;
+                    }
                 }
 
                 word(&mut self.s, ">")?;
index 90d752ae6ee297db8100658c6e236c59739d0b4c..9d48fbca53edd9ddf11c8af56286e87fd8bc9ed1 100644 (file)
@@ -1620,7 +1620,6 @@ fn rebuild_path(&self,
         new_segs.push(new_seg);
         hir::Path {
             span: path.span,
-            global: path.global,
             def: path.def,
             segments: new_segs.into()
         }
index 23771f4bae3dc109cb81e6b0383443c421f344ba..ebe103490110436e6712fbf3b86b52805cf655c8 100644 (file)
@@ -324,7 +324,6 @@ fn apply_constructor<'a, 'tcx>(
                     let v = ctor.variant_for_adt(adt);
                     let qpath = hir::QPath::Resolved(None, P(hir::Path {
                         span: DUMMY_SP,
-                        global: false,
                         def: Def::Err,
                         segments: vec![hir::PathSegment::from_name(v.name)].into(),
                     }));
index ec44e19df10c999518d873199520d035632cfab3..bd865d10efcafb329f93380b44ada97b1076ca6d 100644 (file)
@@ -189,7 +189,6 @@ enum SawAbiComponent<'a> {
     SawStructField,
     SawVariant,
     SawQPath,
-    SawPath(bool),
     SawPathSegment,
     SawPathParameters,
     SawBlock,
@@ -678,7 +677,6 @@ fn visit_qpath(&mut self, qpath: &'tcx QPath, id: NodeId, span: Span) {
 
     fn visit_path(&mut self, path: &'tcx Path, _: ast::NodeId) {
         debug!("visit_path: st={:?}", self.st);
-        SawPath(path.global).hash(self.st);
         hash_span!(self, path.span);
         visit::walk_path(self, path)
     }
index 2aa74407afc5b087fe64c4804f1e0b279b4e3e1d..1d384741d9660b974ed3e53643229dbdc3581a18 100644 (file)
@@ -382,7 +382,7 @@ fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) {
     fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
         // Lint for constants that look like binding identifiers (#7526)
         if let PatKind::Path(hir::QPath::Resolved(None, ref path)) = p.node {
-            if !path.global && path.segments.len() == 1 && path.segments[0].parameters.is_empty() {
+            if path.segments.len() == 1 && path.segments[0].parameters.is_empty() {
                 if let Def::Const(..) = path.def {
                     NonUpperCaseGlobals::check_upper_case(cx,
                                                           "constant in pattern",
index bc150b847786f2c08531e847d08061b2f9600d3d..52bdd014933b8d6438949a179e1afe5cbe041d7a 100644 (file)
@@ -154,8 +154,8 @@ fn visit_ty(&mut self, ty: &'a Ty) {
     }
 
     fn visit_path(&mut self, path: &'a Path, id: NodeId) {
-        if path.global && path.segments.len() > 0 {
-            let ident = path.segments[0].identifier;
+        if path.segments.len() >= 2 && path.is_global() {
+            let ident = path.segments[1].identifier;
             if token::Ident(ident).is_path_segment_keyword() {
                 self.session.add_lint(lint::builtin::SUPER_OR_SELF_IN_GLOBAL_PATH,
                                       id,
index cd2a2767979144fdcb3272a5205ef71128f8d196..09f438953ecd2badfc7cae2f4e8c2ebab5fd92e3 100644 (file)
@@ -40,6 +40,7 @@
 use syntax::ext::expand::mark_tts;
 use syntax::ext::hygiene::Mark;
 use syntax::ext::tt::macro_rules;
+use syntax::parse::token;
 use syntax::symbol::keywords;
 use syntax::visit::{self, Visitor};
 
@@ -112,7 +113,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                 // Extract and intern the module part of the path. For
                 // globs and lists, the path is found directly in the AST;
                 // for simple paths we have to munge the path a little.
-                let module_path: Vec<_> = match view_path.node {
+                let mut module_path: Vec<_> = match view_path.node {
                     ViewPathSimple(_, ref full_path) => {
                         full_path.segments
                                  .split_last()
@@ -132,6 +133,12 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                     }
                 };
 
+                // This can be removed once warning cycle #36888 is complete.
+                if module_path.len() >= 2 && module_path[0].name == keywords::CrateRoot.name() &&
+                   token::Ident(module_path[1]).is_path_segment_keyword() {
+                    module_path.remove(0);
+                }
+
                 // Build up the import directives.
                 let is_prelude = attr::contains_name(&item.attrs, "prelude_import");
 
@@ -193,18 +200,16 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                                     let rename = node.rename.unwrap_or(node.name);
                                     (module_path.clone(), node.name, rename)
                                 } else {
-                                    let ident = match module_path.last() {
-                                        Some(&ident) => ident,
-                                        None => {
-                                            resolve_error(
-                                                self,
-                                                source_item.span,
-                                                ResolutionError::
-                                                SelfImportOnlyInImportListWithNonEmptyPrefix
-                                            );
-                                            continue;
-                                        }
-                                    };
+                                    let ident = *module_path.last().unwrap();
+                                    if ident.name == keywords::CrateRoot.name() {
+                                        resolve_error(
+                                            self,
+                                            source_item.span,
+                                            ResolutionError::
+                                            SelfImportOnlyInImportListWithNonEmptyPrefix
+                                        );
+                                        continue;
+                                    }
                                     let module_path = module_path.split_last().unwrap().1;
                                     let rename = node.rename.unwrap_or(ident);
                                     (module_path.to_vec(), ident, rename)
index f73227681c5e159a1ace316489174e15ac233d27..7f91576f6d68f60a1c4eb1b742fcf5e1e101236c 100644 (file)
@@ -578,9 +578,9 @@ fn visit_ty(&mut self, ty: &'tcx Ty) {
     fn visit_poly_trait_ref(&mut self,
                             tref: &'tcx ast::PolyTraitRef,
                             m: &'tcx ast::TraitBoundModifier) {
-        let ast::Path { ref segments, span, global } = tref.trait_ref.path;
+        let ast::Path { ref segments, span } = tref.trait_ref.path;
         let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
-        let def = self.resolve_trait_reference(&path, global, None, span);
+        let def = self.resolve_trait_reference(&path, None, span);
         self.record_def(tref.trait_ref.ref_id, def);
         visit::walk_poly_trait_ref(self, tref, m);
     }
@@ -753,13 +753,6 @@ fn item(self) -> Option<&'a NameBinding<'a>> {
     }
 }
 
-#[derive(Copy, Clone, PartialEq)]
-enum PathScope {
-    Global,
-    Lexical,
-    Import,
-}
-
 #[derive(Clone)]
 enum PathResult<'a> {
     Module(Module<'a>),
@@ -783,7 +776,7 @@ pub struct ModuleData<'a> {
 
     resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
     legacy_macro_resolutions: RefCell<Vec<(Mark, Ident, Span)>>,
-    macro_resolutions: RefCell<Vec<(Box<[Ident]>, PathScope, Span)>>,
+    macro_resolutions: RefCell<Vec<(Box<[Ident]>, Span)>>,
 
     // Macro invocations that can expand into items in this module.
     unresolved_invocations: RefCell<FxHashSet<Mark>>,
@@ -1174,13 +1167,12 @@ fn is_descendant_of(&self, mut node: NodeId, ancestor: NodeId) -> bool {
 impl<'a> hir::lowering::Resolver for Resolver<'a> {
     fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) {
         let namespace = if is_value { ValueNS } else { TypeNS };
-        let hir::Path { ref segments, span, global, ref mut def } = *path;
+        let hir::Path { ref segments, span, ref mut def } = *path;
         let path: Vec<_> = segments.iter().map(|seg| Ident::with_empty_ctxt(seg.name)).collect();
-        let scope = if global { PathScope::Global } else { PathScope::Lexical };
-        match self.resolve_path(&path, scope, Some(namespace), Some(span)) {
+        match self.resolve_path(&path, Some(namespace), Some(span)) {
             PathResult::Module(module) => *def = module.def().unwrap(),
             PathResult::NonModule(path_res) if path_res.depth == 0 => *def = path_res.base_def,
-            PathResult::NonModule(..) => match self.resolve_path(&path, scope, None, Some(span)) {
+            PathResult::NonModule(..) => match self.resolve_path(&path, None, Some(span)) {
                 PathResult::Failed(msg, _) => {
                     resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
                 }
@@ -1601,17 +1593,16 @@ fn resolve_item(&mut self, item: &Item) {
                             prefix.segments.iter().map(|seg| seg.identifier).collect();
                         // Resolve prefix of an import with empty braces (issue #28388)
                         if items.is_empty() && !prefix.segments.is_empty() {
-                            let (scope, span) = (PathScope::Import, prefix.span);
+                            let span = prefix.span;
                             // FIXME(#38012) This should be a module path, not anything in TypeNS.
-                            let result =
-                                self.resolve_path(&path, scope, Some(TypeNS), Some(span));
+                            let result = self.resolve_path(&path, Some(TypeNS), Some(span));
                             let (def, msg) = match result {
                                 PathResult::Module(module) => (module.def().unwrap(), None),
                                 PathResult::NonModule(res) if res.depth == 0 =>
                                     (res.base_def, None),
                                 PathResult::NonModule(_) => {
                                     // Resolve a module path for better errors
-                                    match self.resolve_path(&path, scope, None, Some(span)) {
+                                    match self.resolve_path(&path, None, Some(span)) {
                                         PathResult::Failed(msg, _) => (Def::Err, Some(msg)),
                                         _ => unreachable!(),
                                     }
@@ -1698,19 +1689,17 @@ fn with_constant_rib<F>(&mut self, f: F)
 
     fn resolve_trait_reference(&mut self,
                                path: &[Ident],
-                               global: bool,
                                generics: Option<&Generics>,
                                span: Span)
                                -> PathResolution {
-        let scope = if global { PathScope::Global } else { PathScope::Lexical };
-        let def = match self.resolve_path(path, scope, None, Some(span)) {
+        let def = match self.resolve_path(path, None, Some(span)) {
             PathResult::Module(module) => Some(module.def().unwrap()),
             PathResult::NonModule(..) => return err_path_resolution(),
             PathResult::Failed(msg, false) => {
                 resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
                 return err_path_resolution();
             }
-            _ => match self.resolve_path(path, scope, Some(TypeNS), None) {
+            _ => match self.resolve_path(path, Some(TypeNS), None) {
                 PathResult::NonModule(path_resolution) => Some(path_resolution.base_def),
                 _ => None,
             },
@@ -1766,9 +1755,9 @@ fn with_optional_trait_ref<T, F>(&mut self,
         let mut new_val = None;
         let mut new_id = None;
         if let Some(trait_ref) = opt_trait_ref {
-            let ast::Path { ref segments, span, global } = trait_ref.path;
+            let ast::Path { ref segments, span } = trait_ref.path;
             let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
-            let path_res = self.resolve_trait_reference(&path, global, generics, span);
+            let path_res = self.resolve_trait_reference(&path, generics, span);
             assert!(path_res.depth == 0);
             self.record_def(trait_ref.ref_id, path_res);
             if path_res.base_def != Def::Err {
@@ -2260,9 +2249,8 @@ fn resolve_possibly_assoc_item(&mut self,
                                    path: &Path,
                                    ns: Namespace)
                                    -> Option<PathResolution> {
-        let ast::Path { ref segments, global, span } = *path;
+        let ast::Path { ref segments, span } = *path;
         let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
-        let scope = if global { PathScope::Global } else { PathScope::Lexical };
 
         if let Some(qself) = maybe_qself {
             if qself.position == 0 {
@@ -2273,10 +2261,10 @@ fn resolve_possibly_assoc_item(&mut self,
                 });
             }
             // Make sure the trait is valid.
-            self.resolve_trait_reference(&path[..qself.position], global, None, span);
+            self.resolve_trait_reference(&path[..qself.position], None, span);
         }
 
-        let result = match self.resolve_path(&path, scope, Some(ns), Some(span)) {
+        let result = match self.resolve_path(&path, Some(ns), Some(span)) {
             PathResult::NonModule(path_res) => match path_res.base_def {
                 Def::Trait(..) if maybe_qself.is_some() => return None,
                 _ => path_res,
@@ -2297,7 +2285,7 @@ fn resolve_possibly_assoc_item(&mut self,
             // Such behavior is required for backward compatibility.
             // The same fallback is used when `a` resolves to nothing.
             PathResult::Module(..) | PathResult::Failed(..)
-                    if scope == PathScope::Lexical && (ns == TypeNS || path.len() > 1) &&
+                    if (ns == TypeNS || path.len() > 1) &&
                        self.primitive_type_table.primitive_types.contains_key(&path[0].name) => {
                 PathResolution {
                     base_def: Def::PrimTy(self.primitive_type_table.primitive_types[&path[0].name]),
@@ -2317,7 +2305,7 @@ fn resolve_possibly_assoc_item(&mut self,
         }
 
         let unqualified_result = {
-            match self.resolve_path(&[*path.last().unwrap()], PathScope::Lexical, Some(ns), None) {
+            match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) {
                 PathResult::NonModule(path_res) => path_res.base_def,
                 PathResult::Module(module) => module.def().unwrap(),
                 _ => return Some(result),
@@ -2333,27 +2321,19 @@ fn resolve_possibly_assoc_item(&mut self,
 
     fn resolve_path(&mut self,
                     path: &[Ident],
-                    scope: PathScope,
                     opt_ns: Option<Namespace>, // `None` indicates a module path
                     record_used: Option<Span>)
                     -> PathResult<'a> {
-        let (mut module, allow_self) = match scope {
-            PathScope::Lexical => (None, true),
-            PathScope::Import => (Some(self.graph_root), true),
-            PathScope::Global => (Some(self.graph_root), false),
-        };
-        let mut allow_super = allow_self;
+        let mut module = None;
+        let mut allow_super = true;
 
         for (i, &ident) in path.iter().enumerate() {
             let is_last = i == path.len() - 1;
             let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
 
-            if i == 0 && allow_self && ns == TypeNS && ident.name == keywords::SelfValue.name() {
+            if i == 0 && ns == TypeNS && ident.name == keywords::SelfValue.name() {
                 module = Some(self.module_map[&self.current_module.normal_ancestor_id.unwrap()]);
                 continue
-            } else if i == 0 && allow_self && ns == TypeNS && ident.name == "$crate" {
-                module = Some(self.resolve_crate_var(ident.ctxt));
-                continue
             } else if allow_super && ns == TypeNS && ident.name == keywords::Super.name() {
                 let current_module = if i == 0 { self.current_module } else { module.unwrap() };
                 let self_module = self.module_map[&current_module.normal_ancestor_id.unwrap()];
@@ -2367,6 +2347,14 @@ fn resolve_path(&mut self,
             }
             allow_super = false;
 
+            if i == 0 && ns == TypeNS && ident.name == keywords::CrateRoot.name() {
+                module = Some(self.graph_root);
+                continue
+            } else if i == 0 && ns == TypeNS && ident.name == "$crate" {
+                module = Some(self.resolve_crate_var(ident.ctxt));
+                continue
+            }
+
             let binding = if let Some(module) = module {
                 self.resolve_ident_in_module(module, ident, ns, false, record_used)
             } else if opt_ns == Some(MacroNS) {
@@ -2430,7 +2418,7 @@ fn resolve_path(&mut self,
             }
         }
 
-        PathResult::Module(module.unwrap())
+        PathResult::Module(module.unwrap_or(self.graph_root))
     }
 
     // Resolve a local definition, potentially adjusting for closures.
@@ -2665,10 +2653,8 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
                 } else {
                     // Be helpful if the name refers to a struct
                     let path_name = path_names_to_string(path, 0);
-                    let ast::Path { ref segments, global, .. } = *path;
-                    let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
-                    let scope = if global { PathScope::Global } else { PathScope::Lexical };
-                    let type_res = match self.resolve_path(&path, scope, Some(TypeNS), None) {
+                    let path: Vec<_> = path.segments.iter().map(|seg| seg.identifier).collect();
+                    let type_res = match self.resolve_path(&path, Some(TypeNS), None) {
                         PathResult::NonModule(type_res) => Some(type_res),
                         _ => None,
                     };
@@ -2738,7 +2724,7 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
                             } else {
                                 // we display a help message if this is a module
                                 if let PathResult::Module(module) =
-                                        self.resolve_path(&path, scope, None, None) {
+                                        self.resolve_path(&path, None, None) {
                                     def = module.def().unwrap();
                                     context = UnresolvedNameContext::PathIsMod(parent);
                                 }
@@ -2964,7 +2950,6 @@ fn lookup_candidates<FilterFn>(&mut self,
                         segms.push(ident.into());
                         let path = Path {
                             span: span,
-                            global: false,
                             segments: segms,
                         };
                         // the entity is accessible in the following cases:
@@ -3022,7 +3007,7 @@ fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
 
         let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
         let mut path_resolution = err_path_resolution();
-        let vis = match self.resolve_path(&path, PathScope::Import, None, Some(span)) {
+        let vis = match self.resolve_path(&path, None, Some(span)) {
             PathResult::Module(module) => {
                 path_resolution = PathResolution::new(module.def().unwrap());
                 ty::Visibility::Restricted(module.normal_ancestor_id.unwrap())
@@ -3190,15 +3175,14 @@ fn report_conflict(&mut self,
 }
 
 fn names_to_string(names: &[Ident]) -> String {
-    let mut first = true;
     let mut result = String::new();
-    for ident in names {
-        if first {
-            first = false
-        } else {
-            result.push_str("::")
+    for (i, ident) in names.iter().enumerate() {
+        if i > 0 {
+            result.push_str("::");
+        }
+        if ident.name != keywords::CrateRoot.name() {
+            result.push_str(&ident.name.as_str());
         }
-        result.push_str(&ident.name.as_str());
     }
     result
 }
index 204d1127fc48dc90aba8710e48e5cbda9710bae9..ff3c583629371fed73a6cbbd3c716f21a0d852ba 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use {AmbiguityError, Resolver, ResolutionError, resolve_error};
-use {Module, ModuleKind, NameBinding, NameBindingKind, PathScope, PathResult};
+use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult};
 use Namespace::{self, MacroNS};
 use build_reduced_graph::BuildReducedGraphVisitor;
 use resolve_imports::ImportResolver;
@@ -30,6 +30,7 @@
 use syntax::feature_gate::{emit_feature_err, GateIssue};
 use syntax::fold::Folder;
 use syntax::ptr::P;
+use syntax::symbol::keywords;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::visit::Visitor;
 use syntax_pos::{Span, DUMMY_SP};
@@ -105,15 +106,13 @@ impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> {
             fn fold_path(&mut self, mut path: ast::Path) -> ast::Path {
                 let ident = path.segments[0].identifier;
                 if ident.name == "$crate" {
-                    path.global = true;
+                    path.segments[0].identifier.name = keywords::CrateRoot.name();
                     let module = self.0.resolve_crate_var(ident.ctxt);
-                    if module.is_local() {
-                        path.segments.remove(0);
-                    } else {
-                        path.segments[0].identifier = match module.kind {
-                            ModuleKind::Def(_, name) => ast::Ident::with_empty_ctxt(name),
+                    if !module.is_local() {
+                        path.segments.insert(1, match module.kind {
+                            ModuleKind::Def(_, name) => ast::Ident::with_empty_ctxt(name).into(),
                             _ => unreachable!(),
-                        };
+                        })
                     }
                 }
                 path
@@ -182,7 +181,7 @@ fn find_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>) -> Option<ast::At
 
     fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                      -> Result<Rc<SyntaxExtension>, Determinacy> {
-        let ast::Path { ref segments, global, span } = *path;
+        let ast::Path { ref segments, span } = *path;
         if segments.iter().any(|segment| segment.parameters.is_some()) {
             let kind =
                 if segments.last().unwrap().parameters.is_some() { "macro" } else { "module" };
@@ -191,12 +190,11 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
             return Err(Determinacy::Determined);
         }
 
-        let path_scope = if global { PathScope::Global } else { PathScope::Lexical };
         let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
         let invocation = self.invocations[&scope];
         self.current_module = invocation.module.get();
 
-        if path.len() > 1 || global {
+        if path.len() > 1 {
             if !self.use_extern_macros {
                 let msg = "non-ident macro paths are experimental";
                 let feature = "use_extern_macros";
@@ -204,7 +202,7 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                 return Err(Determinacy::Determined);
             }
 
-            let ext = match self.resolve_path(&path, path_scope, Some(MacroNS), None) {
+            let ext = match self.resolve_path(&path, Some(MacroNS), None) {
                 PathResult::NonModule(path_res) => match path_res.base_def {
                     Def::Err => Err(Determinacy::Determined),
                     def @ _ => Ok(self.get_macro(def)),
@@ -214,7 +212,7 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                 _ => Err(Determinacy::Determined),
             };
             self.current_module.macro_resolutions.borrow_mut()
-                .push((path.into_boxed_slice(), path_scope, span));
+                .push((path.into_boxed_slice(), span));
             return ext;
         }
 
@@ -351,8 +349,8 @@ pub fn resolve_legacy_scope(&mut self,
 
     pub fn finalize_current_module_macro_resolutions(&mut self) {
         let module = self.current_module;
-        for &(ref path, scope, span) in module.macro_resolutions.borrow().iter() {
-            match self.resolve_path(path, scope, Some(MacroNS), Some(span)) {
+        for &(ref path, span) in module.macro_resolutions.borrow().iter() {
+            match self.resolve_path(path, Some(MacroNS), Some(span)) {
                 PathResult::NonModule(_) => {},
                 PathResult::Failed(msg, _) => {
                     resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
index 8bc0bfb41ff753d175bf0a5edb697d13a43e13e5..f62974b30d18ea37c29bd1cf1b0fea973d2aac42 100644 (file)
@@ -12,7 +12,7 @@
 
 use {AmbiguityError, Module, PerNS};
 use Namespace::{self, TypeNS, MacroNS};
-use {NameBinding, NameBindingKind, PathResult, PathScope, PrivacyError};
+use {NameBinding, NameBindingKind, PathResult, PrivacyError};
 use Resolver;
 use {names_to_string, module_to_string};
 use {resolve_error, ResolutionError};
@@ -24,6 +24,7 @@
 use syntax::ast::{Ident, NodeId};
 use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
 use syntax::ext::hygiene::Mark;
+use syntax::parse::token;
 use syntax::symbol::keywords;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax_pos::Span;
@@ -490,7 +491,7 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
             // For better failure detection, pretend that the import will not define any names
             // while resolving its module path.
             directive.vis.set(ty::Visibility::PrivateExternal);
-            let result = self.resolve_path(&directive.module_path, PathScope::Import, None, None);
+            let result = self.resolve_path(&directive.module_path, None, None);
             directive.vis.set(vis);
 
             match result {
@@ -553,15 +554,17 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<Stri
         self.current_module = directive.parent;
 
         let ImportDirective { ref module_path, span, .. } = *directive;
-        let module_result = self.resolve_path(&module_path, PathScope::Import, None, Some(span));
+        let module_result = self.resolve_path(&module_path, None, Some(span));
         let module = match module_result {
             PathResult::Module(module) => module,
             PathResult::Failed(msg, _) => {
-                let mut path = vec![keywords::SelfValue.ident()];
-                path.extend(module_path);
-                let result = self.resolve_path(&path, PathScope::Import, None, None);
-                return if let PathResult::Module(..) = result {
-                    Some(format!("Did you mean `self::{}`?", &names_to_string(module_path)))
+                let (mut self_path, mut self_result) = (module_path.clone(), None);
+                if !self_path.is_empty() && !token::Ident(self_path[0]).is_path_segment_keyword() {
+                    self_path[0].name = keywords::SelfValue.name();
+                    self_result = Some(self.resolve_path(&self_path, None, None));
+                }
+                return if let Some(PathResult::Module(..)) = self_result {
+                    Some(format!("Did you mean `{}`?", names_to_string(&self_path)))
                 } else {
                     Some(msg)
                 };
@@ -787,6 +790,8 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
 }
 
 fn import_path_to_string(names: &[Ident], subclass: &ImportDirectiveSubclass) -> String {
+    let global = !names.is_empty() && names[0].name == keywords::CrateRoot.name();
+    let names = if global { &names[1..] } else { names };
     if names.is_empty() {
         import_directive_subclass_to_string(subclass)
     } else {
index afa78a05a63a897c4a49ca447b4f326c3e22808c..65372d4dca9a19dcf31cf091154931e97f975d42 100644 (file)
@@ -143,19 +143,20 @@ pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
     // a str representation of the entire prefix.
     fn process_path_prefixes(&self, path: &ast::Path) -> Vec<(Span, String)> {
         let spans = self.span.spans_for_path_segments(path);
+        let segments = &path.segments[if path.is_global() { 1 } else { 0 }..];
 
         // Paths to enums seem to not match their spans - the span includes all the
         // variants too. But they seem to always be at the end, so I hope we can cope with
         // always using the first ones. So, only error out if we don't have enough spans.
         // What could go wrong...?
-        if spans.len() < path.segments.len() {
+        if spans.len() < segments.len() {
             if generated_code(path.span) {
                 return vec![];
             }
             error!("Mis-calculated spans for path '{}'. Found {} spans, expected {}. Found spans:",
                    path_to_string(path),
                    spans.len(),
-                   path.segments.len());
+                   segments.len());
             for s in &spans {
                 let loc = self.sess.codemap().lookup_char_pos(s.lo);
                 error!("    '{}' in {}, line {}",
@@ -170,14 +171,13 @@ fn process_path_prefixes(&self, path: &ast::Path) -> Vec<(Span, String)> {
         let mut result: Vec<(Span, String)> = vec![];
 
         let mut segs = vec![];
-        for (i, (seg, span)) in path.segments.iter().zip(&spans).enumerate() {
+        for (i, (seg, span)) in segments.iter().zip(&spans).enumerate() {
             segs.push(seg.clone());
             let sub_path = ast::Path {
                 span: *span, // span for the last segment
-                global: path.global,
                 segments: segs,
             };
-            let qualname = if i == 0 && path.global {
+            let qualname = if i == 0 && path.is_global() {
                 format!("::{}", path_to_string(&sub_path))
             } else {
                 path_to_string(&sub_path)
@@ -189,20 +189,11 @@ fn process_path_prefixes(&self, path: &ast::Path) -> Vec<(Span, String)> {
         result
     }
 
-    // The global arg allows us to override the global-ness of the path (which
-    // actually means 'does the path start with `::`', rather than 'is the path
-    // semantically global). We use the override for `use` imports (etc.) where
-    // the syntax is non-global, but the semantics are global.
-    fn write_sub_paths(&mut self, path: &ast::Path, global: bool) {
+    fn write_sub_paths(&mut self, path: &ast::Path) {
         let sub_paths = self.process_path_prefixes(path);
-        for (i, &(ref span, ref qualname)) in sub_paths.iter().enumerate() {
-            let qualname = if i == 0 && global && !path.global {
-                format!("::{}", qualname)
-            } else {
-                qualname.clone()
-            };
+        for (span, qualname) in sub_paths {
             self.dumper.mod_ref(ModRefData {
-                span: *span,
+                span: span,
                 qualname: qualname,
                 scope: self.cur_scope,
                 ref_id: None
@@ -212,22 +203,16 @@ fn write_sub_paths(&mut self, path: &ast::Path, global: bool) {
 
     // As write_sub_paths, but does not process the last ident in the path (assuming it
     // will be processed elsewhere). See note on write_sub_paths about global.
-    fn write_sub_paths_truncated(&mut self, path: &ast::Path, global: bool) {
+    fn write_sub_paths_truncated(&mut self, path: &ast::Path) {
         let sub_paths = self.process_path_prefixes(path);
         let len = sub_paths.len();
         if len <= 1 {
             return;
         }
 
-        let sub_paths = &sub_paths[..len-1];
-        for (i, &(ref span, ref qualname)) in sub_paths.iter().enumerate() {
-            let qualname = if i == 0 && global && !path.global {
-                format!("::{}", qualname)
-            } else {
-                qualname.clone()
-            };
+        for (span, qualname) in sub_paths.into_iter().take(len - 1) {
             self.dumper.mod_ref(ModRefData {
-                span: *span,
+                span: span,
                 qualname: qualname,
                 scope: self.cur_scope,
                 ref_id: None
@@ -935,7 +920,7 @@ fn process_path(&mut self, id: NodeId, path: &ast::Path, ref_kind: Option<record
             Def::Union(..) |
             Def::Variant(..) |
             Def::TyAlias(..) |
-            Def::AssociatedTy(..) => self.write_sub_paths_truncated(path, false),
+            Def::AssociatedTy(..) => self.write_sub_paths_truncated(path),
             _ => {}
         }
     }
@@ -946,7 +931,7 @@ fn process_struct_lit(&mut self,
                           fields: &'l [ast::Field],
                           variant: &'l ty::VariantDef,
                           base: &'l Option<P<ast::Expr>>) {
-        self.write_sub_paths_truncated(path, false);
+        self.write_sub_paths_truncated(path);
 
         if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) {
             down_cast_data!(struct_lit_data, TypeRefData, ex.span);
@@ -1201,7 +1186,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                                 visibility: From::from(&item.vis),
                             }.lower(self.tcx));
                         }
-                        self.write_sub_paths_truncated(path, true);
+                        self.write_sub_paths_truncated(path);
                     }
                     ast::ViewPathGlob(ref path) => {
                         // Make a comma-separated list of names of imported modules.
@@ -1225,7 +1210,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                                 visibility: From::from(&item.vis),
                             }.lower(self.tcx));
                         }
-                        self.write_sub_paths(path, true);
+                        self.write_sub_paths(path);
                     }
                     ast::ViewPathList(ref path, ref list) => {
                         for plid in list {
@@ -1237,7 +1222,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                             }
                         }
 
-                        self.write_sub_paths(path, true);
+                        self.write_sub_paths(path);
                     }
                 }
             }
@@ -1340,7 +1325,7 @@ fn visit_ty(&mut self, t: &'l ast::Ty) {
                     }.lower(self.tcx));
                 }
 
-                self.write_sub_paths_truncated(path, false);
+                self.write_sub_paths_truncated(path);
 
                 visit::walk_path(self, path);
             }
index 123516dc89d746fcad14b912ca96e3328c2230d3..fdbd2f3647c0c482c787d2c82322567a48b593be 100644 (file)
@@ -1737,7 +1737,6 @@ fn clean(&self, cx: &DocContext) -> Type {
                 segments.pop();
                 let trait_path = hir::Path {
                     span: p.span,
-                    global: p.global,
                     def: Def::Trait(cx.tcx.associated_item(p.def.def_id()).container.id()),
                     segments: segments.into(),
                 };
@@ -1756,7 +1755,6 @@ fn clean(&self, cx: &DocContext) -> Type {
                 }
                 let trait_path = hir::Path {
                     span: self.span,
-                    global: false,
                     def: def,
                     segments: vec![].into(),
                 };
@@ -2213,9 +2211,9 @@ pub fn last_name(&self) -> String {
 impl Clean<Path> for hir::Path {
     fn clean(&self, cx: &DocContext) -> Path {
         Path {
-            global: self.global,
+            global: self.is_global(),
             def: self.def,
-            segments: self.segments.clean(cx),
+            segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx),
         }
     }
 }
@@ -2270,24 +2268,19 @@ fn clean(&self, cx: &DocContext) -> PathSegment {
 }
 
 fn qpath_to_string(p: &hir::QPath) -> String {
-    let (segments, global) = match *p {
-        hir::QPath::Resolved(_, ref path) => {
-            (&path.segments, path.global)
-        }
-        hir::QPath::TypeRelative(_, ref segment) => {
-            return segment.name.to_string()
-        }
+    let segments = match *p {
+        hir::QPath::Resolved(_, ref path) => &path.segments,
+        hir::QPath::TypeRelative(_, ref segment) => return segment.name.to_string(),
     };
 
     let mut s = String::new();
-    let mut first = true;
-    for i in segments.iter().map(|x| x.name.as_str()) {
-        if !first || global {
+    for (i, seg) in segments.iter().enumerate() {
+        if i > 0 {
             s.push_str("::");
-        } else {
-            first = false;
         }
-        s.push_str(&i);
+        if seg.name != keywords::CrateRoot.name() {
+            s.push_str(&*seg.name.as_str());
+        }
     }
     s
 }
index fdd82225b974747990adb31c6a9d8067499011d2..648a82ffb76844262a64ce610ecb8dcf4d2dd6db 100644 (file)
@@ -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 @@ fn from(id: Ident) -> Self {
     }
 }
 
+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)`
index c3dc64f91247bed799f59ed813dff72b423217f9..7584fa3916de01d77c9398c2b5e459c83d3d95fb 100644 (file)
@@ -322,7 +322,12 @@ fn path_all(&self,
                 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 @@ fn path_all(&self,
         segments.push(ast::PathSegment { identifier: last_identifier, parameters: parameters });
         ast::Path {
             span: sp,
-            global: global,
             segments: segments,
         }
     }
index eb4b6144c8d28ad989d2044710ed2cda42b3f49f..66555d7d95dce03c0ca9b0bda7dfbf18ba857473 100644 (file)
@@ -25,7 +25,7 @@
 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(),
         })
     }
index b3753e3e977e331cf424d382694f2bcd28ff0c34..bf10d45add4a0b09e4d43f23a3492cc1310def7a 100644 (file)
@@ -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))),
index b9e6605639ead2c8ff0f8ee61cd0814c5df31738..24178e1f675b5197d218017aa558a5013b537932 100644 (file)
@@ -633,7 +633,6 @@ fn sp(a: u32, b: u32) -> Span {
                     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 @@ fn sp(a: u32, b: u32) -> Span {
                     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 @@ fn string_to_tts_1() {
                         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 @@ fn string_to_tts_1() {
                            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 @@ fn parser_done(p: Parser){
                                     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 @@ fn parser_done(p: Parser){
                                                 node: ast::ExprKind::Path(None,
                                                       ast::Path{
                                                         span:sp(17,18),
-                                                        global:false,
                                                         segments: vec![Ident::from_str("b").into()],
                                                       }),
                                                 span: sp(17,18),
index 72462b74e686ca60b1f002f220738dd7e55b162f..cd4f255b5e3f815668aaedc483177d811ccca2bd 100644 (file)
@@ -1614,7 +1614,6 @@ pub fn parse_qualified_path(&mut self, mode: PathStyle)
         } else {
             ast::Path {
                 span: span,
-                global: false,
                 segments: vec![]
             }
         };
@@ -1658,7 +1657,7 @@ pub fn parse_path(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> {
         // 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 @@ pub fn parse_path(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> {
             }
         };
 
+        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 @@ fn parse_visibility(&mut self, allow_path: bool) -> PResult<'a, Visibility> {
         } 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 @@ fn parse_view_path(&mut self) -> PResult<'a, P<ViewPath>> {
         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 @@ fn parse_view_path(&mut self) -> PResult<'a, P<ViewPath>> {
             };
             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();
index 22e8391de93ed4910d9fbf988db6e3093392c844..e9c1cbcba61db9953bab3135bd9349222f4b53e8 100644 (file)
@@ -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 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
                                  &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 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
             }
             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 @@ 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)
+        self.print_path(&t.path, false, 0, false)
     }
 
     fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> io::Result<()> {
@@ -1405,8 +1406,10 @@ pub fn print_visibility(&mut self, vis: &ast::Visibility) -> io::Result<()> {
         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 @@ 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)?;
+                self.print_path(&node.path, false, 0, false)?;
                 word(&mut self.s, "! ")?;
                 self.cbox(INDENT_UNIT)?;
                 self.popen()?;
@@ -1607,7 +1610,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:
-                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 @@ pub fn print_if_let(&mut self, pat: &ast::Pat, expr: &ast::Expr, blk: &ast::Bloc
 
     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 @@ fn print_expr_struct(&mut self,
                          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 @@ fn print_expr_outer_attr_style(&mut self,
                 }
             }
             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 @@ pub fn print_for_decl(&mut self, loc: &ast::Local,
     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 @@ fn print_qpath(&mut self,
             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 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
                 }
             }
             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 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
                 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 @@ pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause)
                     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 @@ pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause)
     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 @@ pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> io::Result<()> {
             }
 
             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 @@ pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> io::Result<()> {
                 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| {
index 4ad760a3cafe4194ca60be1ec28fb9e5c5c12168..68d807b24a788547bc8516c68dbffd496e4ce353 100644 (file)
@@ -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,
index fe9a176179ce67aebc42f13398c418b104c7f4cd..c2123ea5a079803a3897053afefec54656df786e 100644 (file)
@@ -221,6 +221,9 @@ fn fresh() -> Self {
     (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.
index 7709d3bd1cf1ce27e5bcd1492ac54a34a7ad08b8..b8e0b938814a76605dc24226e8c726c97cb30589 100644 (file)
@@ -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(),
     }
 }
index 1381490efa194b3bd7a1e7850aa35c394bae9a30..1fc1bdff593c2766fa16ab94bad998451f82e0ee 100644 (file)
@@ -61,7 +61,6 @@ impl Result {
         fn path(&self) -> ast::Path {
             ast::Path {
                 span: self.span,
-                global: false,
                 segments: vec![self.ident.into()],
             }
         }
index 51199819dfcd7dec64c15568222460ae7703e47b..7f187d8d1c1195a472d8a749ace01da3a892fa63 100644 (file)
@@ -363,15 +363,12 @@ struct Visitor<'a, 'b: 'a> {
 
     impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> {
         fn visit_ty(&mut self, ty: &'a ast::Ty) {
-            match ty.node {
-                ast::TyKind::Path(_, ref path) if !path.global => {
-                    if let Some(segment) = path.segments.first() {
-                        if self.ty_param_names.contains(&segment.identifier.name) {
-                            self.types.push(P(ty.clone()));
-                        }
+            if let ast::TyKind::Path(_, ref path) = ty.node {
+                if let Some(segment) = path.segments.first() {
+                    if self.ty_param_names.contains(&segment.identifier.name) {
+                        self.types.push(P(ty.clone()));
                     }
                 }
-                _ => {}
             }
 
             visit::walk_ty(self, ty)
index 1e43933ad0ab4356ccfd93746d9a99d6aa857669..3c585680eab119222c5a4a65104c401ca28106c7 100644 (file)
@@ -16,5 +16,5 @@ fn main() {
 
     // Make sure primitive type fallback doesn't work with global paths
     let _: ::u8;
-    //~^ ERROR type name `u8` is undefined or not in scope
+    //~^ ERROR type name `::u8` is undefined or not in scope
 }