about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-11-24 19:14:05 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-11-27 00:34:21 +0300
commit5e121756ef003f13b9dbb6a44b8bc4dce87b84a8 (patch)
tree3e1d434a10fa8d1518d8366be6604f999ced5ada
parentc06e69ee70bf1fec4630458d8e4417efcabe0424 (diff)
downloadrust-5e121756ef003f13b9dbb6a44b8bc4dce87b84a8.tar.gz
rust-5e121756ef003f13b9dbb6a44b8bc4dce87b84a8.zip
resolve: Generalize `early_resolve_ident_in_lexical_scope` slightly
Flatten `ModuleOrUniformRoot` variants
-rw-r--r--src/librustc_resolve/lib.rs51
-rw-r--r--src/librustc_resolve/macros.rs24
-rw-r--r--src/librustc_resolve/resolve_imports.rs85
3 files changed, 78 insertions, 82 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 07ded5c6723..bc0e8a56157 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -102,6 +102,12 @@ enum Weak {
     No,
 }
 
+enum ScopeSet {
+    Import(Namespace),
+    Macro(MacroKind),
+    Module,
+}
+
 /// A free importable items suggested in case of resolution failure.
 struct ImportSuggestion {
     path: Path,
@@ -997,22 +1003,19 @@ impl<'a> LexicalScopeBinding<'a> {
     }
 }
 
-
-#[derive(Clone, Copy, PartialEq, Debug)]
-enum UniformRootKind {
-    CurrentScope,
-    ExternPrelude,
-}
-
 #[derive(Copy, Clone, Debug)]
 enum ModuleOrUniformRoot<'a> {
     /// Regular module.
     Module(Module<'a>),
 
-    /// This "virtual module" denotes either resolution in extern prelude
-    /// for paths starting with `::` on 2018 edition or `extern::`,
-    /// or resolution in current scope for single-segment imports.
-    UniformRoot(UniformRootKind),
+    /// Virtual module that denotes resolution in extern prelude.
+    /// Used for paths starting with `::` on 2018 edition or `extern::`.
+    ExternPrelude,
+
+    /// Virtual module that denotes resolution in current scope.
+    /// Used only for resolving single-segment imports. The reason it exists is that import paths
+    /// are always split into two parts, the first of which should be some kind of module.
+    CurrentScope,
 }
 
 impl<'a> PartialEq for ModuleOrUniformRoot<'a> {
@@ -1020,8 +1023,8 @@ impl<'a> PartialEq for ModuleOrUniformRoot<'a> {
         match (*self, *other) {
             (ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) =>
                 ptr::eq(lhs, rhs),
-            (ModuleOrUniformRoot::UniformRoot(lhs), ModuleOrUniformRoot::UniformRoot(rhs)) =>
-                lhs == rhs,
+            (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) => true,
+            (ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true,
             _ => false,
         }
     }
@@ -1758,8 +1761,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
                 error_callback(self, span, ResolutionError::FailedToResolve(msg));
                 Def::Err
             }
-            PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) |
-            PathResult::Indeterminate => unreachable!(),
+            PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
             PathResult::Failed(span, msg, _) => {
                 error_callback(self, span, ResolutionError::FailedToResolve(&msg));
                 Def::Err
@@ -2220,11 +2222,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                     self.current_module = self.macro_def_scope(def);
                 }
             }
-            ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude) => {
+            ModuleOrUniformRoot::ExternPrelude => {
                 ident.span = ident.span.modern();
                 ident.span.adjust(Mark::root());
             }
-            ModuleOrUniformRoot::UniformRoot(UniformRootKind::CurrentScope) => {
+            ModuleOrUniformRoot::CurrentScope => {
                 // No adjustments
             }
         }
@@ -3667,8 +3669,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                 resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
                 err_path_resolution()
             }
-            PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) |
-            PathResult::Failed(..) => return None,
+            PathResult::Module(..) | PathResult::Failed(..) => return None,
             PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"),
         };
 
@@ -3787,8 +3788,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                     }
                     if name == keywords::Extern.name() ||
                        name == keywords::CrateRoot.name() && ident.span.rust_2018() {
-                        module =
-                            Some(ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude));
+                        module = Some(ModuleOrUniformRoot::ExternPrelude);
                         continue;
                     }
                     if name == keywords::CrateRoot.name() ||
@@ -3821,9 +3821,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                 self.resolve_ident_in_module(module, ident, ns, None, record_used, path_span)
             } else if opt_ns.is_none() || opt_ns == Some(MacroNS) {
                 assert!(ns == TypeNS);
-                self.early_resolve_ident_in_lexical_scope(ident, ns, None, opt_ns.is_none(),
-                                                          parent_scope, record_used, record_used,
-                                                          path_span)
+                let scopes = if opt_ns.is_none() { ScopeSet::Import(ns) } else { ScopeSet::Module };
+                self.early_resolve_ident_in_lexical_scope(ident, scopes, parent_scope, record_used,
+                                                          record_used, path_span)
             } else {
                 let record_used_id =
                     if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None };
