]> git.lizzy.rs Git - rust.git/commitdiff
rustc_resolve: only prepend CrateRoot to a non-keyword segment.
authorEduard-Mihai Burtescu <edy.burt@gmail.com>
Thu, 6 Sep 2018 10:29:45 +0000 (13:29 +0300)
committerEduard-Mihai Burtescu <edy.burt@gmail.com>
Fri, 7 Sep 2018 20:23:51 +0000 (23:23 +0300)
src/librustc_resolve/build_reduced_graph.rs
src/test/ui/run-pass/rfcs/rfc-2126-crate-paths/crate-path-absolute.rs

index 37868a83e342168727f1623c8f2b0e7c5724cca4..92a9057d96ebccd37b1a8fdb663fe5c9977273bf 100644 (file)
@@ -120,26 +120,48 @@ fn build_reduced_graph_for_use_tree(
         use_tree: &ast::UseTree,
         id: NodeId,
         vis: ty::Visibility,
-        prefix: &ast::Path,
+        parent_prefix: &[Ident],
         mut uniform_paths_canary_emitted: bool,
         nested: bool,
         item: &Item,
         expansion: Mark,
     ) {
-        debug!("build_reduced_graph_for_use_tree(prefix={:?}, \
+        debug!("build_reduced_graph_for_use_tree(parent_prefix={:?}, \
                 uniform_paths_canary_emitted={}, \
                 use_tree={:?}, nested={})",
-               prefix, uniform_paths_canary_emitted, use_tree, nested);
+               parent_prefix, uniform_paths_canary_emitted, use_tree, nested);
 
         let is_prelude = attr::contains_name(&item.attrs, "prelude_import");
-        let path = &use_tree.prefix;
+        let uniform_paths =
+            self.session.rust_2018() &&
+            self.session.features_untracked().uniform_paths;
+
+        let prefix_iter = || parent_prefix.iter().cloned()
+            .chain(use_tree.prefix.segments.iter().map(|seg| seg.ident));
+        let prefix_start = prefix_iter().nth(0);
+        let starts_with_non_keyword = prefix_start.map_or(false, |ident| {
+            !ident.is_path_segment_keyword()
+        });
+
+        // Imports are resolved as global by default, prepend `CrateRoot`,
+        // unless `#![feature(uniform_paths)]` is enabled.
+        let inject_crate_root =
+            !uniform_paths &&
+            match use_tree.kind {
+                // HACK(eddyb) special-case `use *` to mean `use ::*`.
+                ast::UseTreeKind::Glob if prefix_start.is_none() => true,
+                _ => starts_with_non_keyword,
+            };
+        let root = if inject_crate_root {
+            let span = use_tree.prefix.span.shrink_to_lo();
+            Some(Ident::new(keywords::CrateRoot.name(), span))
+        } else {
+            None
+        };
 
-        let mut module_path: Vec<_> = prefix.segments.iter()
-            .chain(path.segments.iter())
-            .map(|seg| seg.ident)
-            .collect();
+        let prefix: Vec<_> = root.into_iter().chain(prefix_iter()).collect();
 
-        debug!("build_reduced_graph_for_use_tree: module_path={:?}", module_path);
+        debug!("build_reduced_graph_for_use_tree: prefix={:?}", prefix);
 
         // `#[feature(uniform_paths)]` allows an unqualified import path,
         // e.g. `use x::...;` to resolve not just globally (`use ::x::...;`)
@@ -172,15 +194,10 @@ fn build_reduced_graph_for_use_tree(
         // ergonomically unacceptable.
         let emit_uniform_paths_canary =
             !uniform_paths_canary_emitted &&
-            module_path.get(0).map_or(false, |ident| {
-                !ident.is_path_segment_keyword()
-            });
+            uniform_paths &&
+            starts_with_non_keyword;
         if emit_uniform_paths_canary {
-            // Relative paths should only get here if the feature-gate is on.
-            assert!(self.session.rust_2018() &&
-                    self.session.features_untracked().uniform_paths);
-
-            let source = module_path[0];
+            let source = prefix_start.unwrap();
 
             // HACK(eddyb) For `use x::{self, ...};`, use the ID of the
             // `self` nested import for the canary. This allows the
@@ -256,6 +273,7 @@ fn build_reduced_graph_for_use_tree(
         match use_tree.kind {
             ast::UseTreeKind::Simple(rename, ..) => {
                 let mut ident = use_tree.ident();
+                let mut module_path = prefix;
                 let mut source = module_path.pop().unwrap();
                 let mut type_ns_only = false;
 
@@ -354,7 +372,7 @@ fn build_reduced_graph_for_use_tree(
                     max_vis: Cell::new(ty::Visibility::Invisible),
                 };
                 self.add_import_directive(
-                    module_path,
+                    prefix,
                     subclass,
                     use_tree.span,
                     id,
@@ -366,13 +384,6 @@ fn build_reduced_graph_for_use_tree(
                 );
             }
             ast::UseTreeKind::Nested(ref items) => {
-                let prefix = ast::Path {
-                    segments: module_path.into_iter()
-                        .map(|ident| ast::PathSegment::from_ident(ident))
-                        .collect(),
-                    span: path.span,
-                };
-
                 // Ensure there is at most one `self` in the list
                 let self_spans = items.iter().filter_map(|&(ref use_tree, _)| {
                     if let ast::UseTreeKind::Simple(..) = use_tree.kind {
@@ -422,28 +433,13 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
 
         match item.node {
             ItemKind::Use(ref use_tree) => {
-                let uniform_paths =
-                    self.session.rust_2018() &&
-                    self.session.features_untracked().uniform_paths;
-                // Imports are resolved as global by default, add starting root segment.
-                let root = if !uniform_paths {
-                    use_tree.prefix.make_root()
-                } else {
-                    // Except when `#![feature(uniform_paths)]` is on.
-                    None
-                };
-                let prefix = ast::Path {
-                    segments: root.into_iter().collect(),
-                    span: use_tree.span,
-                };
-
                 self.build_reduced_graph_for_use_tree(
                     use_tree,
                     item.id,
                     use_tree,
                     item.id,
                     vis,
-                    &prefix,
+                    &[],
                     false, // uniform_paths_canary_emitted
                     false,
                     item,
index e44ab838cafa02b08b3eea83de6ffb0bde4500ee..71904acae724d8c5b7d5984dfbf2b26afde3417d 100644 (file)
@@ -23,8 +23,7 @@ pub fn h() -> u8 { 3 }
     pub(in crate::m) struct S;
 }
 
-mod n
-{
+mod n {
     use crate::m::f;
     use crate as root;
     pub fn check() {
@@ -34,9 +33,20 @@ pub fn check() {
     }
 }
 
+mod p {
+    use {super::f, crate::m::g, self::root::m::h};
+    use crate as root;
+    pub fn check() {
+        assert_eq!(f(), 1);
+        assert_eq!(g(), 2);
+        assert_eq!(h(), 3);
+    }
+}
+
 fn main() {
     assert_eq!(f(), 1);
     assert_eq!(crate::m::g(), 2);
     assert_eq!(root::m::h(), 3);
     n::check();
+    p::check();
 }