diff options
Diffstat (limited to 'compiler')
23 files changed, 669 insertions, 207 deletions
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 85306d7184d..54c83fb7604 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -205,13 +205,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let static_def_id = self .resolver .get_partial_res(sym.id) - .filter(|res| res.unresolved_segments() == 0) - .and_then(|res| { - if let Res::Def(DefKind::Static(_), def_id) = res.base_res() { - Some(def_id) - } else { - None - } + .and_then(|res| res.full_res()) + .and_then(|res| match res { + Res::Def(DefKind::Static(_), def_id) => Some(def_id), + _ => None, }); if let Some(def_id) = static_def_id { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 46886c518af..c55b4906302 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1044,9 +1044,7 @@ impl<'hir> LoweringContext<'_, 'hir> { if let ExprKind::Path(qself, path) = &expr.kind { // Does the path resolve to something disallowed in a tuple struct/variant pattern? if let Some(partial_res) = self.resolver.get_partial_res(expr.id) { - if partial_res.unresolved_segments() == 0 - && !partial_res.base_res().expected_in_tuple_struct_pat() - { + if let Some(res) = partial_res.full_res() && !res.expected_in_tuple_struct_pat() { return None; } } @@ -1066,9 +1064,7 @@ impl<'hir> LoweringContext<'_, 'hir> { if let ExprKind::Path(qself, path) = &expr.kind { // Does the path resolve to something disallowed in a unit struct/variant pattern? if let Some(partial_res) = self.resolver.get_partial_res(expr.id) { - if partial_res.unresolved_segments() == 0 - && !partial_res.base_res().expected_in_unit_struct_pat() - { + if let Some(res) = partial_res.full_res() && !res.expected_in_unit_struct_pat() { return None; } } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 56d71aaa7d3..687d810ed4e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -947,7 +947,10 @@ impl<'hir> LoweringContext<'_, 'hir> { } AssocItemKind::MacCall(..) => unimplemented!(), }, - trait_item_def_id: self.resolver.get_partial_res(i.id).map(|r| r.base_res().def_id()), + trait_item_def_id: self + .resolver + .get_partial_res(i.id) + .map(|r| r.expect_full_res().def_id()), } } @@ -1349,9 +1352,9 @@ impl<'hir> LoweringContext<'_, 'hir> { match self .resolver .get_partial_res(bound_pred.bounded_ty.id) - .map(|d| (d.base_res(), d.unresolved_segments())) + .and_then(|r| r.full_res()) { - Some((Res::Def(DefKind::TyParam, def_id), 0)) + Some(Res::Def(DefKind::TyParam, def_id)) if bound_pred.bound_generic_params.is_empty() => { generics diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8281164ab12..ce5893efa92 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -175,12 +175,7 @@ impl ResolverAstLoweringExt for ResolverAstLowering { return None; } - let partial_res = self.partial_res_map.get(&expr.id)?; - if partial_res.unresolved_segments() != 0 { - return None; - } - - if let Res::Def(DefKind::Fn, def_id) = partial_res.base_res() { + if let Res::Def(DefKind::Fn, def_id) = self.partial_res_map.get(&expr.id)?.full_res()? { // We only support cross-crate argument rewriting. Uses // within the same crate should be updated to use the new // const generics style. @@ -753,12 +748,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn expect_full_res(&mut self, id: NodeId) -> Res<NodeId> { - self.resolver.get_partial_res(id).map_or(Res::Err, |pr| { - if pr.unresolved_segments() != 0 { - panic!("path not fully resolved: {:?}", pr); - } - pr.base_res() - }) + self.resolver.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res()) } fn expect_full_res_from_use(&mut self, id: NodeId) -> impl Iterator<Item = Res<NodeId>> { @@ -1138,8 +1128,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // type and value namespaces. If we resolved the path in the value namespace, we // transform it into a generic const argument. TyKind::Path(ref qself, ref path) => { - if let Some(partial_res) = self.resolver.get_partial_res(ty.id) { - let res = partial_res.base_res(); + if let Some(res) = self + .resolver + .get_partial_res(ty.id) + .and_then(|partial_res| partial_res.full_res()) + { if !res.matches_ns(Namespace::TypeNS) { debug!( "lower_generic_arg: Lowering type argument as const argument: {:?}", @@ -1206,8 +1199,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // by `ty_path`. if qself.is_none() && let Some(partial_res) = self.resolver.get_partial_res(t.id) - && partial_res.unresolved_segments() == 0 - && let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res() + && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res() { let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| { let poly_trait_ref = this.ast_arena.ptr.alloc(PolyTraitRef { diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 1ea76fdbfcb..1af1633b524 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -239,7 +239,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ident: Ident, lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>, ) -> hir::PatKind<'hir> { - match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) { + match self.resolver.get_partial_res(p.id).map(|d| d.expect_full_res()) { // `None` can occur in body-less function signatures res @ (None | Some(Res::Local(_))) => { let canonical_id = match res { diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 6bb1bb9eace..888776cccac 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -29,11 +29,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let partial_res = self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err)); + let base_res = partial_res.base_res(); + let unresolved_segments = partial_res.unresolved_segments(); let path_span_lo = p.span.shrink_to_lo(); - let proj_start = p.segments.len() - partial_res.unresolved_segments(); + let proj_start = p.segments.len() - unresolved_segments; let path = self.arena.alloc(hir::Path { - res: self.lower_res(partial_res.base_res()), + res: self.lower_res(base_res), segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map( |(i, segment)| { let param_mode = match (qself_position, param_mode) { @@ -46,7 +48,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { _ => param_mode, }; - let parenthesized_generic_args = match partial_res.base_res() { + let parenthesized_generic_args = match base_res { // `a::b::Trait(Args)` Res::Def(DefKind::Trait, _) if i + 1 == proj_start => { ParenthesizedGenericArgs::Ok @@ -83,7 +85,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Simple case, either no projections, or only fully-qualified. // E.g., `std::mem::size_of` or `<I as Iterator>::Item`. - if partial_res.unresolved_segments() == 0 { + if unresolved_segments == 0 { return hir::QPath::Resolved(qself, path); } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 9a0c379b4e4..95e72184ff0 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -31,7 +31,9 @@ use super::command::Command; use super::linker::{self, Linker}; use super::metadata::{create_rmeta_file, MetadataPosition}; use super::rpath::{self, RPathConfig}; -use crate::{looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, NativeLib}; +use crate::{ + errors, looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, NativeLib, +}; use cc::windows_registry; use regex::Regex; @@ -93,7 +95,7 @@ pub fn link_binary<'a>( let tmpdir = TempFileBuilder::new() .prefix("rustc") .tempdir() - .unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err))); + .unwrap_or_else(|error| sess.emit_fatal(errors::CreateTempDir { error })); let path = MaybeTempDir::new(tmpdir, sess.opts.cg.save_temps); let out_filename = out_filename( sess, @@ -208,7 +210,7 @@ pub fn link_binary<'a>( pub fn each_linked_rlib( info: &CrateInfo, f: &mut dyn FnMut(CrateNum, &Path), -) -> Result<(), String> { +) -> Result<(), errors::LinkRlibError> { let crates = info.used_crates.iter(); let mut fmts = None; for (ty, list) in info.dependency_formats.iter() { @@ -224,26 +226,23 @@ pub fn each_linked_rlib( } } let Some(fmts) = fmts else { - return Err("could not find formats for rlibs".to_string()); + return Err(errors::LinkRlibError::MissingFormat); }; for &cnum in crates { match fmts.get(cnum.as_usize() - 1) { Some(&Linkage::NotLinked | &Linkage::IncludedFromDylib) => continue, Some(_) => {} - None => return Err("could not find formats for rlibs".to_string()), + None => return Err(errors::LinkRlibError::MissingFormat), } - let name = info.crate_name[&cnum]; + let crate_name = info.crate_name[&cnum]; let used_crate_source = &info.used_crate_source[&cnum]; if let Some((path, _)) = &used_crate_source.rlib { f(cnum, &path); } else { if used_crate_source.rmeta.is_some() { - return Err(format!( - "could not find rlib for: `{}`, found rmeta (metadata) file", - name - )); + return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name }); } else { - return Err(format!("could not find rlib for: `{}`", name)); + return Err(errors::LinkRlibError::NotFound { crate_name }); } } } @@ -340,10 +339,7 @@ fn link_rlib<'a>( // -whole-archive and it isn't clear how we can currently handle such a // situation correctly. // See https://github.com/rust-lang/rust/issues/88085#issuecomment-901050897 - sess.err( - "the linking modifiers `+bundle` and `+whole-archive` are not compatible \ - with each other when generating rlibs", - ); + sess.emit_err(errors::IncompatibleLinkingModifiers); } NativeLibKind::Static { bundle: None | Some(true), .. } => {} NativeLibKind::Static { bundle: Some(false), .. } @@ -365,12 +361,8 @@ fn link_rlib<'a>( )); continue; } - ab.add_archive(&location, Box::new(|_| false)).unwrap_or_else(|e| { - sess.fatal(&format!( - "failed to add native library {}: {}", - location.to_string_lossy(), - e - )); + ab.add_archive(&location, Box::new(|_| false)).unwrap_or_else(|error| { + sess.emit_fatal(errors::AddNativeLibrary { library_path: location, error }); }); } } @@ -385,8 +377,8 @@ fn link_rlib<'a>( tmpdir.as_ref(), ); - ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|e| { - sess.fatal(&format!("failed to add native library {}: {}", output_path.display(), e)); + ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| { + sess.emit_fatal(errors::AddNativeLibrary { library_path: output_path, error }); }); } @@ -451,14 +443,11 @@ fn collate_raw_dylibs( // FIXME: when we add support for ordinals, figure out if we need to do anything // if we have two DllImport values with the same name but different ordinals. if import.calling_convention != old_import.calling_convention { - sess.span_err( - import.span, - &format!( - "multiple declarations of external function `{}` from \ - library `{}` have different calling conventions", - import.name, name, - ), - ); + sess.emit_err(errors::MultipleExternalFuncDecl { + span: import.span, + function: import.name, + library_name: &name, + }); } } } @@ -560,7 +549,7 @@ fn link_staticlib<'a>( all_native_libs.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned()); }); if let Err(e) = res { - sess.fatal(&e); + sess.emit_fatal(e); } ab.build(out_filename); @@ -673,9 +662,7 @@ fn link_dwarf_object<'a>( }) { Ok(()) => {} Err(e) => { - sess.struct_err("linking dwarf objects with thorin failed") - .note(&format!("{:?}", e)) - .emit(); + sess.emit_err(errors::ThorinErrorWrapper(e)); sess.abort_if_errors(); } } @@ -879,23 +866,14 @@ fn link_natively<'a>( let mut output = prog.stderr.clone(); output.extend_from_slice(&prog.stdout); let escaped_output = escape_string(&output); - let mut err = sess.struct_err(&format!( - "linking with `{}` failed: {}", - linker_path.display(), - prog.status - )); - err.note(&format!("{:?}", &cmd)).note(&escaped_output); - if escaped_output.contains("undefined reference to") { - err.help( - "some `extern` functions couldn't be found; some native libraries may \ - need to be installed or have their path specified", - ); - err.note("use the `-l` flag to specify native libraries to link"); - err.note("use the `cargo:rustc-link-lib` directive to specify the native \ - libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)"); - } - err.emit(); - + // FIXME: Add UI tests for this error. + let err = errors::LinkingFailed { + linker_path: &linker_path, + exit_status: prog.status, + command: &cmd, + escaped_output: &escaped_output, + }; + sess.diagnostic().emit_err(err); // If MSVC's `link.exe` was expected but the return code // is not a Microsoft LNK error then suggest a way to fix or // install the Visual Studio build tools. diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index c71d332475a..bad22ccb1fe 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1,5 +1,6 @@ use super::command::Command; use super::symbol_export; +use crate::errors; use rustc_span::symbol::sym; use std::ffi::{OsStr, OsString}; @@ -434,11 +435,11 @@ impl<'a> Linker for GccLinker<'a> { // FIXME(81490): ld64 doesn't support these flags but macOS 11 // has -needed-l{} / -needed_library {} // but we have no way to detect that here. - self.sess.warn("`as-needed` modifier not implemented yet for ld64"); + self.sess.emit_warning(errors::Ld64UnimplementedModifier); } else if self.is_gnu && !self.sess.target.is_like_windows { self.linker_arg("--no-as-needed"); } else { - self.sess.warn("`as-needed` modifier not supported for current linker"); + self.sess.emit_warning(errors::LinkerUnsupportedModifier); } } self.hint_dynamic(); @@ -492,7 +493,7 @@ impl<'a> Linker for GccLinker<'a> { // FIXME(81490): ld64 as of macOS 11 supports the -needed_framework // flag but we have no way to detect that here. // self.cmd.arg("-needed_framework").arg(framework); - self.sess.warn("`as-needed` modifier not implemented yet for ld64"); + self.sess.emit_warning(errors::Ld64UnimplementedModifier); } self.cmd.arg("-framework").arg(framework); } @@ -665,8 +666,8 @@ impl<'a> Linker for GccLinker<'a> { writeln!(f, "_{}", sym)?; } }; - if let Err(e) = res { - self.sess.fatal(&format!("failed to write lib.def file: {}", e)); + if let Err(error) = res { + self.sess.emit_fatal(errors::LibDefWriteFailure { error }); } } else if is_windows { let res: io::Result<()> = try { @@ -680,8 +681,8 @@ impl<'a> Linker for GccLinker<'a> { writeln!(f, " {}", symbol)?; } }; - if let Err(e) = res { - self.sess.fatal(&format!("failed to write list.def file: {}", e)); + if let Err(error) = res { + self.sess.emit_fatal(errors::LibDefWriteFailure { error }); } } else { // Write an LD version script @@ -697,8 +698,8 @@ impl<'a> Linker for GccLinker<'a> { } writeln!(f, "\n local:\n *;\n}};")?; }; - if let Err(e) = res { - self.sess.fatal(&format!("failed to write version script: {}", e)); + if let Err(error) = res { + self.sess.emit_fatal(errors::VersionScriptWriteFailure { error }); } } @@ -915,9 +916,8 @@ impl<'a> Linker for MsvcLinker<'a> { self.cmd.arg(arg); } } - Err(err) => { - self.sess - .warn(&format!("error enumerating natvis directory: {}", err)); + Err(error) => { + self.sess.emit_warning(errors::NoNatvisDirectory { error }); } } } @@ -971,8 +971,8 @@ impl<'a> Linker for MsvcLinker<'a> { writeln!(f, " {}", symbol)?; } }; - if let Err(e) = res { - self.sess.fatal(&format!("failed to write lib.def file: {}", e)); + if let Err(error) = res { + self.sess.emit_fatal(errors::LibDefWriteFailure { error }); } let mut arg = OsString::from("/DEF:"); arg.push(path); @@ -1435,7 +1435,7 @@ impl<'a> Linker for L4Bender<'a> { fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[String]) { // ToDo, not implemented, copy from GCC - self.sess.warn("exporting symbols not implemented yet for L4Bender"); + self.sess.emit_warning(errors::L4BenderExportingSymbolsUnimplemented); return; } @@ -1727,8 +1727,8 @@ impl<'a> Linker for BpfLinker<'a> { writeln!(f, "{}", sym)?; } }; - if let Err(e) = res { - self.sess.fatal(&format!("failed to write symbols file: {}", e)); + if let Err(error) = res { + self.sess.emit_fatal(errors::SymbolFileWriteFailure { error }); } else { self.cmd.arg("--export-symbols").arg(&path); } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 6188094bbbd..1f577e9f352 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -2,11 +2,11 @@ use super::link::{self, ensure_removed}; use super::lto::{self, SerializedModule}; use super::symbol_export::symbol_name_for_instance_in_crate; +use crate::errors; +use crate::traits::*; use crate::{ CachedModuleCodegen, CodegenResults, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind, }; - -use crate::traits::*; use jobserver::{Acquired, Client}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::memmap::Mmap; @@ -530,7 +530,7 @@ fn produce_final_output_artifacts( // Produce final compile outputs. let copy_gracefully = |from: &Path, to: &Path| { if let Err(e) = fs::copy(from, to) { - sess.err(&format!("could not copy {:?} to {:?}: {}", from, to, e)); + sess.emit_err(errors::CopyPath::new(from, to, e)); } }; @@ -546,7 +546,7 @@ fn produce_final_output_artifacts( ensure_removed(sess.diagnostic(), &path); } } else { - let ext = crate_output + let extension = crate_output .temp_path(output_type, None) .extension() .unwrap() @@ -557,19 +557,11 @@ fn produce_final_output_artifacts( if crate_output.outputs.contains_key(&output_type) { // 2) Multiple codegen units, with `--emit foo=some_name`. We have // no good solution for this case, so warn the user. - sess.warn(&format!( - "ignoring emit path because multiple .{} files \ - were produced", - ext - )); + sess.emit_warning(errors::IgnoringEmitPath { extension }); } else if crate_output.single_output_file.is_some() { // 3) Multiple codegen units, with `-o some_name`. We have // no good solution for this case, so warn the user. - sess.warn(&format!( - "ignoring -o because multiple .{} files \ - were produced", - ext - )); + sess.emit_warning(errors::IgnoringOutput { extension }); } else { // 4) Multiple codegen units, but no explicit name. We // just leave the `foo.0.x` files in place. @@ -880,14 +872,12 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>( ); match link_or_copy(&source_file, &output_path) { Ok(_) => Some(output_path), - Err(err) => { - let diag_handler = cgcx.create_diag_handler(); - diag_handler.err(&format!( - "unable to copy {} to {}: {}", - source_file.display(), - output_path.display(), - err - )); + Err(error) => { + cgcx.create_diag_handler().emit_err(errors::CopyPathBuf { + source_file, + output_path, + error, + }); None } } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs new file mode 100644 index 00000000000..0ffe8872022 --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -0,0 +1,353 @@ +//! Errors emitted by codegen_ssa + +use crate::back::command::Command; +use rustc_errors::{ + fluent, DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, + IntoDiagnosticArg, +}; +use rustc_macros::Diagnostic; +use rustc_span::{Span, Symbol}; +use std::borrow::Cow; +use std::io::Error; +use std::path::{Path, PathBuf}; +use std::process::ExitStatus; + +#[derive(Diagnostic)] +#[diag(codegen_ssa::lib_def_write_failure)] +pub struct LibDefWriteFailure { + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa::version_script_write_failure)] +pub struct VersionScriptWriteFailure { + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa::symbol_file_write_failure)] +pub struct SymbolFileWriteFailure { + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa::ld64_unimplemented_modifier)] +pub struct Ld64UnimplementedModifier; + +#[derive(Diagnostic)] +#[diag(codegen_ssa::linker_unsupported_modifier)] +pub struct LinkerUnsupportedModifier; + +#[derive(Diagnostic)] +#[diag(codegen_ssa::L4Bender_exporting_symbols_unimplemented)] +pub struct L4BenderExportingSymbolsUnimplemented; + +#[derive(Diagnostic)] +#[diag(codegen_ssa::no_natvis_directory)] +pub struct NoNatvisDirectory { + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa::copy_path_buf)] +pub struct CopyPathBuf { + pub source_file: PathBuf, + pub output_path: PathBuf, + pub error: Error, +} + +// Reports Paths using `Debug` implementation rather than Path's `Display` implementation. +#[derive(Diagnostic)] +#[diag(codegen_ssa::copy_path)] +pub struct CopyPath<'a> { + from: DebugArgPath<'a>, + to: DebugArgPath<'a>, + error: Error, +} + +impl<'a> CopyPath<'a> { + pub fn new(from: &'a Path, to: &'a Path, error: Error) -> CopyPath<'a> { + CopyPath { from: DebugArgPath(from), to: DebugArgPath(to), error } + } +} + +struct DebugArgPath<'a>(pub &'a Path); + +impl IntoDiagnosticArg for DebugArgPath<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(format!("{:?}", self.0))) + } +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa::ignoring_emit_path)] +pub struct IgnoringEmitPath { + pub extension: String, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa::ignoring_output)] +pub struct IgnoringOutput { + pub extension: String, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa::create_temp_dir)] +pub struct CreateTempDir { + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa::incompatible_linking_modifiers)] +pub struct IncompatibleLinkingModifiers; + +#[derive(Diagnostic)] +#[diag(codegen_ssa::add_native_library)] +pub struct AddNativeLibrary { + pub library_path: PathBuf, + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa::multiple_external_func_decl)] +pub struct MultipleExternalFuncDecl<'a> { + #[primary_span] + pub span: Span, + pub function: Symbol, + pub library_name: &'a str, +} + +#[derive(Diagnostic)] +pub enum LinkRlibError { + #[diag(codegen_ssa::rlib_missing_format)] + MissingFormat, + + #[diag(codegen_ssa::rlib_only_rmeta_found)] + OnlyRmetaFound { crate_name: Symbol }, + + #[diag(codegen_ssa::rlib_not_found)] + NotFound { crate_name: Symbol }, +} + +pub struct ThorinErrorWrapper(pub thorin::Error); + +impl IntoDiagnostic<'_> for ThorinErrorWrapper { + fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag; + match self.0 { + thorin::Error::ReadInput(_) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_read_input_failure); + diag + } + thorin::Error::ParseFileKind(_) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_input_file_kind); + diag + } + thorin::Error::ParseObjectFile(_) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_input_object_file); + diag + } + thorin::Error::ParseArchiveFile(_) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_input_archive_file); + diag + } + thorin::Error::ParseArchiveMember(_) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_archive_member); + diag + } + thorin::Error::InvalidInputKind => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_invalid_input_kind); + diag + } + thorin::Error::DecompressData(_) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_decompress_data); + diag + } + thorin::Error::NamelessSection(_, offset) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_section_without_name); + diag.set_arg("offset", format!("0x{:08x}", offset)); + diag + } + thorin::Error::RelocationWithInvalidSymbol(section, offset) => { + diag = + handler.struct_err(fluent::codegen_ssa::thorin_relocation_with_invalid_symbol); + diag.set_arg("section", section); + diag.set_arg("offset", format!("0x{:08x}", offset)); + diag + } + thorin::Error::MultipleRelocations(section, offset) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_multiple_relocations); + diag.set_arg("section", section); + diag.set_arg("offset", format!("0x{:08x}", offset)); + diag + } + thorin::Error::UnsupportedRelocation(section, offset) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_unsupported_relocation); + diag.set_arg("section", section); + diag.set_arg("offset", format!("0x{:08x}", offset)); + diag + } + thorin::Error::MissingDwoName(id) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_missing_dwo_name); + diag.set_arg("id", format!("0x{:08x}", id)); + diag + } + thorin::Error::NoCompilationUnits => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_no_compilation_units); + diag + } + thorin::Error::NoDie => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_no_die); + diag + } + thorin::Error::TopLevelDieNotUnit => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_top_level_die_not_unit); + diag + } + thorin::Error::MissingRequiredSection(section) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_missing_required_section); + diag.set_arg("section", section); + diag + } + thorin::Error::ParseUnitAbbreviations(_) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_unit_abbreviations); + diag + } + thorin::Error::ParseUnitAttribute(_) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_unit_attribute); + diag + } + thorin::Error::ParseUnitHeader(_) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_unit_header); + diag + } + thorin::Error::ParseUnit(_) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_unit); + diag + } + thorin::Error::IncompatibleIndexVersion(section, format, actual) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_incompatible_index_version); + diag.set_arg("section", section); + diag.set_arg("actual", actual); + diag.set_arg("format", format); + diag + } + thorin::Error::OffsetAtIndex(_, index) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_offset_at_index); + diag.set_arg("index", index); + diag + } + thorin::Error::StrAtOffset(_, offset) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_str_at_offset); + diag.set_arg("offset", format!("0x{:08x}", offset)); + diag + } + thorin::Error::ParseIndex(_, section) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_index); + diag.set_arg("section", section); + diag + } + thorin::Error::UnitNotInIndex(unit) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_unit_not_in_index); + diag.set_arg("unit", format!("0x{:08x}", unit)); + diag + } + thorin::Error::RowNotInIndex(_, row) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_row_not_in_index); + diag.set_arg("row", row); + diag + } + thorin::Error::SectionNotInRow => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_section_not_in_row); + diag + } + thorin::Error::EmptyUnit(unit) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_empty_unit); + diag.set_arg("unit", format!("0x{:08x}", unit)); + diag + } + thorin::Error::MultipleDebugInfoSection => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_multiple_debug_info_section); + diag + } + thorin::Error::MultipleDebugTypesSection => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_multiple_debug_types_section); + diag + } + thorin::Error::NotSplitUnit => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_not_split_unit); + diag + } + thorin::Error::DuplicateUnit(unit) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_duplicate_unit); + diag.set_arg("unit", format!("0x{:08x}", unit)); + diag + } + thorin::Error::MissingReferencedUnit(unit) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_missing_referenced_unit); + diag.set_arg("unit", format!("0x{:08x}", unit)); + diag + } + thorin::Error::NoOutputObjectCreated => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_not_output_object_created); + diag + } + thorin::Error::MixedInputEncodings => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_mixed_input_encodings); + diag + } + thorin::Error::Io(e) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_io); + diag.set_arg("error", format!("{e}")); + diag + } + thorin::Error::ObjectRead(e) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_object_read); + diag.set_arg("error", format!("{e}")); + diag + } + thorin::Error::ObjectWrite(e) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_object_write); + diag.set_arg("error", format!("{e}")); + diag + } + thorin::Error::GimliRead(e) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_gimli_read); + diag.set_arg("error", format!("{e}")); + diag + } + thorin::Error::GimliWrite(e) => { + diag = handler.struct_err(fluent::codegen_ssa::thorin_gimli_write); + diag.set_arg("error", format!("{e}")); + diag + } + _ => unimplemented!("Untranslated thorin error"), + } + } +} + +pub struct LinkingFailed<'a> { + pub linker_path: &'a PathBuf, + pub exit_status: ExitStatus, + pub command: &'a Command, + pub escaped_output: &'a str, +} + +impl IntoDiagnostic<'_> for LinkingFailed<'_> { + fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = handler.struct_err(fluent::codegen_ssa::linking_failed); + diag.set_arg("linker_path", format!("{}", self.linker_path.display())); + diag.set_arg("exit_status", format!("{}", self.exit_status)); + + diag.note(format!("{:?}", self.command)).note(self.escaped_output); + + // Trying to match an error from OS linkers + // which by now we have no way to translate. + if self.escaped_output.contains("undefined reference to") { + diag.note(fluent::codegen_ssa::extern_funcs_not_found) + .note(fluent::codegen_ssa::specify_libraries_to_link) + .note(fluent::codegen_ssa::use_cargo_directive); + } + diag + } +} diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 3ef9a634e18..ceebe4d417f 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -6,6 +6,7 @@ #![feature(strict_provenance)] #![feature(int_roundings)] #![feature(if_let_guard)] +#![feature(never_type)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] @@ -43,6 +44,7 @@ pub mod base; pub mod common; pub mod coverageinfo; pub mod debuginfo; +pub mod errors; pub mod glue; pub mod meth; pub mod mir; diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl new file mode 100644 index 00000000000..0d0388a039e --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -0,0 +1,119 @@ +codegen_ssa_lib_def_write_failure = failed to write lib.def file: {$error} + +codegen_ssa_version_script_write_failure = failed to write version script: {$error} + +codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error} + +codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64 + +codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker + +codegen_ssa_L4Bender_exporting_symbols_unimplemented = exporting symbols not implemented yet for L4Bender + +codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error} + +codegen_ssa_copy_path = could not copy {$from} to {$to}: {$error} + +codegen_ssa_copy_path_buf = unable to copy {$source_file} to {$output_path}: {$error} + +codegen_ssa_ignoring_emit_path = ignoring emit path because multiple .{$extension} files were produced + +codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files were produced + +codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error} + +codegen_ssa_incompatible_linking_modifiers = the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs + +codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error} + +codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions + +codegen_ssa_rlib_missing_format = could not find formats for rlibs + +codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, found rmeta (metadata) file + +codegen_ssa_rlib_not_found = could not find rlib for: `{$crate_name}` + +codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status} + +codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified + +codegen_ssa_specify_libraries_to_link = use the `-l` flag to specify native libraries to link + +codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname) + +codegen_ssa_thorin_read_input_failure = failed to read input file + +codegen_ssa_thorin_parse_input_file_kind = failed to parse input file kind + +codegen_ssa_thorin_parse_input_object_file = failed to parse input object file + +codegen_ssa_thorin_parse_input_archive_file = failed to parse input archive file + +codegen_ssa_thorin_parse_archive_member = failed to parse archive member + +codegen_ssa_thorin_invalid_input_kind = input is not an archive or elf object + +codegen_ssa_thorin_decompress_data = failed to decompress compressed section + +codegen_ssa_thorin_section_without_name = section without name at offset {$offset} + +codegen_ssa_thorin_relocation_with_invalid_symbol = relocation with invalid symbol for section `{$section}` at offset {$offset} + +codegen_ssa_thorin_multiple_relocations = multiple relocations for section `{$section}` at offset {$offset} + +codegen_ssa_thorin_unsupported_relocation = unsupported relocation for section {$section} at offset {$offset} + +codegen_ssa_thorin_missing_dwo_name = missing path attribute to DWARF object ({$id}) + +codegen_ssa_thorin_no_compilation_units = input object has no compilation units + +codegen_ssa_thorin_no_die = no top-level debugging information entry in compilation/type unit + +codegen_ssa_thorin_top_level_die_not_unit = top-level debugging information entry is not a compilation/type unit + +codegen_ssa_thorin_missing_required_section = input object missing required section `{$section}` + +codegen_ssa_thorin_parse_unit_abbreviations = failed to parse unit abbreviations + +codegen_ssa_thorin_parse_unit_attribute = failed to parse unit attribute + +codegen_ssa_thorin_parse_unit_header = failed to parse unit header + +codegen_ssa_thorin_parse_unit = failed to parse unit + +codegen_ssa_thorin_incompatible_index_version = incompatible `{$section}` index version: found version {$actual}, expected version {$format} + +codegen_ssa_thorin_offset_at_index = read offset at index {$index} of `.debug_str_offsets.dwo` section + +codegen_ssa_thorin_str_at_offset = read string at offset {$offset} of `.debug_str.dwo` section + +codegen_ssa_thorin_parse_index = failed to parse `{$section}` index section + +codegen_ssa_thorin_unit_not_in_index = unit {$unit} from input package is not in its index + +codegen_ssa_thorin_row_not_in_index = row {$row} found in index's hash table not present in index + +codegen_ssa_thorin_section_not_in_row = section not found in unit's row in index + +codegen_ssa_thorin_empty_unit = unit {$unit} in input DWARF object with no data + +codegen_ssa_thorin_multiple_debug_info_section = multiple `.debug_info.dwo` sections + +codegen_ssa_thorin_multiple_debug_types_section = multiple `.debug_types.dwo` sections in a package + +codegen_ssa_thorin_not_split_unit = regular compilation unit in object (missing dwo identifier) + +codegen_ssa_thorin_duplicate_unit = duplicate split compilation unit ({$unit}) + +codegen_ssa_thorin_missing_referenced_unit = unit {$unit} referenced by executable was not found + +codegen_ssa_thorin_not_output_object_created = no output object was created from inputs + +codegen_ssa_thorin_mixed_input_encodings = input objects haved mixed encodings + +codegen_ssa_thorin_io = {$error} +codegen_ssa_thorin_object_read = {$error} +codegen_ssa_thorin_object_write = {$error} +codegen_ssa_thorin_gimli_read = {$error} +codegen_ssa_thorin_gimli_write = {$error} diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 18be60975e4..a2d507328b3 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -40,9 +40,10 @@ fluent_messages! { attr => "../locales/en-US/attr.ftl", borrowck => "../locales/en-US/borrowck.ftl", builtin_macros => "../locales/en-US/builtin_macros.ftl", + codegen_gcc => "../locales/en-US/codegen_gcc.ftl", + codegen_ssa => "../locales/en-US/codegen_ssa.ftl", compiletest => "../locales/en-US/compiletest.ftl", const_eval => "../locales/en-US/const_eval.ftl", - codegen_gcc => "../locales/en-US/codegen_gcc.ftl", driver => "../locales/en-US/driver.ftl", expand => "../locales/en-US/expand.ftl", hir_analysis => "../locales/en-US/hir_analysis.ftl", @@ -336,19 +337,6 @@ impl DiagnosticMessage { } } } - - /// Returns the `String` contained within the `DiagnosticMessage::Str` variant, assuming that - /// this diagnostic message is of the legacy, non-translatable variety. Panics if this - /// assumption does not hold. - /// - /// Don't use this - it exists to support some places that do comparison with diagnostic - /// strings. - pub fn expect_str(&self) -> &str { - match self { - DiagnosticMessage::Str(s) => s, - _ => panic!("expected non-translatable diagnostic message"), - } - } } /// `From` impl that enables existing diagnostic calls to functions which now take diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 6d2c7aac6af..30aa4f0fa34 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -14,7 +14,7 @@ use rustc_ast::{NodeId, DUMMY_NODE_ID}; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, TransparencyError}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage}; use rustc_feature::Features; use rustc_lint_defs::builtin::{ RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, @@ -68,19 +68,22 @@ fn emit_frag_parse_err( kind: AstFragmentKind, ) { // FIXME(davidtwco): avoid depending on the error message text - if parser.token == token::Eof && e.message[0].0.expect_str().ends_with(", found `<eof>`") { - if !e.span.is_dummy() { - // early end of macro arm (#52866) - e.replace_span_with(parser.sess.source_map().next_point(parser.token.span)); - } + if parser.token == token::Eof + && let DiagnosticMessage::Str(message) = &e.message[0].0 + && message.ends_with(", found `<eof>`") + { let msg = &e.message[0]; e.message[0] = ( - rustc_errors::DiagnosticMessage::Str(format!( + DiagnosticMessage::Str(format!( "macro expansion ends with an incomplete expression: {}", - msg.0.expect_str().replace(", found `<eof>`", ""), + message.replace(", found `<eof>`", ""), )), msg.1, ); + if !e.span.is_dummy() { + // early end of macro arm (#52866) + e.replace_span_with(parser.sess.source_map().next_point(parser.token.span)); + } } if e.span.is_dummy() { // Get around lack of span in error (#30128) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index f1f0c224bbd..4ef4aad902c 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -464,6 +464,16 @@ impl PartialRes { pub fn unresolved_segments(&self) -> usize { self.unresolved_segments } + + #[inline] + pub fn full_res(&self) -> Option<Res<NodeId>> { + (self.unresolved_segments == 0).then_some(self.base_res) + } + + #[inline] + pub fn expect_full_res(&self) -> Res<NodeId> { + self.full_res().expect("unexpected unresolved segments") + } } /// Different kinds of symbols can coexist even if they share the same textual name. diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index c499364056f..69155a422b0 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -197,6 +197,9 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: Symbol /// Enforce that we do not have two items in an impl with the same name. fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) { + if tcx.impl_trait_ref(impl_def_id).is_some() { + return; + } let mut seen_type_items = FxHashMap::default(); let mut seen_value_items = FxHashMap::default(); for &impl_item_ref in tcx.associated_item_def_ids(impl_def_id) { diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 8d9a0388e21..45c84680ad2 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -32,7 +32,6 @@ #![feature(exhaustive_patterns)] #![feature(get_mut_unchecked)] #![feature(if_let_guard)] -#![feature(map_first_last)] #![feature(negative_impls)] #![feature(never_type)] #![feature(extern_types)] diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index c3d87b5b6af..a17793ecd99 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -326,7 +326,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } PathResult::Module(..) => Err(VisResolutionError::ModuleOnly(path.span)), PathResult::NonModule(partial_res) => { - expected_found_error(partial_res.base_res()) + expected_found_error(partial_res.expect_full_res()) } PathResult::Failed { span, label, suggestion, .. } => { Err(VisResolutionError::FailedToResolve(span, label, suggestion)) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 9a3eac2f866..83aae286402 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1050,6 +1050,19 @@ impl<'a> Resolver<'a> { err.span_label(trait_item_span, "item in trait"); err } + ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => { + let mut err = struct_span_err!( + self.session, + span, + E0201, + "duplicate definitions with name `{}`:", + name, + ); + err.span_label(old_span, "previous definition here"); + err.span_label(trait_item_span, "item in trait"); + err.span_label(span, "duplicate definition"); + err + } ResolutionError::InvalidAsmSym => { let mut err = self.session.struct_span_err(span, "invalid `sym` operand"); err.span_label(span, "is a local variable"); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index c08f4a7204d..776c8ad528c 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -641,8 +641,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // Check whether we should interpret this as a bare trait object. if qself.is_none() && let Some(partial_res) = self.r.partial_res_map.get(&ty.id) - && partial_res.unresolved_segments() == 0 - && let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res() + && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res() { // This path is actually a bare trait object. In case of a bare `Fn`-trait // object with anonymous lifetimes, we need this rib to correctly place the @@ -1929,7 +1928,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { match ty.kind { TyKind::ImplicitSelf => true, TyKind::Path(None, _) => { - let path_res = self.r.partial_res_map[&ty.id].base_res(); + let path_res = self.r.partial_res_map[&ty.id].expect_full_res(); if let Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } = path_res { return true; } @@ -1970,7 +1969,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { None } }) - .map(|res| res.base_res()) + .map(|res| res.expect_full_res()) .filter(|res| { // Permit the types that unambiguously always // result in the same type constructor being used @@ -2530,7 +2529,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { Finalize::new(trait_ref.ref_id, trait_ref.path.span), ); self.diagnostic_metadata.currently_processing_impl_trait = None; - if let Some(def_id) = res.base_res().opt_def_id() { + if let Some(def_id) = res.expect_full_res().opt_def_id() { new_id = Some(def_id); new_val = Some((self.r.expect_module(def_id), trait_ref.clone())); } @@ -2618,8 +2617,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.with_current_self_type(self_type, |this| { this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| { debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)"); + let mut seen_trait_items = Default::default(); for item in impl_items { - this.resolve_impl_item(&**item); + this.resolve_impl_item(&**item, &mut seen_trait_items); } }); }); @@ -2633,7 +2633,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ); } - fn resolve_impl_item(&mut self, item: &'ast AssocItem) { + fn resolve_impl_item( + &mut self, + item: &'ast AssocItem, + seen_trait_items: &mut FxHashMap<DefId, Span>, + ) { use crate::ResolutionError::*; match &item.kind { AssocItemKind::Const(_, ty, default) => { @@ -2646,6 +2650,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &item.kind, ValueNS, item.span, + seen_trait_items, |i, s, c| ConstNotMemberOfTrait(i, s, c), ); @@ -2686,6 +2691,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &item.kind, ValueNS, item.span, + seen_trait_items, |i, s, c| MethodNotMemberOfTrait(i, s, c), ); @@ -2714,6 +2720,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &item.kind, TypeNS, item.span, + seen_trait_items, |i, s, c| TypeNotMemberOfTrait(i, s, c), ); @@ -2735,6 +2742,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { kind: &AssocItemKind, ns: Namespace, span: Span, + seen_trait_items: &mut FxHashMap<DefId, Span>, err: F, ) where F: FnOnce(Ident, String, Option<Symbol>) -> ResolutionError<'a>, @@ -2767,7 +2775,25 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }; let res = binding.res(); - let Res::Def(def_kind, _) = res else { bug!() }; + let Res::Def(def_kind, id_in_trait) = res else { bug!() }; + + match seen_trait_items.entry(id_in_trait) { + Entry::Occupied(entry) => { + self.report_error( + span, + ResolutionError::TraitImplDuplicate { + name: ident.name, + old_span: *entry.get(), + trait_item_span: binding.span, + }, + ); + return; + } + Entry::Vacant(entry) => { + entry.insert(span); + } + }; + match (def_kind, kind) { (DefKind::AssocTy, AssocItemKind::Type(..)) | (DefKind::AssocFn, AssocItemKind::Fn(..)) @@ -2859,7 +2885,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } fn is_base_res_local(&self, nid: NodeId) -> bool { - matches!(self.r.partial_res_map.get(&nid).map(|res| res.base_res()), Some(Res::Local(..))) + matches!( + self.r.partial_res_map.get(&nid).map(|res| res.expect_full_res()), + Some(Res::Local(..)) + ) } /// Checks that all of the arms in an or-pattern have exactly the @@ -3346,12 +3375,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { source.defer_to_typeck(), finalize, ) { - Ok(Some(partial_res)) if partial_res.unresolved_segments() == 0 => { - if source.is_expected(partial_res.base_res()) || partial_res.base_res() == Res::Err - { + Ok(Some(partial_res)) if let Some(res) = partial_res.full_res() => { + if source.is_expected(res) || res == Res::Err { partial_res } else { - report_errors(self, Some(partial_res.base_res())) + report_errors(self, Some(res)) } } @@ -3559,20 +3587,21 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }; if path.len() > 1 - && result.base_res() != Res::Err + && let Some(res) = result.full_res() + && res != Res::Err && path[0].ident.name != kw::PathRoot && path[0].ident.name != kw::DollarCrate { let unqualified_result = { match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) { - PathResult::NonModule(path_res) => path_res.base_res(), + PathResult::NonModule(path_res) => path_res.expect_full_res(), PathResult::Module(ModuleOrUniformRoot::Module(module)) => { module.res().unwrap() } _ => return Ok(Some(result)), } }; - if result.base_res() == unqualified_result { + if res == unqualified_result { let lint = lint::builtin::UNUSED_QUALIFICATIONS; self.r.lint_buffer.buffer_lint( lint, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index c05f89a6575..13cd7987e92 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -968,11 +968,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else { return false; }; - if !(matches!( - partial_res.base_res(), - hir::def::Res::Def(hir::def::DefKind::AssocTy, _) - ) && partial_res.unresolved_segments() == 0) - { + if !matches!( + partial_res.full_res(), + Some(hir::def::Res::Def(hir::def::DefKind::AssocTy, _)) + ) { return false; } (ty, position, path) @@ -986,11 +985,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { let Some(partial_res) = self.r.partial_res_map.get(&peeled_ty.id) else { return false; }; - if !(matches!( - partial_res.base_res(), - hir::def::Res::Def(hir::def::DefKind::TyParam, _) - ) && partial_res.unresolved_segments() == 0) - { + if !matches!( + partial_res.full_res(), + Some(hir::def::Res::Def(hir::def::DefKind::TyParam, _)) + ) { return false; } if let ( @@ -1518,20 +1516,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { { // Look for a field with the same name in the current self_type. if let Some(resolution) = self.r.partial_res_map.get(&node_id) { - match resolution.base_res() { - Res::Def(DefKind::Struct | DefKind::Union, did) - if resolution.unresolved_segments() == 0 => - { - if let Some(field_names) = self.r.field_names.get(&did) { - if field_names - .iter() - .any(|&field_name| ident.name == field_name.node) - { - return Some(AssocSuggestion::Field); - } + if let Some(Res::Def(DefKind::Struct | DefKind::Union, did)) = + resolution.full_res() + { + if let Some(field_names) = self.r.field_names.get(&did) { + if field_names.iter().any(|&field_name| ident.name == field_name.node) { + return Some(AssocSuggestion::Field); } } - _ => {} } } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 095a57ae24f..971cd62831d 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -235,6 +235,8 @@ enum ResolutionError<'a> { trait_item_span: Span, code: rustc_errors::DiagnosticId, }, + /// Error E0201: multiple impl items for the same trait item. + TraitImplDuplicate { name: Symbol, trait_item_span: Span, old_span: Span }, /// Inline asm `sym` operand must refer to a `fn` or `static`. InvalidAsmSym, } @@ -1881,12 +1883,10 @@ impl<'a> Resolver<'a> { match self.maybe_resolve_path(&segments, Some(ns), &parent_scope) { PathResult::Module(ModuleOrUniformRoot::Module(module)) => Some(module.res().unwrap()), - PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => { - Some(path_res.base_res()) + PathResult::NonModule(path_res) => path_res.full_res(), + PathResult::Module(ModuleOrUniformRoot::ExternPrelude) | PathResult::Failed { .. } => { + None } - PathResult::Module(ModuleOrUniformRoot::ExternPrelude) - | PathResult::NonModule(..) - | PathResult::Failed { .. } => None, PathResult::Module(..) | PathResult::Indeterminate => unreachable!(), } } @@ -1937,12 +1937,8 @@ impl<'a> Resolver<'a> { return None; } - let partial_res = self.partial_res_map.get(&expr.id)?; - if partial_res.unresolved_segments() != 0 { - return None; - } - - if let Res::Def(def::DefKind::Fn, def_id) = partial_res.base_res() { + let res = self.partial_res_map.get(&expr.id)?.full_res()?; + if let Res::Def(def::DefKind::Fn, def_id) = res { // We only support cross-crate argument rewriting. Uses // within the same crate should be updated to use the new // const generics style. diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index dafa10e9e00..f6f0b3c1139 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -590,9 +590,7 @@ impl<'a> Resolver<'a> { let res = if path.len() > 1 { let res = match self.maybe_resolve_path(&path, Some(MacroNS), parent_scope) { - PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => { - Ok(path_res.base_res()) - } + PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => Ok(res), PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined), PathResult::NonModule(..) | PathResult::Indeterminate @@ -692,9 +690,8 @@ impl<'a> Resolver<'a> { Some(Finalize::new(ast::CRATE_NODE_ID, path_span)), None, ) { - PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => { - let res = path_res.base_res(); - check_consistency(self, &path, path_span, kind, initial_res, res); + PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => { + check_consistency(self, &path, path_span, kind, initial_res, res) } path_res @ PathResult::NonModule(..) | path_res @ PathResult::Failed { .. } => { let (span, label) = if let PathResult::Failed { span, label, .. } = path_res { |
