Skip to content

Commit

Permalink
Rollup merge of rust-lang#91045 - mjptree:issue-90702-fix, r=petroche…
Browse files Browse the repository at this point in the history
…nkov

Issue 90702 fix: Stop treating some crate loading failures as fatal errors

Surface mulitple `extern crate` resolution errors at a time.

This is achieved by creating a dummy crate, instead of aborting directly after the resolution error. The `ExternCrateError` has been added to allow propagating the resolution error from `rustc_metadata` crate to the `rustc_resolve` with a minimal public surface. The `import_extern_crate` function is a block that was factored out from `build_reduced_graph_for_item` for better organization. The only added functionality made to it where the added error handling in the `process_extern_crate` call. The remaining bits in this function are the same as before.

Resolves rust-lang#90702

r? ``@petrochenkov``
  • Loading branch information
matthiaskrgr committed Nov 30, 2021
2 parents f84065f + 2c9d9b4 commit 9f1cbdf
Show file tree
Hide file tree
Showing 17 changed files with 208 additions and 106 deletions.
32 changes: 18 additions & 14 deletions compiler/rustc_metadata/src/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,13 +512,17 @@ impl<'a> CrateLoader<'a> {
name: Symbol,
span: Span,
dep_kind: CrateDepKind,
) -> CrateNum {
) -> Option<CrateNum> {
self.used_extern_options.insert(name);
self.maybe_resolve_crate(name, dep_kind, None).unwrap_or_else(|err| {
let missing_core =
self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err();
err.report(&self.sess, span, missing_core)
})
match self.maybe_resolve_crate(name, dep_kind, None) {
Ok(cnum) => Some(cnum),
Err(err) => {
let missing_core =
self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err();
err.report(&self.sess, span, missing_core);
None
}
}
}

fn maybe_resolve_crate<'b>(
Expand Down Expand Up @@ -751,7 +755,7 @@ impl<'a> CrateLoader<'a> {
};
info!("panic runtime not found -- loading {}", name);

let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit);
let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; };
let data = self.cstore.get_crate_data(cnum);

// Sanity check the loaded crate to ensure it is indeed a panic runtime
Expand Down Expand Up @@ -791,7 +795,7 @@ impl<'a> CrateLoader<'a> {
);
}

let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit);
let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; };
let data = self.cstore.get_crate_data(cnum);

// Sanity check the loaded crate to ensure it is indeed a profiler runtime
Expand Down Expand Up @@ -991,7 +995,7 @@ impl<'a> CrateLoader<'a> {
item: &ast::Item,
definitions: &Definitions,
def_id: LocalDefId,
) -> CrateNum {
) -> Option<CrateNum> {
match item.kind {
ast::ItemKind::ExternCrate(orig_name) => {
debug!(
Expand All @@ -1011,7 +1015,7 @@ impl<'a> CrateLoader<'a> {
CrateDepKind::Explicit
};

let cnum = self.resolve_crate(name, item.span, dep_kind);
let cnum = self.resolve_crate(name, item.span, dep_kind)?;

let path_len = definitions.def_path(def_id).data.len();
self.update_extern_crate(
Expand All @@ -1023,14 +1027,14 @@ impl<'a> CrateLoader<'a> {
dependency_of: LOCAL_CRATE,
},
);
cnum
Some(cnum)
}
_ => bug!(),
}
}

pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum {
let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit);
pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> Option<CrateNum> {
let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit)?;

self.update_extern_crate(
cnum,
Expand All @@ -1043,7 +1047,7 @@ impl<'a> CrateLoader<'a> {
},
);

cnum
Some(cnum)
}

pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> {
Expand Down
18 changes: 8 additions & 10 deletions compiler/rustc_metadata/src/locator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::owning_ref::OwningRef;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::MetadataRef;
use rustc_errors::struct_span_err;
use rustc_errors::{struct_span_err, FatalError};
use rustc_session::config::{self, CrateType};
use rustc_session::cstore::{CrateSource, MetadataLoader};
use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch};
Expand Down Expand Up @@ -814,11 +814,11 @@ pub fn find_plugin_registrar(
span: Span,
name: Symbol,
) -> PathBuf {
match find_plugin_registrar_impl(sess, metadata_loader, name) {
Ok(res) => res,
find_plugin_registrar_impl(sess, metadata_loader, name).unwrap_or_else(|err| {
// `core` is always available if we got as far as loading plugins.
Err(err) => err.report(sess, span, false),
}
err.report(sess, span, false);
FatalError.raise()
})
}

