Skip to content

Commit 9f1cbdf

Browse files
authored
Rollup merge of #91045 - mjptree:issue-90702-fix, r=petrochenkov
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 #90702 r? ``@petrochenkov``
2 parents f84065f + 2c9d9b4 commit 9f1cbdf

17 files changed

+208
-106
lines changed

compiler/rustc_metadata/src/creader.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -512,13 +512,17 @@ impl<'a> CrateLoader<'a> {
512512
name: Symbol,
513513
span: Span,
514514
dep_kind: CrateDepKind,
515-
) -> CrateNum {
515+
) -> Option<CrateNum> {
516516
self.used_extern_options.insert(name);
517-
self.maybe_resolve_crate(name, dep_kind, None).unwrap_or_else(|err| {
518-
let missing_core =
519-
self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err();
520-
err.report(&self.sess, span, missing_core)
521-
})
517+
match self.maybe_resolve_crate(name, dep_kind, None) {
518+
Ok(cnum) => Some(cnum),
519+
Err(err) => {
520+
let missing_core =
521+
self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err();
522+
err.report(&self.sess, span, missing_core);
523+
None
524+
}
525+
}
522526
}
523527

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

754-
let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit);
758+
let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; };
755759
let data = self.cstore.get_crate_data(cnum);
756760

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

794-
let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit);
798+
let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; };
795799
let data = self.cstore.get_crate_data(cnum);
796800

797801
// Sanity check the loaded crate to ensure it is indeed a profiler runtime
@@ -991,7 +995,7 @@ impl<'a> CrateLoader<'a> {
991995
item: &ast::Item,
992996
definitions: &Definitions,
993997
def_id: LocalDefId,
994-
) -> CrateNum {
998+
) -> Option<CrateNum> {
995999
match item.kind {
9961000
ast::ItemKind::ExternCrate(orig_name) => {
9971001
debug!(
@@ -1011,7 +1015,7 @@ impl<'a> CrateLoader<'a> {
10111015
CrateDepKind::Explicit
10121016
};
10131017

1014-
let cnum = self.resolve_crate(name, item.span, dep_kind);
1018+
let cnum = self.resolve_crate(name, item.span, dep_kind)?;
10151019

10161020
let path_len = definitions.def_path(def_id).data.len();
10171021
self.update_extern_crate(
@@ -1023,14 +1027,14 @@ impl<'a> CrateLoader<'a> {
10231027
dependency_of: LOCAL_CRATE,
10241028
},
10251029
);
1026-
cnum
1030+
Some(cnum)
10271031
}
10281032
_ => bug!(),
10291033
}
10301034
}
10311035

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

10351039
self.update_extern_crate(
10361040
cnum,
@@ -1043,7 +1047,7 @@ impl<'a> CrateLoader<'a> {
10431047
},
10441048
);
10451049

1046-
cnum
1050+
Some(cnum)
10471051
}
10481052

10491053
pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> {

compiler/rustc_metadata/src/locator.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ use rustc_data_structures::memmap::Mmap;
220220
use rustc_data_structures::owning_ref::OwningRef;
221221
use rustc_data_structures::svh::Svh;
222222
use rustc_data_structures::sync::MetadataRef;
223-
use rustc_errors::struct_span_err;
223+
use rustc_errors::{struct_span_err, FatalError};
224224
use rustc_session::config::{self, CrateType};
225225
use rustc_session::cstore::{CrateSource, MetadataLoader};
226226
use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch};
@@ -814,11 +814,11 @@ pub fn find_plugin_registrar(
814814
span: Span,
815815
name: Symbol,
816816
) -> PathBuf {
817-
match find_plugin_registrar_impl(sess, metadata_loader, name) {
818-
Ok(res) => res,
817+
find_plugin_registrar_impl(sess, metadata_loader, name).unwrap_or_else(|err| {
819818
// `core` is always available if we got as far as loading plugins.
820-
Err(err) => err.report(sess, span, false),
821-
}
819+
err.report(sess, span, false);
820+
FatalError.raise()
821+
})
822822
}
823823

824824
fn find_plugin_registrar_impl<'a>(
@@ -931,8 +931,8 @@ impl fmt::Display for MetadataError<'_> {
931931
}
932932

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

1213-
err.emit();
1214-
sess.abort_if_errors();
1215-
unreachable!();
1213+
diag.emit();
12161214
}
12171215
}

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 88 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -683,75 +683,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
683683
}
684684

