From 2c9d9b4b758a9d6bdae212852c59d71a3edcc5de Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 26 Nov 2021 21:39:44 +0000 Subject: [PATCH] Improve suggestion for extern crate self error message --- compiler/rustc_metadata/src/creader.rs | 30 ++++-------- compiler/rustc_metadata/src/locator.rs | 12 ++--- .../rustc_resolve/src/build_reduced_graph.rs | 48 +++++++------------ compiler/rustc_resolve/src/imports.rs | 6 +-- compiler/rustc_resolve/src/lib.rs | 4 +- src/test/ui/crate-loading/invalid-rlib.rs | 2 + src/test/ui/crate-loading/invalid-rlib.stderr | 10 +++- .../extern/extern-crate-multiple-missing.rs | 2 + .../extern-crate-self-fail.stderr | 7 ++- .../ui/rust-2018/uniform-paths/deadlock.rs | 3 +- .../rust-2018/uniform-paths/deadlock.stderr | 21 ++++++-- 11 files changed, 75 insertions(+), 70 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index f3e7d84c1c530..2626a2e189c1d 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -9,7 +9,6 @@ use rustc_ast::{self as ast, *}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; -use rustc_errors::FatalError; use rustc_expand::base::SyntaxExtension; use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; @@ -508,15 +507,6 @@ impl<'a> CrateLoader<'a> { })) } - fn resolve_crate_or_abort<'b>( - &'b mut self, - name: Symbol, - span: Span, - dep_kind: CrateDepKind, - ) -> CrateNum { - self.resolve_crate(name, span, dep_kind).unwrap_or_else(|| FatalError.raise()) - } - fn resolve_crate<'b>( &'b mut self, name: Symbol, @@ -524,15 +514,15 @@ impl<'a> CrateLoader<'a> { dep_kind: CrateDepKind, ) -> Option { self.used_extern_options.insert(name); - self.maybe_resolve_crate(name, dep_kind, None).map_or_else( - |err| { + 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 - }, - |cnum| Some(cnum), - ) + } + } } fn maybe_resolve_crate<'b>( @@ -765,7 +755,7 @@ impl<'a> CrateLoader<'a> { }; info!("panic runtime not found -- loading {}", name); - let cnum = self.resolve_crate_or_abort(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 @@ -805,7 +795,7 @@ impl<'a> CrateLoader<'a> { ); } - let cnum = self.resolve_crate_or_abort(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 @@ -1043,8 +1033,8 @@ impl<'a> CrateLoader<'a> { } } - pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum { - let cnum = self.resolve_crate_or_abort(name, span, CrateDepKind::Explicit); + pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> Option { + let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit)?; self.update_extern_crate( cnum, @@ -1057,7 +1047,7 @@ impl<'a> CrateLoader<'a> { }, ); - cnum + Some(cnum) } pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option { diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 03181012bccb7..e2fd8056f1a7c 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -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, DiagnosticBuilder, FatalError}; +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}; @@ -931,8 +931,8 @@ impl fmt::Display for MetadataError<'_> { } impl CrateError { - fn build_diag(self, sess: &Session, span: Span, missing_core: bool) -> DiagnosticBuilder<'_> { - 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), @@ -1208,10 +1208,8 @@ impl CrateError { "plugin `{}` only found in rlib format, but must be available in dylib format", crate_name, ), - } - } + }; - crate fn report(self, sess: &Session, span: Span, missing_core: bool) { - self.build_diag(sess, span, missing_core).emit(); + diag.emit(); } } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index aaa946f75421b..c936e08d536a4 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -840,57 +840,41 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let parent_scope = self.parent_scope; let expansion = parent_scope.expansion; - let module = if orig_name.is_none() && ident.name == kw::SelfLower { + 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, - "try", + "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) { - self.r.graph_root + Some(self.r.graph_root) } else { - match self.r.crate_loader.process_extern_crate(item, &self.r.definitions, local_def_id) - { - Some(crate_id) => { + 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()) - } - _ => { - let dummy_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(None), - 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(true), - }); - self.r.import_dummy_binding(dummy_import); - return; - } - } - }; - let used = self.process_macro_use_imports(item, module); - let binding = - (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas); + }, + ) + } + .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(Some(ModuleOrUniformRoot::Module(module))), + imported_module: Cell::new(module), has_attributes: !item.attrs.is_empty(), use_span_with_attributes: item.span_with_attributes(), use_span: item.span, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index d2c64b7e4418d..bf4cece8bde8d 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -600,10 +600,8 @@ impl<'a> Resolver<'a> { // Define a "dummy" resolution containing a Res::Err as a placeholder for a // failed resolution - crate fn import_dummy_binding(&mut self, import: &'a Import<'a>) { - if let ImportKind::Single { target, .. } | ImportKind::ExternCrate { target, .. } = - import.kind - { + fn import_dummy_binding(&mut self, import: &'a Import<'a>) { + if let ImportKind::Single { target, .. } = import.kind { let dummy_binding = self.dummy_binding; let dummy_binding = self.import(dummy_binding, import); self.per_ns(|this, ns| { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index d17e8875a1ec0..1c084086ceb02 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -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)? }; diff --git a/src/test/ui/crate-loading/invalid-rlib.rs b/src/test/ui/crate-loading/invalid-rlib.rs index 77c29090a3ee0..aea861e3261b5 100644 --- a/src/test/ui/crate-loading/invalid-rlib.rs +++ b/src/test/ui/crate-loading/invalid-rlib.rs @@ -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 diff --git a/src/test/ui/crate-loading/invalid-rlib.stderr b/src/test/ui/crate-loading/invalid-rlib.stderr index b2c79f742fb30..3c0d23bf7b4cc 100644 --- a/src/test/ui/crate-loading/invalid-rlib.stderr +++ b/src/test/ui/crate-loading/invalid-rlib.stderr @@ -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`. diff --git a/src/test/ui/extern/extern-crate-multiple-missing.rs b/src/test/ui/extern/extern-crate-multiple-missing.rs index fa7da83a6dfef..a6560ca78624d 100644 --- a/src/test/ui/extern/extern-crate-multiple-missing.rs +++ b/src/test/ui/extern/extern-crate-multiple-missing.rs @@ -3,6 +3,8 @@ 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(); } diff --git a/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.stderr b/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.stderr index 8f369f1b03831..127765727b401 100644 --- a/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.stderr +++ b/src/test/ui/imports/extern-crate-self/extern-crate-self-fail.stderr @@ -2,7 +2,12 @@ error: `extern crate self;` requires renaming --> $DIR/extern-crate-self-fail.rs:1:1 | LL | extern crate self; - | ^^^^^^^^^^^^^^^^^^ help: try: `extern crate self as name;` + | ^^^^^^^^^^^^^^^^^^ + | +help: rename the `self` crate to be able to import it + | +LL | extern crate self as name; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ error: `#[macro_use]` is not supported on `extern crate self` --> $DIR/extern-crate-self-fail.rs:3:1 diff --git a/src/test/ui/rust-2018/uniform-paths/deadlock.rs b/src/test/ui/rust-2018/uniform-paths/deadlock.rs index 83ed70a0459a8..2427bde6d18bc 100644 --- a/src/test/ui/rust-2018/uniform-paths/deadlock.rs +++ b/src/test/ui/rust-2018/uniform-paths/deadlock.rs @@ -1,7 +1,8 @@ // edition:2018 // compile-flags:--extern foo --extern bar +use bar::foo; //~ ERROR can't find crate for `bar` use foo::bar; //~ ERROR can't find crate for `foo` -use bar::foo; +//~^^ ERROR unresolved imports `bar::foo`, `foo::bar` fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths/deadlock.stderr b/src/test/ui/rust-2018/uniform-paths/deadlock.stderr index 9336e90afb71d..8b9863948bd6c 100644 --- a/src/test/ui/rust-2018/uniform-paths/deadlock.stderr +++ b/src/test/ui/rust-2018/uniform-paths/deadlock.stderr @@ -1,9 +1,24 @@ -error[E0463]: can't find crate for `foo` +error[E0463]: can't find crate for `bar` --> $DIR/deadlock.rs:4:5 | +LL | use bar::foo; + | ^^^ can't find crate + +error[E0463]: can't find crate for `foo` + --> $DIR/deadlock.rs:5:5 + | LL | use foo::bar; | ^^^ can't find crate -error: aborting due to previous error +error[E0432]: unresolved imports `bar::foo`, `foo::bar` + --> $DIR/deadlock.rs:4:5 + | +LL | use bar::foo; + | ^^^^^^^^ +LL | use foo::bar; + | ^^^^^^^^ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0463`. +Some errors have detailed explanations: E0432, E0463. +For more information about an error, try `rustc --explain E0432`.