fn find_plugin_registrar_impl<'a>(
Expand Down Expand Up @@ -931,8 +931,8 @@ impl fmt::Display for MetadataError<'_> {
}

impl CrateError {
crate fn report(self, sess: &Session, span: Span, missing_core: bool) -> ! {
let mut err = match self {
crate fn report(self, sess: &Session, span: Span, missing_core: bool) {
let mut diag = match self {
CrateError::NonAsciiName(crate_name) => sess.struct_span_err(
span,
&format!("cannot load a crate with a non-ascii name `{}`", crate_name),
Expand Down Expand Up @@ -1210,8 +1210,6 @@ impl CrateError {
),
};

err.emit();
sess.abort_if_errors();
unreachable!();
diag.emit();
}
}
157 changes: 88 additions & 69 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -683,75 +683,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
}

ItemKind::ExternCrate(orig_name) => {
let module = if orig_name.is_none() && ident.name == kw::SelfLower {
self.r
.session
.struct_span_err(item.span, "`extern crate self;` requires renaming")
.span_suggestion(
item.span,
"try",
"extern crate self as name;".into(),
Applicability::HasPlaceholders,
)
.emit();
return;
} else if orig_name == Some(kw::SelfLower) {
self.r.graph_root
} else {
let crate_id = self.r.crate_loader.process_extern_crate(
item,
&self.r.definitions,
local_def_id,
);
self.r.extern_crate_map.insert(local_def_id, crate_id);
self.r.expect_module(crate_id.as_def_id())
};

let used = self.process_macro_use_imports(item, module);
let binding =
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas);
let import = self.r.arenas.alloc_import(Import {
kind: ImportKind::ExternCrate { source: orig_name, target: ident },
root_id: item.id,
id: item.id,
parent_scope: self.parent_scope,
imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
has_attributes: !item.attrs.is_empty(),
use_span_with_attributes: item.span_with_attributes(),
use_span: item.span,
root_span: item.span,
span: item.span,
module_path: Vec::new(),
vis: Cell::new(vis),
used: Cell::new(used),
});
self.r.potentially_unused_imports.push(import);
let imported_binding = self.r.import(binding, import);
if ptr::eq(parent, self.r.graph_root) {
if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0())
{
if expansion != LocalExpnId::ROOT
&& orig_name.is_some()
&& entry.extern_crate_item.is_none()
{
let msg = "macro-expanded `extern crate` items cannot \
shadow names passed with `--extern`";
self.r.session.span_err(item.span, msg);
}
}
let entry =
self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert(
ExternPreludeEntry {
extern_crate_item: None,
introduced_by_item: true,
},
);
entry.extern_crate_item = Some(imported_binding);
if orig_name.is_some() {
entry.introduced_by_item = true;
}
}
self.r.define(parent, ident, TypeNS, imported_binding);
self.build_reduced_graph_for_extern_crate(
orig_name,
item,
local_def_id,
vis,
parent,
);
}

ItemKind::Mod(..) => {
Expand Down Expand Up @@ -889,6 +827,87 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
}
}

fn build_reduced_graph_for_extern_crate(
&mut self,
orig_name: Option<Symbol>,
item: &Item,
local_def_id: LocalDefId,
vis: ty::Visibility,
parent: Module<'a>,
) {
let ident = item.ident;
let sp = item.span;
let parent_scope = self.parent_scope;
let expansion = parent_scope.expansion;

let (used, module, binding) = if orig_name.is_none() && ident.name == kw::SelfLower {
self.r
.session
.struct_span_err(item.span, "`extern crate self;` requires renaming")
.span_suggestion(
item.span,
"rename the `self` crate to be able to import it",
"extern crate self as name;".into(),
Applicability::HasPlaceholders,
)
.emit();
return;
} else if orig_name == Some(kw::SelfLower) {
Some(self.r.graph_root)
} else {
self.r.crate_loader.process_extern_crate(item, &self.r.definitions, local_def_id).map(
|crate_id| {
self.r.extern_crate_map.insert(local_def_id, crate_id);
self.r.expect_module(crate_id.as_def_id())
},
)
}
.map(|module| {
let used = self.process_macro_use_imports(item, module);
let binding =
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas);
(used, Some(ModuleOrUniformRoot::Module(module)), binding)
})
.unwrap_or((true, None, self.r.dummy_binding));
let import = self.r.arenas.alloc_import(Import {
kind: ImportKind::ExternCrate { source: orig_name, target: ident },
root_id: item.id,
id: item.id,
parent_scope: self.parent_scope,
imported_module: Cell::new(module),
has_attributes: !item.attrs.is_empty(),
use_span_with_attributes: item.span_with_attributes(),
use_span: item.span,
root_span: item.span,
span: item.span,
module_path: Vec::new(),
vis: Cell::new(vis),
used: Cell::new(used),
});
self.r.potentially_unused_imports.push(import);
let imported_binding = self.r.import(binding, import);
if ptr::eq(parent, self.r.graph_root) {
if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
if expansion != LocalExpnId::ROOT
&& orig_name.is_some()
&& entry.extern_crate_item.is_none()
{
let msg = "macro-expanded `extern crate` items cannot \
shadow names passed with `--extern`";
self.r.session.span_err(item.span, msg);
}
}
let entry = self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert(
ExternPreludeEntry { extern_crate_item: None, introduced_by_item: true },
);
entry.extern_crate_item = Some(imported_binding);
if orig_name.is_some() {
entry.introduced_by_item = true;
}
}
self.r.define(parent, ident, TypeNS, imported_binding);
}