685685
ItemKind::ExternCrate(orig_name) => {
686-
let module = if orig_name.is_none() && ident.name == kw::SelfLower {
687-
self.r
688-
.session
689-
.struct_span_err(item.span, "`extern crate self;` requires renaming")
690-
.span_suggestion(
691-
item.span,
692-
"try",
693-
"extern crate self as name;".into(),
694-
Applicability::HasPlaceholders,
695-
)
696-
.emit();
697-
return;
698-
} else if orig_name == Some(kw::SelfLower) {
699-
self.r.graph_root
700-
} else {
701-
let crate_id = self.r.crate_loader.process_extern_crate(
702-
item,
703-
&self.r.definitions,
704-
local_def_id,
705-
);
706-
self.r.extern_crate_map.insert(local_def_id, crate_id);
707-
self.r.expect_module(crate_id.as_def_id())
708-
};
709-
710-
let used = self.process_macro_use_imports(item, module);
711-
let binding =
712-
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas);
713-
let import = self.r.arenas.alloc_import(Import {
714-
kind: ImportKind::ExternCrate { source: orig_name, target: ident },
715-
root_id: item.id,
716-
id: item.id,
717-
parent_scope: self.parent_scope,
718-
imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
719-
has_attributes: !item.attrs.is_empty(),
720-
use_span_with_attributes: item.span_with_attributes(),
721-
use_span: item.span,
722-
root_span: item.span,
723-
span: item.span,
724-
module_path: Vec::new(),
725-
vis: Cell::new(vis),
726-
used: Cell::new(used),
727-
});
728-
self.r.potentially_unused_imports.push(import);
729-
let imported_binding = self.r.import(binding, import);
730-
if ptr::eq(parent, self.r.graph_root) {
731-
if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0())
732-
{
733-
if expansion != LocalExpnId::ROOT
734-
&& orig_name.is_some()
735-
&& entry.extern_crate_item.is_none()
736-
{
737-
let msg = "macro-expanded `extern crate` items cannot \
738-
shadow names passed with `--extern`";
739-
self.r.session.span_err(item.span, msg);
740-
}
741-
}
742-
let entry =
743-
self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert(
744-
ExternPreludeEntry {
745-
extern_crate_item: None,
746-
introduced_by_item: true,
747-
},
748-
);
749-
entry.extern_crate_item = Some(imported_binding);
750-
if orig_name.is_some() {
751-
entry.introduced_by_item = true;
752-
}
753-
}
754-
self.r.define(parent, ident, TypeNS, imported_binding);
686+
self.build_reduced_graph_for_extern_crate(
687+
orig_name,
688+
item,
689+
local_def_id,
690+
vis,
691+
parent,
692+
);
755693
}
756694

757695
ItemKind::Mod(..) => {
@@ -889,6 +827,87 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
889827
}
890828
}
891829

