Skip to content

Commit

Permalink
resolve: Fallback to extern crates in absolute paths on 2015 edition
Browse files Browse the repository at this point in the history
  • Loading branch information
petrochenkov committed Jan 18, 2019
1 parent f613dc1 commit bd4a554
Show file tree
Hide file tree
Showing 48 changed files with 102 additions and 199 deletions.
3 changes: 1 addition & 2 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,7 @@ impl<'a> Resolver<'a> {
// get crate root prepended, but get special treatment during in-scope resolution instead.
let is_glob = if let ast::UseTreeKind::Glob = use_tree.kind { true } else { false };
let crate_root = match prefix_iter.peek() {
Some(seg) if !seg.ident.is_path_segment_keyword() &&
seg.ident.span.rust_2015() && self.session.rust_2015() => {
Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.rust_2015() => {
Some(seg.ident.span.ctxt())
}
None if is_glob && use_tree.span.rust_2015() => {
Expand Down
29 changes: 15 additions & 14 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1243,7 +1243,7 @@ struct UseError<'a> {
#[derive(Clone, Copy, PartialEq, Debug)]
enum AmbiguityKind {
Import,
AbsolutePath,
// AbsolutePath,
BuiltinAttr,
DeriveHelper,
LegacyHelperVsPrelude,
Expand All @@ -1259,8 +1259,8 @@ impl AmbiguityKind {
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::AbsolutePath =>
// "name in the crate root vs extern crate during absolute path resolution",
AmbiguityKind::BuiltinAttr =>
"built-in attribute vs any other name",
AmbiguityKind::DeriveHelper =>
Expand Down Expand Up @@ -1513,6 +1513,8 @@ pub struct Resolver<'a> {
/// FIXME: Refactor things so that these fields are passed through arguments and not resolver.
/// We are resolving a last import segment during import validation.
last_import_segment: bool,
/// We are resolving a prefix for `use *` or `use ::*` on 2015 edition.
root_glob_import: bool,
/// This binding should be ignored during in-module resolution, so that we don't get
/// "self-confirming" import resolutions during import validation.
blacklisted_binding: Option<&'a NameBinding<'a>>,
Expand Down Expand Up @@ -1861,6 +1863,7 @@ impl<'a> Resolver<'a> {
current_self_type: None,
current_self_item: None,
last_import_segment: false,
root_glob_import: false,
blacklisted_binding: None,

primitive_type_table: PrimitiveTypeTable::new(),
Expand Down Expand Up @@ -3833,19 +3836,17 @@ impl<'a> Resolver<'a> {
self.resolve_self(&mut ctxt, self.current_module)));
continue;
}
if name == keywords::PathRoot.name() && ident.span.rust_2018() {
module = Some(ModuleOrUniformRoot::ExternPrelude);
continue;
}
if name == keywords::PathRoot.name() &&
ident.span.rust_2015() && self.session.rust_2018() {
// `::a::b` from 2015 macro on 2018 global edition
module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude);
if name == keywords::PathRoot.name() {
module = Some(if ident.span.rust_2018() {
ModuleOrUniformRoot::ExternPrelude
} else if !self.root_glob_import {
ModuleOrUniformRoot::CrateRootAndExternPrelude
} else {
ModuleOrUniformRoot::Module(self.resolve_crate_root(ident))
});
continue;
}
if name == keywords::PathRoot.name() ||
name == keywords::Crate.name() ||
name == keywords::DollarCrate.name() {
if name == keywords::Crate.name() || name == keywords::DollarCrate.name() {
// `::a::b`, `crate::a::b` or `$crate::a::b`
module = Some(ModuleOrUniformRoot::Module(
self.resolve_crate_root(ident)));
Expand Down
41 changes: 1 addition & 40 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -709,8 +709,6 @@ impl<'a> Resolver<'a> {

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 {
Expand Down Expand Up @@ -824,44 +822,7 @@ impl<'a> Resolver<'a> {
}

// The first found solution was the only one, return it.
if let Some((binding, flags)) = innermost_result {
// We get to here only if there's no ambiguity, in ambiguous cases an error will
// be reported anyway, so there's no reason to report an additional feature error.
// The `binding` can actually be introduced by something other than `--extern`,
// but its `Def` should coincide with a crate passed with `--extern`
// (otherwise there would be ambiguity) and we can skip feature error in this case.
'ok: {
if !is_import || !rust_2015 {
break 'ok;
}
if ns == TypeNS && use_prelude && self.extern_prelude_get(ident, true).is_some() {
break 'ok;
}
let root_ident = Ident::new(keywords::PathRoot.name(), orig_ident.span);
let root_module = self.resolve_crate_root(root_ident);
if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module),
orig_ident, ns, None, false, path_span)
.is_ok() {
break 'ok;
}

let msg = "imports can only refer to extern crate names passed with \
`--extern` in macros originating from 2015 edition";
let mut err = self.session.struct_span_err(ident.span, msg);
let what = self.binding_description(binding, ident,
flags.contains(Flags::MISC_FROM_PRELUDE));
let note_msg = format!("this import refers to {what}", what = what);
let label_span = if binding.span.is_dummy() {
err.note(&note_msg);
ident.span
} else {
err.span_note(binding.span, &note_msg);
binding.span
};
err.span_label(label_span, "not an extern crate passed with `--extern`");
err.emit();
}

if let Some((binding, _)) = innermost_result {
return Ok(binding);
}

Expand Down
8 changes: 8 additions & 0 deletions src/librustc_resolve/resolve_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
} else {
// For better failure detection, pretend that the import will
// not define any names while resolving its module path.
let orig_root_glob_import = mem::replace(
&mut self.root_glob_import, directive.is_glob() && directive.module_path.len() == 1
);
let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
let path_res = self.resolve_path(
&directive.module_path,
Expand All @@ -775,6 +778,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
directive.crate_lint(),
);
directive.vis.set(orig_vis);
self.root_glob_import = orig_root_glob_import;

match path_res {
PathResult::Module(module) => module,
Expand Down Expand Up @@ -850,12 +854,16 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
) -> Option<(Span, String, Option<String>)> {
self.current_module = directive.parent_scope.module;

let orig_root_glob_import = mem::replace(
&mut self.root_glob_import, directive.is_glob() && directive.module_path.len() == 1
);
let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
let prev_ambiguity_errors_len = self.ambiguity_errors.len();
let path_res = self.resolve_path(&directive.module_path, None, &directive.parent_scope,
true, directive.span, directive.crate_lint());
let no_ambiguity = self.ambiguity_errors.len() == prev_ambiguity_errors_len;
directive.vis.set(orig_vis);
self.root_glob_import = orig_root_glob_import;
let module = match path_res {
PathResult::Module(module) => {
// Consistency checks, analogous to `finalize_current_module_macro_resolutions`.
Expand Down
3 changes: 1 addition & 2 deletions src/test/run-make-fulldeps/extern-prelude/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ all:
$(RUSTC) basic.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib
$(RUSTC) shadow-mod.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib
$(RUSTC) shadow-prelude.rs --extern Vec=$(TMPDIR)/libep_vec.rlib
$(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "unresolved import"
$(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "failed to resolve"
$(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ error[E0432]: unresolved import `Foo`
--> $DIR/issue-38054-do-not-show-unresolved-names.rs:1:5
|
LL | use Foo; //~ ERROR unresolved
| ^^^ no `Foo` in the root
| ^^^ no `Foo` external crate

error[E0432]: unresolved import `Foo1`
--> $DIR/issue-38054-do-not-show-unresolved-names.rs:3:5
|
LL | use Foo1; //~ ERROR unresolved
| ^^^^ no `Foo1` in the root
| ^^^^ no `Foo1` external crate

error: aborting due to 2 previous errors

Expand Down
3 changes: 2 additions & 1 deletion src/test/ui/editions/edition-imports-2018.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// compile-pass
// edition:2018
// aux-build:edition-imports-2015.rs

Expand All @@ -21,7 +22,7 @@ mod check {
}

mod check_glob {
gen_glob!(); //~ ERROR cannot glob-import all possible crates
gen_glob!(); // OK
}

fn main() {}
10 changes: 0 additions & 10 deletions src/test/ui/editions/edition-imports-2018.stderr

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// compile-pass
// edition:2018
// compile-flags:--extern edition_imports_2015
// aux-build:edition-imports-2015.rs
Expand All @@ -12,8 +13,7 @@ mod check {
pub struct Ambiguous {}

fn check() {
edition_imports_2015::gen_ambiguous!(); //~ ERROR `Ambiguous` is ambiguous
//~| ERROR `edition_imports_2015` is ambiguous
edition_imports_2015::gen_ambiguous!();
}
}

Expand Down
40 changes: 0 additions & 40 deletions src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr

This file was deleted.

3 changes: 1 addition & 2 deletions src/test/ui/editions/edition-imports-virtual-2015-gated.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
// edition:2018
// aux-build:edition-imports-2015.rs
// error-pattern: imports can only refer to extern crate names passed with `--extern`

#[macro_use]
extern crate edition_imports_2015;

mod check {
gen_gated!();
gen_gated!(); //~ ERROR unresolved import `E`
}

fn main() {}
19 changes: 5 additions & 14 deletions src/test/ui/editions/edition-imports-virtual-2015-gated.stderr
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
error: imports can only refer to extern crate names passed with `--extern` in macros originating from 2015 edition
--> <::edition_imports_2015::gen_gated macros>:1:50
error[E0432]: unresolved import `E`
--> $DIR/edition-imports-virtual-2015-gated.rs:8:5
|
LL | ( ) => { fn check_gated ( ) { enum E { A } use E :: * ; } }
| ^
|
::: $DIR/edition-imports-virtual-2015-gated.rs:9:5
LL | gen_gated!(); //~ ERROR unresolved import `E`
| ^^^^^^^^^^^^^ could not find `E` in `{{root}}`
|
LL | gen_gated!();
| ------------- not an extern crate passed with `--extern`
|
note: this import refers to the enum defined here
--> $DIR/edition-imports-virtual-2015-gated.rs:9:5
|
LL | gen_gated!();
| ^^^^^^^^^^^^^
= 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

For more information about this error, try `rustc --explain E0432`.
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0432.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0432]: unresolved import `something`
--> $DIR/E0432.rs:1:5
|
LL | use something::Foo; //~ ERROR E0432
| ^^^^^^^^^ maybe a missing `extern crate something;`?
| ^^^^^^^^^ could not find `something` in `{{root}}`

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/extenv/issue-55897.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ error[E0432]: unresolved import `prelude`
--> $DIR/issue-55897.rs:1:5
|
LL | use prelude::*; //~ ERROR unresolved import `prelude`
| ^^^^^^^ did you mean `std::prelude`?
| ^^^^^^^ could not find `prelude` in `{{root}}`

error: cannot determine resolution for the macro `env`
--> $DIR/issue-55897.rs:6:22
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use core::default; //~ ERROR unresolved import `core`
use core::default;

fn main() {
let _: u8 = ::core::default::Default(); //~ ERROR failed to resolve
let _: u8 = ::core::default::Default();
//~^ ERROR expected function, found trait `core::default::Default`
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
error[E0432]: unresolved import `core`
--> $DIR/feature-gate-extern_absolute_paths.rs:1:5
error[E0423]: expected function, found trait `core::default::Default`
--> $DIR/feature-gate-extern_absolute_paths.rs:4:17
|
LL | use core::default; //~ ERROR unresolved import `core`
| ^^^^ maybe a missing `extern crate core;`?
LL | let _: u8 = ::core::default::Default();
| ^^^^^^^^^^^^^^^^^^^^^^^^ not a function

error[E0433]: failed to resolve: maybe a missing `extern crate core;`?
--> $DIR/feature-gate-extern_absolute_paths.rs:4:19
|
LL | let _: u8 = ::core::default::Default(); //~ ERROR failed to resolve
| ^^^^ maybe a missing `extern crate core;`?

error: aborting due to 2 previous errors
error: aborting due to previous error

Some errors occurred: E0432, E0433.
For more information about an error, try `rustc --explain E0432`.
For more information about this error, try `rustc --explain E0423`.
2 changes: 1 addition & 1 deletion src/test/ui/hidden-rt-injection.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0432]: unresolved import `native`
--> $DIR/hidden-rt-injection.rs:5:9
|
LL | use native; //~ ERROR unresolved import
| ^^^^^^ no `native` in the root
| ^^^^^^ no `native` external crate

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/hidden-rt-injection2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0432]: unresolved import `rt`
--> $DIR/hidden-rt-injection2.rs:5:9
|
LL | use rt; //~ ERROR unresolved import
| ^^ no `rt` in the root
| ^^ no `rt` external crate

error: aborting due to previous error

Expand Down
1 change: 0 additions & 1 deletion src/test/ui/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use zed::baz; //~ ERROR unresolved import `zed::baz` [E0432]
mod zed {
pub fn bar() { println!("bar"); }
use foo; //~ ERROR unresolved import `foo` [E0432]
//~^ no `foo` in the root
}

fn main() {
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/import.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ error[E0432]: unresolved import `foo`
--> $DIR/import.rs:8:9
|
LL | use foo; //~ ERROR unresolved import `foo` [E0432]
| ^^^ no `foo` in the root
| ^^^ no `foo` external crate

error[E0603]: unresolved item `foo` is private
--> $DIR/import.rs:13:10
--> $DIR/import.rs:12:10
|
LL | zed::foo(); //~ ERROR `foo` is private
| ^^^
Expand Down
Loading

0 comments on commit bd4a554

Please sign in to comment.