about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-10-27 23:38:09 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-10-28 03:06:38 +0300
commitc57f0a7201860eb87ad8df1f3e63ea1ed03dcb40 (patch)
tree0278291bd3295c6607751326de414ab220ae3d06
parent1f257bd022389e21b8f165a055b854c7195d7e45 (diff)
downloadrust-c57f0a7201860eb87ad8df1f3e63ea1ed03dcb40.tar.gz
rust-c57f0a7201860eb87ad8df1f3e63ea1ed03dcb40.zip
resolve: Desugar empty import groups into synthetic dummy imports
so that they are correctly resolved on 2018 edition
-rw-r--r--src/librustc/hir/lowering.rs3
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs33
-rw-r--r--src/librustc_resolve/lib.rs72
-rw-r--r--src/test/ui/issues/issue-28388-1.rs2
-rw-r--r--src/test/ui/issues/issue-28388-1.stderr8
-rw-r--r--src/test/ui/resolve/resolve-bad-import-prefix.rs6
-rw-r--r--src/test/ui/resolve/resolve-bad-import-prefix.stderr25
7 files changed, 51 insertions, 98 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 6370a520183..9795c0cba61 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -3133,7 +3133,8 @@ impl<'a> LoweringContext<'a> {
                 // Privatize the degenerate import base, used only to check
                 // the stability of `use a::{};`, to avoid it showing up as
                 // a re-export by accident when `pub`, e.g. in documentation.
-                let path = P(self.lower_path(id, &prefix, ParamMode::Explicit));
+                let def = self.expect_full_def_from_use(id).next().unwrap_or(Def::Err);
+                let path = P(self.lower_path_extra(def, &prefix, None, ParamMode::Explicit, None));
                 *vis = respan(prefix.span.shrink_to_lo(), hir::VisibilityKind::Inherited);
                 hir::ItemKind::Use(path, hir::UseKind::ListStem)
             }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 328d5bb3af0..bb451f554d6 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -253,6 +253,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
             uniform_paths_canary_emitted = true;
         }
 
