Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] resolve: Fallback to extern crates in absolute paths on 2015 edition #57745

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/librustc_resolve/build_reduced_graph.rs
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
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
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
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to extract this out to a new method (+ comment on that) since it's repeated below.

);
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
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
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
@@ -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.

@@ -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
@@ -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
@@ -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
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
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
@@ -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`
}
@@ -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
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
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
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
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