/// Constructs the reduced graph for one foreign item.
fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) {
let local_def_id = self.r.local_def_id(item.id);
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3288,7 +3288,9 @@ impl<'a> Resolver<'a> {
Some(binding)
} else {
let crate_id = if !speculative {
self.crate_loader.process_path_extern(ident.name, ident.span)
let Some(crate_id) =
self.crate_loader.process_path_extern(ident.name, ident.span) else { return Some(self.dummy_binding); };
crate_id
} else {
self.crate_loader.maybe_process_path_extern(ident.name)?
};
Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/crate-loading/invalid-rlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
#![no_std]
use ::foo; //~ ERROR invalid metadata files for crate `foo`
//~| NOTE failed to mmap file
//~^^ ERROR invalid metadata files for crate `foo`
//~| NOTE failed to mmap file
10 changes: 9 additions & 1 deletion src/test/ui/crate-loading/invalid-rlib.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ LL | use ::foo;
|
= note: failed to mmap file 'auxiliary/libfoo.rlib'

error: aborting due to previous error
error[E0786]: found invalid metadata files for crate `foo`
--> $DIR/invalid-rlib.rs:7:7
|
LL | use ::foo;
| ^^^
|
= note: failed to mmap file 'auxiliary/libfoo.rlib'

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0786`.
1 change: 1 addition & 0 deletions src/test/ui/crate-loading/missing-std.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// compile-flags: --target x86_64-unknown-uefi
// needs-llvm-components: x86
// rustc-env:CARGO=/usr/bin/cargo
#![feature(no_core)]
#![no_core]
extern crate core;
//~^ ERROR can't find crate for `core`
Expand Down
6 changes: 4 additions & 2 deletions src/test/ui/crate-loading/missing-std.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0463]: can't find crate for `core`
--> $DIR/missing-std.rs:5:1
--> $DIR/missing-std.rs:6:1
|
LL | extern crate core;
| ^^^^^^^^^^^^^^^^^^ can't find crate
Expand All @@ -8,6 +8,8 @@ LL | extern crate core;
= help: consider downloading the target with `rustup target add x86_64-unknown-uefi`
= help: consider building the standard library from source with `cargo build -Zbuild-std`

error: aborting due to previous error
error: requires `sized` lang_item

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0463`.
6 changes: 5 additions & 1 deletion src/test/ui/extern-flag/empty-extern-arg.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
error: extern location for std does not exist:

error: aborting due to previous error
error: language item required, but not found: `eh_personality`

error: `#[panic_handler]` function required, but not found

error: aborting due to 3 previous errors

10 changes: 10 additions & 0 deletions src/test/ui/extern/extern-crate-multiple-missing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// If multiple `extern crate` resolutions fail each of them should produce an error
extern crate bar; //~ ERROR can't find crate for `bar`
extern crate foo; //~ ERROR can't find crate for `foo`

fn main() {
// If the crate name introduced by `extern crate` failed to resolve then subsequent
// derived paths do not emit additional errors
foo::something();
bar::something();
}
15 changes: 15 additions & 0 deletions src/test/ui/extern/extern-crate-multiple-missing.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0463]: can't find crate for `bar`
--> $DIR/extern-crate-multiple-missing.rs:2:1
|
LL | extern crate bar;
| ^^^^^^^^^^^^^^^^^ can't find crate

error[E0463]: can't find crate for `foo`
--> $DIR/extern-crate-multiple-missing.rs:3:1
|
LL | extern crate foo;
| ^^^^^^^^^^^^^^^^^ can't find crate

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0463`.
Loading

0 comments on commit 9f1cbdf

Please sign in to comment.