+        let empty_for_self = |prefix: &[Segment]| {
+            prefix.is_empty() ||
+            prefix.len() == 1 && prefix[0].ident.name == keywords::CrateRoot.name()
+        };
         match use_tree.kind {
             ast::UseTreeKind::Simple(rename, ..) => {
                 let mut ident = use_tree.ident();
@@ -265,10 +269,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                     if source.ident.name == keywords::SelfValue.name() {
                         type_ns_only = true;
 
-                        let empty_prefix = module_path.last().map_or(true, |seg| {
-                            seg.ident.name == keywords::CrateRoot.name()
-                        });
-                        if empty_prefix {
+                        if empty_for_self(&module_path) {
                             resolve_error(
                                 self,
                                 use_tree.span,
@@ -400,6 +401,30 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                         parent_scope.clone(), item, vis, root_span,
                     );
                 }
+
+                // Empty groups `a::b::{}` are turned into synthetic `self` imports
+                // `a::b::c::{self as _}`, so that their prefixes are correctly
+                // resolved and checked for privacy/stability/etc.
+                if items.is_empty() && !empty_for_self(&prefix) {
+                    let new_span = prefix[prefix.len() - 1].ident.span;
+                    let tree = ast::UseTree {
+                        prefix: ast::Path::from_ident(
+                            Ident::new(keywords::SelfValue.name(), new_span)
+                        ),
+                        kind: ast::UseTreeKind::Simple(
+                            Some(Ident::new(keywords::Underscore.name().gensymed(), new_span)),
+                            ast::DUMMY_NODE_ID,
+                            ast::DUMMY_NODE_ID,
+                        ),
+                        span: use_tree.span,
+                    };
+                    self.build_reduced_graph_for_use_tree(
+                        // This particular use tree
+                        &tree, id, &prefix, true, uniform_paths_canary_emitted,
+                        // The whole `use` item
+                        parent_scope.clone(), item, ty::Visibility::Invisible, root_span,
+                    );
+                }
             }
         }
     }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 397c67e7587..ebd87e87ff6 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -482,15 +482,13 @@ enum PathSource<'a> {
     TraitItem(Namespace),
     // Path in `pub(path)`
     Visibility,
-    // Path in `use a::b::{...};`
-    ImportPrefix,
 }
 
 impl<'a> PathSource<'a> {
     fn namespace(self) -> Namespace {
         match self {
             PathSource::Type | PathSource::Trait(_) | PathSource::Struct |
-            PathSource::Visibility | PathSource::ImportPrefix => TypeNS,
+            PathSource::Visibility => TypeNS,
             PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct => ValueNS,
             PathSource::TraitItem(ns) => ns,
         }
@@ -498,7 +496,7 @@ impl<'a> PathSource<'a> {
 
     fn global_by_default(self) -> bool {
         match self {
-            PathSource::Visibility | PathSource::ImportPrefix => true,
+            PathSource::Visibility => true,
             PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
             PathSource::Struct | PathSource::TupleStruct |
             PathSource::Trait(_) | PathSource::TraitItem(..) => false,
@@ -510,7 +508,7 @@ impl<'a> PathSource<'a> {
             PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
             PathSource::Struct | PathSource::TupleStruct => true,
             PathSource::Trait(_) | PathSource::TraitItem(..) |
-            PathSource::Visibility | PathSource::ImportPrefix => false,
+            PathSource::Visibility => false,
         }
     }
 
@@ -522,7 +520,6 @@ impl<'a> PathSource<'a> {
             PathSource::Struct => "struct, variant or union type",
             PathSource::TupleStruct => "tuple struct/variant",
             PathSource::Visibility => "module",
-            PathSource::ImportPrefix => "module or enum",
             PathSource::TraitItem(ns) => match ns {
                 TypeNS => "associated type",
                 ValueNS => "method or associated constant",
@@ -587,10 +584,6 @@ impl<'a> PathSource<'a> {
                 Def::AssociatedTy(..) if ns == TypeNS => true,
                 _ => false,
             },
-            PathSource::ImportPrefix => match def {
-                Def::Mod(..) | Def::Enum(..) => true,
-                _ => false,
-            },
             PathSource::Visibility => match def {
                 Def::Mod(..) => true,
                 _ => false,
@@ -626,8 +619,8 @@ impl<'a> PathSource<'a> {
             (PathSource::Pat, false) | (PathSource::TupleStruct, false) => "E0531",
             (PathSource::TraitItem(..), true) => "E0575",
             (PathSource::TraitItem(..), false) => "E0576",
-            (PathSource::Visibility, true) | (PathSource::ImportPrefix, true) => "E0577",
-            (PathSource::Visibility, false) | (PathSource::ImportPrefix, false) => "E0578",
+            (PathSource::Visibility, true) => "E0577",
+            (PathSource::Visibility, false) => "E0578",
         }
     }
 }
@@ -2350,16 +2343,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                 });
             }
 
-            ItemKind::Use(ref use_tree) => {
-                // Imports are resolved as global by default, add starting root segment.
-                let path = Path {
-                    segments: use_tree.prefix.make_root().into_iter().collect(),
-                    span: use_tree.span,
-                };
-                self.resolve_use_tree(item.id, use_tree.span, item.id, use_tree, &path);
-            }
-
-            ItemKind::ExternCrate(_) | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(_) => {
+            ItemKind::Use(..) | ItemKind::ExternCrate(..) |
+            ItemKind::MacroDef(..) | ItemKind::GlobalAsm(..) => {
                 // do nothing, these are just around to be encoded
             }
 
@@ -2367,49 +2352,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
         }
     }
 
-    /// For the most part, use trees are desugared into `ImportDirective` instances
-    /// when building the reduced graph (see `build_reduced_graph_for_use_tree`). But
-    /// there is one special case we handle here: an empty nested import like
-    /// `a::{b::{}}`, which desugares into...no import directives.
-    fn resolve_use_tree(
-        &mut self,
-        root_id: NodeId,
-        root_span: Span,
-        id: NodeId,
-        use_tree: &ast::UseTree,
-        prefix: &Path,
-    ) {
-        match use_tree.kind {
-            ast::UseTreeKind::Nested(ref items) => {
-                let path = Path {
-                    segments: prefix.segments
-                        .iter()
-                        .chain(use_tree.prefix.segments.iter())
-                        .cloned()
-                        .collect(),
-                    span: prefix.span.to(use_tree.prefix.span),
-                };
-
-                if items.is_empty() {
-                    // Resolve prefix of an import with empty braces (issue #28388).
-                    self.smart_resolve_path_with_crate_lint(
-                        id,
-                        None,
-                        &path,
-                        PathSource::ImportPrefix,
-                        CrateLint::UsePath { root_id, root_span },
-                    );
-                } else {
-                    for &(ref tree, nested_id) in items {
-                        self.resolve_use_tree(root_id, root_span, nested_id, tree, &path);
-                    }
-                }
-            }
-            ast::UseTreeKind::Simple(..) => {},
-            ast::UseTreeKind::Glob => {},
-        }
-    }
-
     fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters<'a, 'b>, f: F)
         where F: FnOnce(&mut Resolver)
     {
diff --git a/src/test/ui/issues/issue-28388-1.rs b/src/test/ui/issues/issue-28388-1.rs
index 187d91731d0..b0418a513e3 100644
--- a/src/test/ui/issues/issue-28388-1.rs
+++ b/src/test/ui/issues/issue-28388-1.rs
@@ -10,6 +10,6 @@
 
 // Prefix in imports with empty braces should be resolved and checked privacy, stability, etc.
 
-use foo::{}; //~ ERROR cannot find module or enum `foo` in the crate root
+use foo::{}; //~ ERROR unresolved import `foo`
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-28388-1.stderr b/src/test/ui/issues/issue-28388-1.stderr
index 9f4b6cb56e7..f93252f1d7d 100644
--- a/src/test/ui/issues/issue-28388-1.stderr
+++ b/src/test/ui/issues/issue-28388-1.stderr
@@ -1,9 +1,9 @@
-error[E0578]: cannot find module or enum `foo` in the crate root
+error[E0432]: unresolved import `foo`
   --> $DIR/issue-28388-1.rs:13:5
    |
-LL | use foo::{}; //~ ERROR cannot find module or enum `foo` in the crate root
-   |     ^^^ not found in the crate root
+LL | use foo::{}; //~ ERROR unresolved import `foo`
+   |     ^^^^^^^ no `foo` in the root
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0578`.
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/resolve/resolve-bad-import-prefix.rs b/src/test/ui/resolve/resolve-bad-import-prefix.rs
index 370782fc7d9..5da5a8c3fef 100644
--- a/src/test/ui/resolve/resolve-bad-import-prefix.rs
+++ b/src/test/ui/resolve/resolve-bad-import-prefix.rs
@@ -17,8 +17,8 @@ use {}; // OK
 use ::{}; // OK
 use m::{}; // OK
 use E::{}; // OK
-use S::{}; //~ ERROR expected module or enum, found struct `S`
-use Tr::{}; //~ ERROR expected module or enum, found trait `Tr`
-use Nonexistent::{}; //~ ERROR cannot find module or enum `Nonexistent` in the crate root
+use S::{}; // FIXME, this and `use S::{self};` should be an error
+use Tr::{}; // FIXME, this and `use Tr::{self};` should be an error
+use Nonexistent::{}; //~ ERROR unresolved import `Nonexistent`
 
 fn main () {}
diff --git a/src/test/ui/resolve/resolve-bad-import-prefix.stderr b/src/test/ui/resolve/resolve-bad-import-prefix.stderr
index 76d0c035335..c4d9b1d0075 100644
--- a/src/test/ui/resolve/resolve-bad-import-prefix.stderr
+++ b/src/test/ui/resolve/resolve-bad-import-prefix.stderr
@@ -1,24 +1,9 @@
-error[E0577]: expected module or enum, found struct `S`
-  --> $DIR/resolve-bad-import-prefix.rs:20:5
-   |
-LL | use S::{}; //~ ERROR expected module or enum, found struct `S`
-   |     -^^^^
-   |     |
-   |     did you mean `E`?
-
-error[E0577]: expected module or enum, found trait `Tr`
-  --> $DIR/resolve-bad-import-prefix.rs:21:5
-   |
-LL | use Tr::{}; //~ ERROR expected module or enum, found trait `Tr`
-   |     ^^^^^^ not a module or enum
-
-error[E0578]: cannot find module or enum `Nonexistent` in the crate root
+error[E0432]: unresolved import `Nonexistent`
   --> $DIR/resolve-bad-import-prefix.rs:22:5
    |
-LL | use Nonexistent::{}; //~ ERROR cannot find module or enum `Nonexistent` in the crate root
-   |     ^^^^^^^^^^^ not found in the crate root
+LL | use Nonexistent::{}; //~ ERROR unresolved import `Nonexistent`
+   |     ^^^^^^^^^^^^^^^ no `Nonexistent` in the root
 
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0577, E0578.
-For more information about an error, try `rustc --explain E0577`.
+For more information about this error, try `rustc --explain E0432`.