@@ -3912,8 +3912,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
 
         PathResult::Module(match module {
             Some(module) => module,
-            None if path.is_empty() =>
-                ModuleOrUniformRoot::UniformRoot(UniformRootKind::CurrentScope),
+            None if path.is_empty() => ModuleOrUniformRoot::CurrentScope,
             _ => span_bug!(path_span, "resolve_path: non-empty path `{:?}` has no module", path),
         })
     }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index bc3700b8c63..5493913fd81 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -9,11 +9,11 @@
 // except according to those terms.
 
 use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
-use {CrateLint, Resolver, ResolutionError, Segment, Weak};
-use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding};
+use {CrateLint, Resolver, ResolutionError, ScopeSet, Weak};
+use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding};
 use {is_known_tool, resolve_error};
 use ModuleOrUniformRoot;
-use Namespace::{self, *};
+use Namespace::*;
 use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
 use resolve_imports::ImportResolver;
 use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex,
@@ -502,7 +502,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
             def
         } else {
             let binding = self.early_resolve_ident_in_lexical_scope(
-                path[0].ident, MacroNS, Some(kind), false, parent_scope, false, force, path_span
+                path[0].ident, ScopeSet::Macro(kind), parent_scope, false, force, path_span
             );
             match binding {
                 Ok(..) => {}
@@ -527,9 +527,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
     crate fn early_resolve_ident_in_lexical_scope(
         &mut self,
         orig_ident: Ident,
-        ns: Namespace,
-        macro_kind: Option<MacroKind>,
-        is_import: bool,
+        scope_set: ScopeSet,
         parent_scope: &ParentScope<'a>,
         record_used: bool,
         force: bool,
@@ -605,8 +603,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
         }
 
         assert!(force || !record_used); // `record_used` implies `force`
-        assert!(macro_kind.is_none() || !is_import); // `is_import` implies no macro kind
-        let rust_2015 = orig_ident.span.rust_2015();
         let mut ident = orig_ident.modern();
 
         // Make sure `self`, `super` etc produce an error when passed to here.
@@ -628,6 +624,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
         let mut innermost_result: Option<(&NameBinding, Flags)> = None;
 
         // Go through all the scopes and try to resolve the name.
+        let rust_2015 = orig_ident.span.rust_2015();
+        let (ns, macro_kind, is_import) = match scope_set {
+            ScopeSet::Import(ns) => (ns, None, true),
+            ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false),
+            ScopeSet::Module => (TypeNS, None, false),
+        };
         let mut where_to_resolve = match ns {
             _ if is_import && rust_2015 => WhereToResolve::CrateRoot,
             TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module),
@@ -1041,7 +1043,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
         let macro_resolutions =
             mem::replace(&mut *module.single_segment_macro_resolutions.borrow_mut(), Vec::new());
         for (ident, kind, parent_scope, initial_binding) in macro_resolutions {
-            match self.early_resolve_ident_in_lexical_scope(ident, MacroNS, Some(kind), false,
+            match self.early_resolve_ident_in_lexical_scope(ident, ScopeSet::Macro(kind),
                                                             &parent_scope, true, true, ident.span) {
                 Ok(binding) => {
                     let initial_def = initial_binding.map(|initial_binding| {
@@ -1067,7 +1069,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
         let builtin_attrs = mem::replace(&mut *module.builtin_attrs.borrow_mut(), Vec::new());
         for (ident, parent_scope) in builtin_attrs {
             let _ = self.early_resolve_ident_in_lexical_scope(
-                ident, MacroNS, Some(MacroKind::Attr), false, &parent_scope, true, true, ident.span
+                ident, ScopeSet::Macro(MacroKind::Attr), &parent_scope, true, true, ident.span
             );
         }
     }
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 52e3e54b9f9..47bfadf932e 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -11,7 +11,7 @@
 use self::ImportDirectiveSubclass::*;
 
 use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
-use {CrateLint, Module, ModuleOrUniformRoot, PerNS, UniformRootKind, Weak};
+use {CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, Weak};
 use Namespace::{self, TypeNS, MacroNS};
 use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
 use {Resolver, Segment};
@@ -162,45 +162,42 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
     ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
         let module = match module {
             ModuleOrUniformRoot::Module(module) => module,
-            ModuleOrUniformRoot::UniformRoot(uniform_root_kind) => {
+            ModuleOrUniformRoot::ExternPrelude => {
                 assert!(!restricted_shadowing);
-                match uniform_root_kind {
-                    UniformRootKind::ExternPrelude => {
-                        return if let Some(binding) = self.extern_prelude_get(ident, !record_used) {
-                            Ok(binding)
-                        } else if !self.graph_root.unresolved_invocations.borrow().is_empty() {
-                            // Macro-expanded `extern crate` items can add names to extern prelude.
-                            Err((Undetermined, Weak::No))
-                        } else {
-                            Err((Determined, Weak::No))
-                        }
-                    }
-                    UniformRootKind::CurrentScope => {
-                        let parent_scope =
-                            parent_scope.expect("no parent scope for a single-segment import");
-
-                        if ns == TypeNS {
-                            if ident.name == keywords::Crate.name() ||
-                               ident.name == keywords::DollarCrate.name() {
-                                let module = self.resolve_crate_root(ident);
-                                let binding = (module, ty::Visibility::Public,
-                                               module.span, Mark::root())
-                                               .to_name_binding(self.arenas);
-                                return Ok(binding);
-                            } else if ident.name == keywords::Super.name() ||
-                                      ident.name == keywords::SelfValue.name() {
-                                // FIXME: Implement these with renaming requirements so that e.g.
-                                // `use super;` doesn't work, but `use super as name;` does.
-                                // Fall through here to get an error from `early_resolve_...`.
-                            }
-                        }
-
-                        let binding = self.early_resolve_ident_in_lexical_scope(
-                            ident, ns, None, true, parent_scope, record_used, record_used, path_span
-                        );
-                        return binding.map_err(|determinacy| (determinacy, Weak::No));
+                return if let Some(binding) = self.extern_prelude_get(ident, !record_used) {
+                    Ok(binding)
+                } else if !self.graph_root.unresolved_invocations.borrow().is_empty() {
+                    // Macro-expanded `extern crate` items can add names to extern prelude.
+                    Err((Undetermined, Weak::No))
+                } else {
+                    Err((Determined, Weak::No))
+                }
+            }
+            ModuleOrUniformRoot::CurrentScope => {
+                assert!(!restricted_shadowing);
+                let parent_scope =
+                    parent_scope.expect("no parent scope for a single-segment import");
+
+                if ns == TypeNS {
+                    if ident.name == keywords::Crate.name() ||
+                        ident.name == keywords::DollarCrate.name() {
+                        let module = self.resolve_crate_root(ident);
+                        let binding = (module, ty::Visibility::Public,
+                                        module.span, Mark::root())
+                                        .to_name_binding(self.arenas);
+                        return Ok(binding);
+                    } else if ident.name == keywords::Super.name() ||
+                                ident.name == keywords::SelfValue.name() {
+                        // FIXME: Implement these with renaming requirements so that e.g.
+                        // `use super;` doesn't work, but `use super as name;` does.
+                        // Fall through here to get an error from `early_resolve_...`.
                     }
                 }
+
+                let binding = self.early_resolve_ident_in_lexical_scope(
+                    ident, ScopeSet::Import(ns), parent_scope, record_used, record_used, path_span
+                );
+                return binding.map_err(|determinacy| (determinacy, Weak::No));
             }
         };
 
@@ -333,7 +330,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
             }
             let module = match glob_import.imported_module.get() {
                 Some(ModuleOrUniformRoot::Module(module)) => module,
-                Some(ModuleOrUniformRoot::UniformRoot(_)) => continue,
+                Some(_) => continue,
                 None => return Err((Undetermined, Weak::Yes)),
             };
             let (orig_current_module, mut ident) = (self.current_module, ident.modern());
@@ -966,9 +963,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
 
             return if all_ns_failed {
                 let resolutions = match module {
-                    ModuleOrUniformRoot::Module(module) =>
-                        Some(module.resolutions.borrow()),
-                    ModuleOrUniformRoot::UniformRoot(_) => None,
+                    ModuleOrUniformRoot::Module(module) => Some(module.resolutions.borrow()),
+                    _ => None,
                 };
                 let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter());
                 let names = resolutions.filter_map(|(&(ref i, _), resolution)| {
@@ -1006,7 +1002,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
                             format!("no `{}` in the root{}", ident, lev_suggestion)
                         }
                     }
-                    ModuleOrUniformRoot::UniformRoot(_) => {
+                    _ => {
                         if !ident.is_path_segment_keyword() {
                             format!("no `{}` external crate{}", ident, lev_suggestion)
                         } else {
@@ -1107,9 +1103,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
     fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
         let module = match directive.imported_module.get().unwrap() {
             ModuleOrUniformRoot::Module(module) => module,
-            ModuleOrUniformRoot::UniformRoot(_) => {
-                self.session.span_err(directive.span,
-                    "cannot glob-import all possible crates");
+            _ => {
+                self.session.span_err(directive.span, "cannot glob-import all possible crates");
                 return;
             }
         };