830+
fn build_reduced_graph_for_extern_crate(
831+
&mut self,
832+
orig_name: Option<Symbol>,
833+
item: &Item,
834+
local_def_id: LocalDefId,
835+
vis: ty::Visibility,
836+
parent: Module<'a>,
837+
) {
838+
let ident = item.ident;
839+
let sp = item.span;
840+
let parent_scope = self.parent_scope;
841+
let expansion = parent_scope.expansion;
842+
843+
let (used, module, binding) = if orig_name.is_none() && ident.name == kw::SelfLower {
844+
self.r
845+
.session
846+
.struct_span_err(item.span, "`extern crate self;` requires renaming")
847+
.span_suggestion(
848+
item.span,
849+
"rename the `self` crate to be able to import it",
850+
"extern crate self as name;".into(),
851+
Applicability::HasPlaceholders,
852+
)
853+
.emit();
854+
return;
855+
} else if orig_name == Some(kw::SelfLower) {
856+
Some(self.r.graph_root)
857+
} else {
858+
self.r.crate_loader.process_extern_crate(item, &self.r.definitions, local_def_id).map(
859+
|crate_id| {
860+
self.r.extern_crate_map.insert(local_def_id, crate_id);
861+
self.r.expect_module(crate_id.as_def_id())
862+
},
863+
)
864+
}
865+
.map(|module| {
866+
let used = self.process_macro_use_imports(item, module);
867+
let binding =
868+
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas);
869+
(used, Some(ModuleOrUniformRoot::Module(module)), binding)
870+
})
871+
.unwrap_or((true, None, self.r.dummy_binding));
872+
let import = self.r.arenas.alloc_import(Import {
873+
kind: ImportKind::ExternCrate { source: orig_name, target: ident },
874+
root_id: item.id,
875+
id: item.id,
876+
parent_scope: self.parent_scope,
877+
imported_module: Cell::new(module),
878+
has_attributes: !item.attrs.is_empty(),
879+
use_span_with_attributes: item.span_with_attributes(),
880+
use_span: item.span,
881+
root_span: item.span,
882+
span: item.span,
883+
module_path: Vec::new(),
884+
vis: Cell::new(vis),
885+
used: Cell::new(used),
886+
});
887+
self.r.potentially_unused_imports.push(import);
888+
let imported_binding = self.r.import(binding, import);
889+
if ptr::eq(parent, self.r.graph_root) {
890+
if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
891+
if expansion != LocalExpnId::ROOT
892+
&& orig_name.is_some()
893+
&& entry.extern_crate_item.is_none()
894+
{
895+
let msg = "macro-expanded `extern crate` items cannot \
896+
shadow names passed with `--extern`";
897+
self.r.session.span_err(item.span, msg);
898+
}
899+
}
900+
let entry = self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert(
901+
ExternPreludeEntry { extern_crate_item: None, introduced_by_item: true },
902+
);
903+
entry.extern_crate_item = Some(imported_binding);
904+
if orig_name.is_some() {
905+
entry.introduced_by_item = true;
906+
}
907+
}
908+
self.r.define(parent, ident, TypeNS, imported_binding);
909+
}
910+
892911
/// Constructs the reduced graph for one foreign item.
893912
fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) {
894913
let local_def_id = self.r.local_def_id(item.id);

compiler/rustc_resolve/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3288,7 +3288,9 @@ impl<'a> Resolver<'a> {
32883288
Some(binding)
32893289
} else {
32903290
let crate_id = if !speculative {
3291-
self.crate_loader.process_path_extern(ident.name, ident.span)
3291+
let Some(crate_id) =
3292+
self.crate_loader.process_path_extern(ident.name, ident.span) else { return Some(self.dummy_binding); };
3293+
crate_id
32923294
} else {
32933295
self.crate_loader.maybe_process_path_extern(ident.name)?
32943296
};

src/test/ui/crate-loading/invalid-rlib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@
66
#![no_std]
77
use ::foo; //~ ERROR invalid metadata files for crate `foo`
88
//~| NOTE failed to mmap file
9+
//~^^ ERROR invalid metadata files for crate `foo`
10+
//~| NOTE failed to mmap file

src/test/ui/crate-loading/invalid-rlib.stderr

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ LL | use ::foo;
66
|
77
= note: failed to mmap file 'auxiliary/libfoo.rlib'
88

9-
error: aborting due to previous error
9+
error[E0786]: found invalid metadata files for crate `foo`
10+
--> $DIR/invalid-rlib.rs:7:7
11+
|
12+
LL | use ::foo;
13+
| ^^^
14+
|
15+
= note: failed to mmap file 'auxiliary/libfoo.rlib'
16+
17+
error: aborting due to 2 previous errors
1018

1119
For more information about this error, try `rustc --explain E0786`.

src/test/ui/crate-loading/missing-std.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// compile-flags: --target x86_64-unknown-uefi
22
// needs-llvm-components: x86
33
// rustc-env:CARGO=/usr/bin/cargo
4+
#![feature(no_core)]
45
#![no_core]
56
extern crate core;
67
//~^ ERROR can't find crate for `core`
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0463]: can't find crate for `core`
2-
--> $DIR/missing-std.rs:5:1
2+
--> $DIR/missing-std.rs:6:1
33
|
44
LL | extern crate core;
55
| ^^^^^^^^^^^^^^^^^^ can't find crate
@@ -8,6 +8,8 @@ LL | extern crate core;
88
= help: consider downloading the target with `rustup target add x86_64-unknown-uefi`
99
= help: consider building the standard library from source with `cargo build -Zbuild-std`
1010

11-
error: aborting due to previous error
11+
error: requires `sized` lang_item
12+
13+
error: aborting due to 2 previous errors
1214

1315
For more information about this error, try `rustc --explain E0463`.
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
error: extern location for std does not exist:
22

3-
error: aborting due to previous error
3+
error: language item required, but not found: `eh_personality`
4+
5+
error: `#[panic_handler]` function required, but not found
6+
7+
error: aborting due to 3 previous errors
48

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// If multiple `extern crate` resolutions fail each of them should produce an error
2+
extern crate bar; //~ ERROR can't find crate for `bar`
3+
extern crate foo; //~ ERROR can't find crate for `foo`
4+
5+
fn main() {
6+
// If the crate name introduced by `extern crate` failed to resolve then subsequent
7+
// derived paths do not emit additional errors
8+
foo::something();
9+
bar::something();
10+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0463]: can't find crate for `bar`
2+
--> $DIR/extern-crate-multiple-missing.rs:2:1
3+
|
4+
LL | extern crate bar;
5+
| ^^^^^^^^^^^^^^^^^ can't find crate
6+
7+
error[E0463]: can't find crate for `foo`
8+
--> $DIR/extern-crate-multiple-missing.rs:3:1
9+
|
10+
LL | extern crate foo;
11+
| ^^^^^^^^^^^^^^^^^ can't find crate
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0463`.

0 commit comments

Comments
 (0)