]> git.lizzy.rs Git - rust.git/commitdiff
resolve: Fallback to extern prelude in 2015 imports used from global 2018 edition
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sat, 24 Nov 2018 21:25:03 +0000 (00:25 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Mon, 26 Nov 2018 21:34:24 +0000 (00:34 +0300)
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/test/ui/editions/auxiliary/edition-imports-2015.rs
src/test/ui/editions/edition-imports-2018.rs
src/test/ui/editions/edition-imports-2018.stderr [new file with mode: 0644]
src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs
src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr

index bc0e8a56157e56294e75c9dbacf7e89f63685142..0be9881f910b78f0fede1bfcbefe59583ebed486 100644 (file)
@@ -104,6 +104,7 @@ enum Weak {
 
 enum ScopeSet {
     Import(Namespace),
+    AbsolutePath(Namespace),
     Macro(MacroKind),
     Module,
 }
@@ -1008,6 +1009,9 @@ enum ModuleOrUniformRoot<'a> {
     /// Regular module.
     Module(Module<'a>),
 
+    /// Virtual module that denotes resolution in crate root with fallback to extern prelude.
+    CrateRootAndExternPrelude,
+
     /// Virtual module that denotes resolution in extern prelude.
     /// Used for paths starting with `::` on 2018 edition or `extern::`.
     ExternPrelude,
@@ -1021,9 +1025,11 @@ enum ModuleOrUniformRoot<'a> {
 impl<'a> PartialEq for ModuleOrUniformRoot<'a> {
     fn eq(&self, other: &Self) -> bool {
         match (*self, *other) {
-            (ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) =>
-                ptr::eq(lhs, rhs),
-            (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) => true,
+            (ModuleOrUniformRoot::Module(lhs),
+             ModuleOrUniformRoot::Module(rhs)) => ptr::eq(lhs, rhs),
+            (ModuleOrUniformRoot::CrateRootAndExternPrelude,
+             ModuleOrUniformRoot::CrateRootAndExternPrelude) |
+            (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) |
             (ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true,
             _ => false,
         }
@@ -1243,6 +1249,7 @@ struct UseError<'a> {
 #[derive(Clone, Copy, PartialEq, Debug)]
 enum AmbiguityKind {
     Import,
+    AbsolutePath,
     BuiltinAttr,
     DeriveHelper,
     LegacyHelperVsPrelude,
@@ -1258,6 +1265,8 @@ fn descr(self) -> &'static str {
         match self {
             AmbiguityKind::Import =>
                 "name vs any other name during import resolution",
+            AmbiguityKind::AbsolutePath =>
+                "name in the crate root vs extern crate during absolute path resolution",
             AmbiguityKind::BuiltinAttr =>
                 "built-in attribute vs any other name",
             AmbiguityKind::DeriveHelper =>
@@ -2226,6 +2235,7 @@ fn resolve_ident_in_module_ext(
                 ident.span = ident.span.modern();
                 ident.span.adjust(Mark::root());
             }
+            ModuleOrUniformRoot::CrateRootAndExternPrelude |
             ModuleOrUniformRoot::CurrentScope => {
                 // No adjustments
             }
@@ -3791,6 +3801,12 @@ fn resolve_path(
                         module = Some(ModuleOrUniformRoot::ExternPrelude);
                         continue;
                     }
+                    if name == keywords::CrateRoot.name() &&
+                       ident.span.rust_2015() && self.session.rust_2018() {
+                        // `::a::b` from 2015 macro on 2018 global edition
+                        module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude);
+                        continue;
+                    }
                     if name == keywords::CrateRoot.name() ||
                        name == keywords::Crate.name() ||
                        name == keywords::DollarCrate.name() {
index 5493913fd811d121f280af857d319aabcc1434f7..d306e9ebe32b5f3222fd6eb9c93bcabfac66b25b 100644 (file)
@@ -625,13 +625,14 @@ struct Flags: u8 {
 
         // 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 (ns, macro_kind, is_import, is_absolute_path) = match scope_set {
+            ScopeSet::Import(ns) => (ns, None, true, false),
+            ScopeSet::AbsolutePath(ns) => (ns, None, false, true),
+            ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false, false),
+            ScopeSet::Module => (TypeNS, None, false, false),
         };
         let mut where_to_resolve = match ns {
-            _ if is_import && rust_2015 => WhereToResolve::CrateRoot,
+            _ if is_absolute_path || is_import && rust_2015 => WhereToResolve::CrateRoot,
             TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module),
             MacroNS => WhereToResolve::DeriveHelpers,
         };
@@ -761,7 +762,7 @@ struct Flags: u8 {
                     }
                 }
                 WhereToResolve::ExternPrelude => {
-                    if use_prelude {
+                    if use_prelude || is_absolute_path {
                         match self.extern_prelude_get(ident, !record_used) {
                             Some(binding) => Ok((binding, Flags::PRELUDE)),
                             None => Err(Determinacy::determined(
@@ -827,6 +828,8 @@ struct Flags: u8 {
 
                             let ambiguity_error_kind = if is_import {
                                 Some(AmbiguityKind::Import)
+                            } else if is_absolute_path {
+                                Some(AmbiguityKind::AbsolutePath)
                             } else if innermost_def == builtin || def == builtin {
                                 Some(AmbiguityKind::BuiltinAttr)
                             } else if innermost_def == derive_helper || def == derive_helper {
@@ -894,10 +897,18 @@ struct Flags: u8 {
                     LegacyScope::Empty => WhereToResolve::Module(parent_scope.module),
                     LegacyScope::Uninitialized => unreachable!(),
                 }
-                WhereToResolve::CrateRoot => match ns {
+                WhereToResolve::CrateRoot if is_import => match ns {
                     TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module),
                     MacroNS => WhereToResolve::DeriveHelpers,
                 }
+                WhereToResolve::CrateRoot if is_absolute_path => match ns {
+                    TypeNS => {
+                        ident.span.adjust(Mark::root());
+                        WhereToResolve::ExternPrelude
+                    }
+                    ValueNS | MacroNS => break,
+                }
+                WhereToResolve::CrateRoot => unreachable!(),
                 WhereToResolve::Module(module) => {
                     match self.hygienic_lexical_parent(module, &mut ident.span) {
                         Some(parent_module) => WhereToResolve::Module(parent_module),
@@ -915,6 +926,7 @@ struct Flags: u8 {
                 WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs,
                 WhereToResolve::BuiltinAttrs => WhereToResolve::LegacyPluginHelpers,
                 WhereToResolve::LegacyPluginHelpers => break, // nowhere else to search
+                WhereToResolve::ExternPrelude if is_absolute_path => break,
                 WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude,
                 WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude,
                 WhereToResolve::StdLibPrelude => match ns {
index 47bfadf932e56769e9348aa6afe8f018a4e70dca..3bfa862f0dc7dc8a355c8914a2e2037ffa278270 100644 (file)
@@ -162,6 +162,15 @@ fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace)
     ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
         let module = match module {
             ModuleOrUniformRoot::Module(module) => module,
+            ModuleOrUniformRoot::CrateRootAndExternPrelude => {
+                assert!(!restricted_shadowing);
+                let parent_scope = self.dummy_parent_scope();
+                let binding = self.early_resolve_ident_in_lexical_scope(
+                    ident, ScopeSet::AbsolutePath(ns), &parent_scope,
+                    record_used, record_used, path_span,
+                );
+                return binding.map_err(|determinacy| (determinacy, Weak::No));
+            }
             ModuleOrUniformRoot::ExternPrelude => {
                 assert!(!restricted_shadowing);
                 return if let Some(binding) = self.extern_prelude_get(ident, !record_used) {
index d7985d12dae619bafd2742d724a085533df89947..c72331ca2e119e62c39f3f91b9fcd33363742837 100644 (file)
@@ -7,7 +7,7 @@ macro_rules! gen_imports { () => {
 
     fn check_absolute() {
         ::absolute::Path;
-        // ::std::collections::LinkedList::<u8>::new(); // FIXME
+        ::std::collections::LinkedList::<u8>::new();
     }
 }}
 
@@ -27,4 +27,5 @@ enum E { A }
 #[macro_export]
 macro_rules! gen_ambiguous { () => {
     use Ambiguous;
+    type A = ::edition_imports_2015::Path;
 }}
index 989170d041fe72ac10d53e5e498d48b52f720804..dcdbf0d050be116f9a8ad1574110d83bc4c5974b 100644 (file)
@@ -1,4 +1,3 @@
-// compile-pass
 // edition:2018
 // aux-build:edition-imports-2015.rs
 
@@ -22,12 +21,7 @@ fn check() {
 }
 
 mod check_glob {
-    gen_glob!(); // OK
-
-    fn check() {
-        import::Path;
-        absolute::Path;
-    }
+    gen_glob!(); //~ ERROR cannot glob-import all possible crates
 }
 
 fn main() {}
diff --git a/src/test/ui/editions/edition-imports-2018.stderr b/src/test/ui/editions/edition-imports-2018.stderr
new file mode 100644 (file)
index 0000000..944f42e
--- /dev/null
@@ -0,0 +1,10 @@
+error: cannot glob-import all possible crates
+  --> $DIR/edition-imports-2018.rs:24:5
+   |
+LL |     gen_glob!(); //~ ERROR cannot glob-import all possible crates
+   |     ^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
index 2527b30f07b332801c21330d0867be5a3c8abe8d..562d3c9e70fb1153d392469a43a50dfdc76dab98 100644 (file)
@@ -1,9 +1,12 @@
 // edition:2018
+// compile-flags:--extern edition_imports_2015
 // aux-build:edition-imports-2015.rs
 // error-pattern: `Ambiguous` is ambiguous
+// error-pattern: `edition_imports_2015` is ambiguous
 
-#[macro_use]
-extern crate edition_imports_2015;
+mod edition_imports_2015 {
+    pub struct Path;
+}
 
 pub struct Ambiguous {}
 
@@ -11,7 +14,7 @@ mod check {
     pub struct Ambiguous {}
 
     fn check() {
-        gen_ambiguous!();
+        edition_imports_2015::gen_ambiguous!();
     }
 }
 
index 8e0b135121e0749dadb420d7fc2947501ba2f5c7..d0897d081c3574c7112aa9ee60c7841a89a97379 100644 (file)
@@ -1,21 +1,37 @@
 error[E0659]: `Ambiguous` is ambiguous (name vs any other name during import resolution)
   --> <::edition_imports_2015::gen_ambiguous macros>:1:15
    |
-LL | (  ) => { use Ambiguous ; }
+LL | (  ) => { use Ambiguous ; type A = :: edition_imports_2015 :: Path ; }
    |               ^^^^^^^^^ ambiguous name
    |
 note: `Ambiguous` could refer to the struct defined here
-  --> $DIR/edition-imports-virtual-2015-ambiguity.rs:8:1
+  --> $DIR/edition-imports-virtual-2015-ambiguity.rs:11:1
    |
 LL | pub struct Ambiguous {}
    | ^^^^^^^^^^^^^^^^^^^^^^^
 note: `Ambiguous` could also refer to the struct defined here
-  --> $DIR/edition-imports-virtual-2015-ambiguity.rs:11:5
+  --> $DIR/edition-imports-virtual-2015-ambiguity.rs:14:5
    |
 LL |     pub struct Ambiguous {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    = help: use `self::Ambiguous` to refer to this struct unambiguously
 
-error: aborting due to previous error
+error[E0659]: `edition_imports_2015` is ambiguous (name in the crate root vs extern crate during absolute path resolution)
+  --> <::edition_imports_2015::gen_ambiguous macros>:1:39
+   |
+LL | (  ) => { use Ambiguous ; type A = :: edition_imports_2015 :: Path ; }
+   |                                       ^^^^^^^^^^^^^^^^^^^^ ambiguous name
+   |
+   = note: `edition_imports_2015` could refer to an extern crate passed with `--extern`
+   = help: use `::edition_imports_2015` to refer to this extern crate unambiguously
+note: `edition_imports_2015` could also refer to the module defined here
+  --> $DIR/edition-imports-virtual-2015-ambiguity.rs:7:1
+   |
+LL | / mod edition_imports_2015 {
+LL | |     pub struct Path;
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0659`.