From 54645e880ff88b8c2d242423733e3e0d26e0c1ea Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Tue, 23 Aug 2022 13:25:03 -0600 Subject: [PATCH 1/8] set up rustc_metadata for SessionDiagnostics, port dependency_format.rs --- .../locales/en-US/metadata.ftl | 21 +++++ compiler/rustc_error_messages/src/lib.rs | 1 + .../rustc_metadata/src/dependency_format.rs | 79 ++++++------------- compiler/rustc_metadata/src/errors.rs | 52 ++++++++++++ compiler/rustc_metadata/src/lib.rs | 3 + 5 files changed, 103 insertions(+), 53 deletions(-) create mode 100644 compiler/rustc_error_messages/locales/en-US/metadata.ftl create mode 100644 compiler/rustc_metadata/src/errors.rs diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl new file mode 100644 index 0000000000000..a27e765446427 --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -0,0 +1,21 @@ +metadata_rlib_required = + crate `{$crate_name}` required to be available in rlib format, but was not found in this form + +metadata_lib_required = + crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form + +metadata_crate_dep_multiple = + cannot satisfy dependencies so `{$crate_name}` only shows up once + .help = having upstream crates all available in one format will likely make this go away + +metadata_two_panic_runtimes = + cannot link together two panic runtimes: {$prev_name} and {$cur_name} + +metadata_bad_panic_strategy = + the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}` + +metadata_required_panic_strategy = + the crate `{$crate_name}` requires panic strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}` + +metadata_incompatible_panic_in_drop_strategy = + the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}` diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 42fb2d538b04d..72174d1f75d12 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -46,6 +46,7 @@ fluent_messages! { infer => "../locales/en-US/infer.ftl", lint => "../locales/en-US/lint.ftl", monomorphize => "../locales/en-US/monomorphize.ftl", + metadata => "../locales/en-US/metadata.ftl", parser => "../locales/en-US/parser.ftl", passes => "../locales/en-US/passes.ftl", plugin_impl => "../locales/en-US/plugin_impl.ftl", diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index b765c34f8e364..5d1082acc0beb 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -52,6 +52,10 @@ //! than finding a number of solutions (there are normally quite a few). use crate::creader::CStore; +use crate::errors::{ + BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, LibRequired, + RequiredPanicStrategy, RlibRequired, TwoPanicRuntimes, +}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::CrateNum; @@ -136,11 +140,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { if src.rlib.is_some() { continue; } - sess.err(&format!( - "crate `{}` required to be available in rlib format, \ - but was not found in this form", - tcx.crate_name(cnum) - )); + sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum).to_string() }); } return Vec::new(); } @@ -224,12 +224,10 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { Linkage::Static => "rlib", _ => "dylib", }; - sess.err(&format!( - "crate `{}` required to be available in {} format, \ - but was not found in this form", - tcx.crate_name(cnum), - kind - )); + sess.emit_err(LibRequired { + crate_name: tcx.crate_name(cnum).to_string(), + kind: kind.to_string(), + }); } } } @@ -254,16 +252,7 @@ fn add_library( // can be refined over time. if link2 != link || link == RequireStatic { tcx.sess - .struct_err(&format!( - "cannot satisfy dependencies so `{}` only \ - shows up once", - tcx.crate_name(cnum) - )) - .help( - "having upstream crates all available in one format \ - will likely make this go away", - ) - .emit(); + .emit_err(CrateDepMultiple { crate_name: tcx.crate_name(cnum).to_string() }); } } None => { @@ -358,13 +347,9 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { if tcx.is_panic_runtime(cnum) { if let Some((prev, _)) = panic_runtime { - let prev_name = tcx.crate_name(prev); - let cur_name = tcx.crate_name(cnum); - sess.err(&format!( - "cannot link together two \ - panic runtimes: {} and {}", - prev_name, cur_name - )); + let prev_name = tcx.crate_name(prev).to_string(); + let cur_name = tcx.crate_name(cnum).to_string(); + sess.emit_err(TwoPanicRuntimes { prev_name, cur_name }); } panic_runtime = Some(( cnum, @@ -384,13 +369,10 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { // First up, validate that our selected panic runtime is indeed exactly // our same strategy. if found_strategy != desired_strategy { - sess.err(&format!( - "the linked panic runtime `{}` is \ - not compiled with this crate's \ - panic strategy `{}`", - tcx.crate_name(runtime_cnum), - desired_strategy.desc() - )); + sess.emit_err(BadPanicStrategy { + runtime: tcx.crate_name(runtime_cnum).to_string(), + strategy: desired_strategy.desc().to_string(), + }); } // Next up, verify that all other crates are compatible with this panic @@ -407,28 +389,19 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { } if let Some(found_strategy) = tcx.required_panic_strategy(cnum) && desired_strategy != found_strategy { - sess.err(&format!( - "the crate `{}` requires \ - panic strategy `{}` which is \ - incompatible with this crate's \ - strategy of `{}`", - tcx.crate_name(cnum), - found_strategy.desc(), - desired_strategy.desc() - )); + sess.emit_err(RequiredPanicStrategy { + crate_name: tcx.crate_name(cnum).to_string(), + found_strategy: found_strategy.desc().to_string(), + desired_strategy: desired_strategy.desc().to_string() }); } let found_drop_strategy = tcx.panic_in_drop_strategy(cnum); if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy { - sess.err(&format!( - "the crate `{}` is compiled with the \ - panic-in-drop strategy `{}` which is \ - incompatible with this crate's \ - strategy of `{}`", - tcx.crate_name(cnum), - found_drop_strategy.desc(), - tcx.sess.opts.unstable_opts.panic_in_drop.desc() - )); + sess.emit_err(IncompatiblePanicInDropStrategy { + crate_name: tcx.crate_name(cnum).to_string(), + found_strategy: found_drop_strategy.desc().to_string(), + desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop.desc().to_string(), + }); } } } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs new file mode 100644 index 0000000000000..702863c376b93 --- /dev/null +++ b/compiler/rustc_metadata/src/errors.rs @@ -0,0 +1,52 @@ +// use rustc_errors::ErrorGuaranteed; +use rustc_macros::SessionDiagnostic; + +#[derive(SessionDiagnostic)] +#[diag(metadata::rlib_required)] +pub struct RlibRequired { + pub crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::lib_required)] +pub struct LibRequired { + pub crate_name: String, + pub kind: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::crate_dep_multiple)] +#[help] +pub struct CrateDepMultiple { + pub crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::two_panic_runtimes)] +pub struct TwoPanicRuntimes { + pub prev_name: String, + pub cur_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::bad_panic_strategy)] +pub struct BadPanicStrategy { + pub runtime: String, + pub strategy: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::required_panic_strategy)] +pub struct RequiredPanicStrategy { + pub crate_name: String, + pub found_strategy: String, + pub desired_strategy: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::incompatible_panic_in_drop_strategy)] +pub struct IncompatiblePanicInDropStrategy { + pub crate_name: String, + pub found_strategy: String, + pub desired_strategy: String, +} diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 6440f3e390cf1..fae5b664f4e43 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -16,6 +16,8 @@ #![feature(never_type)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] extern crate proc_macro; @@ -34,6 +36,7 @@ mod native_libs; mod rmeta; pub mod creader; +pub mod errors; pub mod fs; pub mod locator; From 3ed93107ff0f92a64391e3c0936fb17195d525aa Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Tue, 23 Aug 2022 16:33:28 -0600 Subject: [PATCH 2/8] port native_libs.rs to SessionDiagnostics --- .../locales/en-US/metadata.ftl | 102 ++++++++ compiler/rustc_metadata/src/errors.rs | 232 ++++++++++++++++++ compiler/rustc_metadata/src/native_libs.rs | 182 ++++---------- 3 files changed, 388 insertions(+), 128 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index a27e765446427..0685981f9bb49 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -19,3 +19,105 @@ metadata_required_panic_strategy = metadata_incompatible_panic_in_drop_strategy = the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}` + +metadata_multiple_names_in_link = + multiple `name` arguments in a single `#[link]` attribute + +metadata_multiple_kinds_in_link = + multiple `kind` arguments in a single `#[link]` attribute + +metadata_link_name_form = + link name must be of the form `name = "string"` + +metadata_link_kind_form = + link kind must be of the form `kind = "string"` + +metadata_link_modifiers_form = + link modifiers must be of the form `modifiers = "string"` + +metadata_link_cfg_form = + link cfg must be of the form `cfg(/* predicate */)` + +metadata_wasm_import_form = + wasm import module must be of the form `wasm_import_module = "string"` + +metadata_empty_link_name = + link name must not be empty + .label = empty link name + +metadata_link_framework_apple = + link kind `framework` is only supported on Apple targets + +metadata_framework_only_windows = + link kind `raw-dylib` is only supported on Windows targets + +metadata_unknown_link_kind = + unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib + .label = unknown link kind + +metadata_multiple_link_modifiers = + multiple `modifiers` arguments in a single `#[link]` attribute + +metadata_multiple_cfgs = + multiple `cfg` arguments in a single `#[link]` attribute + +metadata_link_cfg_single_predicate = + link cfg must have a single predicate argument + +metadata_multiple_wasm_import = + multiple `wasm_import_module` arguments in a single `#[link]` attribute + +metadata_unexpected_link_arg = + unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type + +metadata_invalid_link_modifier = + invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed + +metadata_multiple_modifiers = + multiple `{$modifier}` modifiers in a single `modifiers` argument + +metadata_bundle_needs_static = + linking modifier `bundle` is only compatible with `static` linking kind + +metadata_whole_archive_needs_static = + linking modifier `whole-archive` is only compatible with `static` linking kind + +metadata_as_needed_compatibility = + linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds + +metadata_unknown_link_modifier = + unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed + +metadata_incompatible_wasm_link = + `wasm_import_module` is incompatible with other arguments in `#[link]` attributes + +metadata_link_requires_name = + `#[link]` attribute requires a `name = "string"` argument + .label = missing `name` argument + +metadata_raw_dylib_no_nul = + link name must not contain NUL characters if link kind is `raw-dylib` + +metadata_link_ordinal_raw_dylib = + `#[link_ordinal]` is only supported if link kind is `raw-dylib` + +metadata_lib_framework_apple = + library kind `framework` is only supported on Apple targets + +metadata_empty_renaming_target = + an empty renaming target was specified for library `{$lib_name}` + +metadata_renaming_no_link = + renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library + +metadata_multiple_renamings = + multiple renamings were specified for library `{$lib_name}` + +metadata_no_link_mod_override = + overriding linking modifiers from command line is not supported + +metadata_unsupported_abi_i686 = + ABI not supported by `#[link(kind = "raw-dylib")]` on i686 + +metadata_unsupported_abi = + ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 702863c376b93..7e3c9b66fbdf5 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -1,5 +1,6 @@ // use rustc_errors::ErrorGuaranteed; use rustc_macros::SessionDiagnostic; +use rustc_span::Span; #[derive(SessionDiagnostic)] #[diag(metadata::rlib_required)] @@ -50,3 +51,234 @@ pub struct IncompatiblePanicInDropStrategy { pub found_strategy: String, pub desired_strategy: String, } + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_names_in_link)] +pub struct MultipleNamesInLink { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_kinds_in_link)] +pub struct MultipleKindsInLink { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_name_form)] +pub struct LinkNameForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_kind_form)] +pub struct LinkKindForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_modifiers_form)] +pub struct LinkModifiersForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_cfg_form)] +pub struct LinkCfgForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::wasm_import_form)] +pub struct WasmImportForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::empty_link_name, code = "E0454")] +pub struct EmptyLinkName { + #[label] + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_framework_apple, code = "E0455")] +pub struct LinkFrameworkApple { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::framework_only_windows, code = "E0455")] +pub struct FrameworkOnlyWindows { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unknown_link_kind, code = "E0458")] +pub struct UnknownLinkKind { + #[label] + #[primary_span] + pub span: Span, + pub kind: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_link_modifiers)] +pub struct MultipleLinkModifiers { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_cfgs)] +pub struct MultipleCfgs { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_cfg_single_predicate)] +pub struct LinkCfgSinglePredicate { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_wasm_import)] +pub struct MultipleWasmImport { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unexpected_link_arg)] +pub struct UnexpectedLinkArg { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::invalid_link_modifier)] +pub struct InvalidLinkModifier { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_modifiers)] +pub struct MultipleModifiers { + #[primary_span] + pub span: Span, + pub modifier: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::bundle_needs_static)] +pub struct BundleNeedsStatic { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::whole_archive_needs_static)] +pub struct WholeArchiveNeedsStatic { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::as_needed_compatibility)] +pub struct AsNeededCompatibility { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unknown_link_modifier)] +pub struct UnknownLinkModifier { + #[primary_span] + pub span: Span, + pub modifier: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::incompatible_wasm_link)] +pub struct IncompatibleWasmLink { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_requires_name, code = "E0459")] +pub struct LinkRequiresName { + #[label] + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::raw_dylib_no_nul)] +pub struct RawDylibNoNul { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::link_ordinal_raw_dylib)] +pub struct LinkOrdinalRawDylib { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::lib_framework_apple)] +pub struct LibFrameworkApple; + +#[derive(SessionDiagnostic)] +#[diag(metadata::empty_renaming_target)] +pub struct EmptyRenamingTarget { + pub lib_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::renaming_no_link)] +pub struct RenamingNoLink { + pub lib_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_renamings)] +pub struct MultipleRenamings { + pub lib_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_link_mod_override)] +pub struct NoLinkModOverride { + #[primary_span] + pub span: Option, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unsupported_abi_i686)] +pub struct UnsupportedAbiI686 { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unsupported_abi)] +pub struct UnsupportedAbi { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 8bafe203748f3..e8489232fbda6 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -12,6 +12,17 @@ use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; use rustc_target::spec::abi::Abi; +use crate::errors::{ + AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, EmptyRenamingTarget, + FrameworkOnlyWindows, IncompatibleWasmLink, InvalidLinkModifier, LibFrameworkApple, + LinkCfgForm, LinkCfgSinglePredicate, LinkFrameworkApple, LinkKindForm, LinkModifiersForm, + LinkNameForm, LinkOrdinalRawDylib, LinkRequiresName, MultipleCfgs, MultipleKindsInLink, + MultipleLinkModifiers, MultipleModifiers, MultipleNamesInLink, MultipleRenamings, + MultipleWasmImport, NoLinkModOverride, RawDylibNoNul, RenamingNoLink, UnexpectedLinkArg, + UnknownLinkKind, UnknownLinkModifier, UnsupportedAbi, UnsupportedAbiI686, WasmImportForm, + WholeArchiveNeedsStatic, +}; + pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { tcx, libs: Vec::new() }; for id in tcx.hir().items() { @@ -66,32 +77,26 @@ impl<'tcx> Collector<'tcx> { match item.name_or_empty() { sym::name => { if name.is_some() { - let msg = "multiple `name` arguments in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleNamesInLink { span: item.span() }); continue; } let Some(link_name) = item.value_str() else { - let msg = "link name must be of the form `name = \"string\"`"; - sess.span_err(item.span(), msg); + sess.emit_err(LinkNameForm { span: item.span() }); continue; }; let span = item.name_value_literal_span().unwrap(); if link_name.is_empty() { - struct_span_err!(sess, span, E0454, "link name must not be empty") - .span_label(span, "empty link name") - .emit(); + sess.emit_err(EmptyLinkName { span }); } name = Some((link_name, span)); } sym::kind => { if kind.is_some() { - let msg = "multiple `kind` arguments in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleKindsInLink { span: item.span() }); continue; } let Some(link_kind) = item.value_str() else { - let msg = "link kind must be of the form `kind = \"string\"`"; - sess.span_err(item.span(), msg); + sess.emit_err(LinkKindForm { span: item.span() }); continue; }; @@ -101,25 +106,13 @@ impl<'tcx> Collector<'tcx> { "dylib" => NativeLibKind::Dylib { as_needed: None }, "framework" => { if !sess.target.is_like_osx { - struct_span_err!( - sess, - span, - E0455, - "link kind `framework` is only supported on Apple targets" - ) - .emit(); + sess.emit_err(LinkFrameworkApple { span }); } NativeLibKind::Framework { as_needed: None } } "raw-dylib" => { if !sess.target.is_like_windows { - struct_span_err!( - sess, - span, - E0455, - "link kind `raw-dylib` is only supported on Windows targets" - ) - .emit(); + sess.emit_err(FrameworkOnlyWindows { span }); } else if !features.raw_dylib { feature_err( &sess.parse_sess, @@ -132,13 +125,7 @@ impl<'tcx> Collector<'tcx> { NativeLibKind::RawDylib } kind => { - let msg = format!( - "unknown link kind `{kind}`, expected one of: \ - static, dylib, framework, raw-dylib" - ); - struct_span_err!(sess, span, E0458, "{}", msg) - .span_label(span, "unknown link kind") - .emit(); + sess.emit_err(UnknownLinkKind { span, kind: kind.to_string() }); continue; } }; @@ -146,32 +133,26 @@ impl<'tcx> Collector<'tcx> { } sym::modifiers => { if modifiers.is_some() { - let msg = - "multiple `modifiers` arguments in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleLinkModifiers { span: item.span() }); continue; } let Some(link_modifiers) = item.value_str() else { - let msg = "link modifiers must be of the form `modifiers = \"string\"`"; - sess.span_err(item.span(), msg); + sess.emit_err(LinkModifiersForm { span: item.span() }); continue; }; modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap())); } sym::cfg => { if cfg.is_some() { - let msg = "multiple `cfg` arguments in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleCfgs { span: item.span() }); continue; } let Some(link_cfg) = item.meta_item_list() else { - let msg = "link cfg must be of the form `cfg(/* predicate */)`"; - sess.span_err(item.span(), msg); + sess.emit_err(LinkCfgForm { span: item.span() }); continue; }; let [NestedMetaItem::MetaItem(link_cfg)] = link_cfg else { - let msg = "link cfg must have a single predicate argument"; - sess.span_err(item.span(), msg); + sess.emit_err(LinkCfgSinglePredicate { span: item.span() }); continue; }; if !features.link_cfg { @@ -187,15 +168,11 @@ impl<'tcx> Collector<'tcx> { } sym::wasm_import_module => { if wasm_import_module.is_some() { - let msg = "multiple `wasm_import_module` arguments \ - in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleWasmImport { span: item.span() }); continue; } let Some(link_wasm_import_module) = item.value_str() else { - let msg = "wasm import module must be of the form \ - `wasm_import_module = \"string\"`"; - sess.span_err(item.span(), msg); + sess.emit_err(WasmImportForm { span: item.span() }); continue; }; wasm_import_module = Some((link_wasm_import_module, item.span())); @@ -243,9 +220,7 @@ impl<'tcx> Collector<'tcx> { import_name_type = Some((link_import_name_type, item.span())); } _ => { - let msg = "unexpected `#[link]` argument, expected one of: \ - name, kind, modifiers, cfg, wasm_import_module, import_name_type"; - sess.span_err(item.span(), msg); + sess.emit_err(UnexpectedLinkArg { span: item.span() }); } } } @@ -257,11 +232,7 @@ impl<'tcx> Collector<'tcx> { let (modifier, value) = match modifier.strip_prefix(&['+', '-']) { Some(m) => (m, modifier.starts_with('+')), None => { - sess.span_err( - span, - "invalid linking modifier syntax, expected '+' or '-' prefix \ - before one of: bundle, verbatim, whole-archive, as-needed", - ); + sess.emit_err(InvalidLinkModifier { span }); continue; } }; @@ -279,10 +250,10 @@ impl<'tcx> Collector<'tcx> { } let assign_modifier = |dst: &mut Option| { if dst.is_some() { - let msg = format!( - "multiple `{modifier}` modifiers in a single `modifiers` argument" - ); - sess.span_err(span, &msg); + sess.emit_err(MultipleModifiers { + span, + modifier: modifier.to_string(), + }); } else { *dst = Some(value); } @@ -292,11 +263,7 @@ impl<'tcx> Collector<'tcx> { assign_modifier(bundle) } ("bundle", _) => { - sess.span_err( - span, - "linking modifier `bundle` is only compatible with \ - `static` linking kind", - ); + sess.emit_err(BundleNeedsStatic { span }); } ("verbatim", _) => { @@ -308,11 +275,7 @@ impl<'tcx> Collector<'tcx> { assign_modifier(whole_archive) } ("whole-archive", _) => { - sess.span_err( - span, - "linking modifier `whole-archive` is only compatible with \ - `static` linking kind", - ); + sess.emit_err(WholeArchiveNeedsStatic { span }); } ("as-needed", Some(NativeLibKind::Dylib { as_needed })) @@ -321,21 +284,14 @@ impl<'tcx> Collector<'tcx> { assign_modifier(as_needed) } ("as-needed", _) => { - sess.span_err( - span, - "linking modifier `as-needed` is only compatible with \ - `dylib` and `framework` linking kinds", - ); + sess.emit_err(AsNeededCompatibility { span }); } _ => { - sess.span_err( + sess.emit_err(UnknownLinkModifier { span, - format!( - "unknown linking modifier `{modifier}`, expected one of: \ - bundle, verbatim, whole-archive, as-needed" - ), - ); + modifier: modifier.to_string(), + }); } } } @@ -343,19 +299,10 @@ impl<'tcx> Collector<'tcx> { if let Some((_, span)) = wasm_import_module { if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() { - let msg = "`wasm_import_module` is incompatible with \ - other arguments in `#[link]` attributes"; - sess.span_err(span, msg); + sess.emit_err(IncompatibleWasmLink { span }); } } else if name.is_none() { - struct_span_err!( - sess, - m.span, - E0459, - "`#[link]` attribute requires a `name = \"string\"` argument" - ) - .span_label(m.span, "missing `name` argument") - .emit(); + sess.emit_err(LinkRequiresName { span: m.span }); } // Do this outside of the loop so that `import_name_type` can be specified before `kind`. @@ -369,10 +316,7 @@ impl<'tcx> Collector<'tcx> { let dll_imports = match kind { Some(NativeLibKind::RawDylib) => { if let Some((name, span)) = name && name.as_str().contains('\0') { - sess.span_err( - span, - "link name must not contain NUL characters if link kind is `raw-dylib`", - ); + sess.emit_err(RawDylibNoNul { span }); } foreign_mod_items .iter() @@ -401,10 +345,7 @@ impl<'tcx> Collector<'tcx> { .iter() .find(|a| a.has_name(sym::link_ordinal)) .unwrap(); - sess.span_err( - link_ordinal_attr.span, - "`#[link_ordinal]` is only supported if link kind is `raw-dylib`", - ); + sess.emit_err(LinkOrdinalRawDylib { span: link_ordinal_attr.span }); } } @@ -430,7 +371,7 @@ impl<'tcx> Collector<'tcx> { for lib in &self.tcx.sess.opts.libs { if let NativeLibKind::Framework { .. } = lib.kind && !self.tcx.sess.target.is_like_osx { // Cannot check this when parsing options because the target is not yet available. - self.tcx.sess.err("library kind `framework` is only supported on Apple targets"); + self.tcx.sess.emit_err(LibFrameworkApple); } if let Some(ref new_name) = lib.new_name { let any_duplicate = self @@ -439,23 +380,11 @@ impl<'tcx> Collector<'tcx> { .filter_map(|lib| lib.name.as_ref()) .any(|n| n.as_str() == lib.name); if new_name.is_empty() { - self.tcx.sess.err(format!( - "an empty renaming target was specified for library `{}`", - lib.name - )); + self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: lib.name.clone() }); } else if !any_duplicate { - self.tcx.sess.err(format!( - "renaming of the library `{}` was specified, \ - however this crate contains no `#[link(...)]` \ - attributes referencing this library", - lib.name - )); + self.tcx.sess.emit_err(RenamingNoLink { lib_name: lib.name.clone() }); } else if !renames.insert(&lib.name) { - self.tcx.sess.err(format!( - "multiple renamings were \ - specified for library `{}`", - lib.name - )); + self.tcx.sess.emit_err(MultipleRenamings { lib_name: lib.name.clone() }); } } } @@ -480,10 +409,13 @@ impl<'tcx> Collector<'tcx> { // involved or not, library reordering and kind overriding without // explicit `:rename` in particular. if lib.has_modifiers() || passed_lib.has_modifiers() { - let msg = "overriding linking modifiers from command line is not supported"; match lib.foreign_module { - Some(def_id) => self.tcx.sess.span_err(self.tcx.def_span(def_id), msg), - None => self.tcx.sess.err(msg), + Some(def_id) => self.tcx.sess.emit_err(NoLinkModOverride { + span: Some(self.tcx.def_span(def_id)), + }), + None => { + self.tcx.sess.emit_err(NoLinkModOverride { span: None }) + } }; } if passed_lib.kind != NativeLibKind::Unspecified { @@ -562,20 +494,14 @@ impl<'tcx> Collector<'tcx> { DllCallingConvention::Vectorcall(self.i686_arg_list_size(item)) } _ => { - self.tcx.sess.span_fatal( - item.span, - r#"ABI not supported by `#[link(kind = "raw-dylib")]` on i686"#, - ); + self.tcx.sess.emit_fatal(UnsupportedAbiI686 { span: item.span }); } } } else { match abi { Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C, _ => { - self.tcx.sess.span_fatal( - item.span, - r#"ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture"#, - ); + self.tcx.sess.emit_fatal(UnsupportedAbi { span: item.span }); } } }; From f7e462a6c7faaea4bfce236fb94b4622ea8260ef Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Tue, 23 Aug 2022 16:40:43 -0600 Subject: [PATCH 3/8] port encoder.rs to SessionDiagnostics --- .../locales/en-US/metadata.ftl | 9 +++++++++ compiler/rustc_metadata/src/errors.rs | 18 ++++++++++++++++++ compiler/rustc_metadata/src/rmeta/encoder.rs | 7 ++++--- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index 0685981f9bb49..8cce1f007e227 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -121,3 +121,12 @@ metadata_unsupported_abi_i686 = metadata_unsupported_abi = ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture + +metadata_fail_create_file_encoder = + failed to create file encoder: {$err} + +metadata_fail_seek_file = + failed to seek the file: {$err} + +metadata_fail_write_file = + failed to write to the file: {$err} diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 7e3c9b66fbdf5..5edc59bf9e923 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -282,3 +282,21 @@ pub struct UnsupportedAbi { #[primary_span] pub span: Span, } + +#[derive(SessionDiagnostic)] +#[diag(metadata::fail_create_file_encoder)] +pub struct FailCreateFileEncoder { + pub err: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::fail_seek_file)] +pub struct FailSeekFile { + pub err: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::fail_write_file)] +pub struct FailWriteFile { + pub err: String, +} diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 3482d9f04514e..2b1f9f17a3c85 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1,3 +1,4 @@ +use crate::errors::{FailCreateFileEncoder, FailSeekFile, FailWriteFile}; use crate::rmeta::def_path_hash_map::DefPathHashMapRef; use crate::rmeta::table::TableBuilder; use crate::rmeta::*; @@ -2269,7 +2270,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { let mut encoder = opaque::FileEncoder::new(path) - .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to create file encoder: {}", err))); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailCreateFileEncoder { err: err.to_string() })); encoder.emit_raw_bytes(METADATA_HEADER); // Will be filled with the root position after encoding everything. @@ -2314,10 +2315,10 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { // Encode the root position. let header = METADATA_HEADER.len(); file.seek(std::io::SeekFrom::Start(header as u64)) - .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to seek the file: {}", err))); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailSeekFile { err: err.to_string() })); let pos = root.position.get(); file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8]) - .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to write to the file: {}", err))); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err: err.to_string() })); // Return to the position where we are before writing the root position. file.seek(std::io::SeekFrom::Start(pos_before_seek)).unwrap(); From 32e1823b2275cf55a598e65c5093a28122b4039f Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Tue, 23 Aug 2022 17:03:49 -0600 Subject: [PATCH 4/8] port creader.rs to SessionDiagnostics --- .../locales/en-US/metadata.ftl | 28 ++++++++++ compiler/rustc_metadata/src/creader.rs | 56 ++++++++----------- compiler/rustc_metadata/src/errors.rs | 52 +++++++++++++++++ 3 files changed, 102 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index 8cce1f007e227..3ce1275a89919 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -130,3 +130,31 @@ metadata_fail_seek_file = metadata_fail_write_file = failed to write to the file: {$err} + +metadata_crate_not_panic_runtime = + the crate `{$crate_name}` is not a panic runtime + +metadata_no_panic_strategy = + the crate `{$crate_name}` does not have the panic strategy `{$strategy}` + +metadata_profiler_builtins_needs_core = + `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]` + +metadata_not_profiler_runtime = + the crate `{$crate_name}` is not a profiler runtime + +metadata_no_multiple_global_alloc = + cannot define multiple global allocators + .label = cannot define a new global allocator + +metadata_prev_global_alloc = + previous global allocator defined here + +metadata_conflicting_global_alloc = + the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name} + +metadata_global_alloc_required = + no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait + +metadata_no_transitive_needs_dep = + the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}` diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 708d0b1fd8a30..f9aa3733f6a37 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1,5 +1,9 @@ //! Validates all used crates and extern libraries and loads their metadata +use crate::errors::{ + ConflictingGlobalAlloc, CrateNotPanicRuntime, GlobalAllocRequired, NoMultipleGlobalAlloc, + NoPanicStrategy, NoTransitiveNeedsDep, NotProfilerRuntime, ProfilerBuiltinsNeedsCore, +}; use crate::locator::{CrateError, CrateLocator, CratePaths}; use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob}; @@ -746,15 +750,13 @@ impl<'a> CrateLoader<'a> { // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. if !data.is_panic_runtime() { - self.sess.err(&format!("the crate `{}` is not a panic runtime", name)); + self.sess.emit_err(CrateNotPanicRuntime { crate_name: name.to_string() }); } if data.required_panic_strategy() != Some(desired_strategy) { - self.sess.err(&format!( - "the crate `{}` does not have the panic \ - strategy `{}`", - name, - desired_strategy.desc() - )); + self.sess.emit_err(NoPanicStrategy { + crate_name: name.to_string(), + strategy: desired_strategy.desc().to_string(), + }); } self.cstore.injected_panic_runtime = Some(cnum); @@ -774,10 +776,7 @@ impl<'a> CrateLoader<'a> { let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime); if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) { - self.sess.err( - "`profiler_builtins` crate (required by compiler options) \ - is not compatible with crate attribute `#![no_core]`", - ); + self.sess.emit_err(ProfilerBuiltinsNeedsCore); } let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; }; @@ -785,18 +784,14 @@ impl<'a> CrateLoader<'a> { // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !data.is_profiler_runtime() { - self.sess.err(&format!("the crate `{}` is not a profiler runtime", name)); + self.sess.emit_err(NotProfilerRuntime { crate_name: name.to_string() }); } } fn inject_allocator_crate(&mut self, krate: &ast::Crate) { self.cstore.has_global_allocator = match &*global_allocator_spans(&self.sess, krate) { [span1, span2, ..] => { - self.sess - .struct_span_err(*span2, "cannot define multiple global allocators") - .span_label(*span2, "cannot define a new global allocator") - .span_label(*span1, "previous global allocator defined here") - .emit(); + self.sess.emit_err(NoMultipleGlobalAlloc { span2: *span2, span1: *span1 }); true } spans => !spans.is_empty(), @@ -832,11 +827,10 @@ impl<'a> CrateLoader<'a> { if data.has_global_allocator() { match global_allocator { Some(other_crate) => { - self.sess.err(&format!( - "the `#[global_allocator]` in {} conflicts with global allocator in: {}", - other_crate, - data.name() - )); + self.sess.emit_err(ConflictingGlobalAlloc { + crate_name: data.name().to_string(), + other_crate_name: other_crate.to_string(), + }); } None => global_allocator = Some(data.name()), } @@ -855,10 +849,7 @@ impl<'a> CrateLoader<'a> { if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator) && !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) { - self.sess.err( - "no global memory allocator found but one is required; link to std or add \ - `#[global_allocator]` to a static item that implements the GlobalAlloc trait", - ); + self.sess.emit_err(GlobalAllocRequired); } self.cstore.allocator_kind = Some(AllocatorKind::Default); } @@ -882,14 +873,11 @@ impl<'a> CrateLoader<'a> { for dep in self.cstore.crate_dependencies_in_reverse_postorder(krate) { let data = self.cstore.get_crate_data(dep); if needs_dep(&data) { - self.sess.err(&format!( - "the crate `{}` cannot depend \ - on a crate that needs {}, but \ - it depends on `{}`", - self.cstore.get_crate_data(krate).name(), - what, - data.name() - )); + self.sess.emit_err(NoTransitiveNeedsDep { + crate_name: self.cstore.get_crate_data(krate).name().to_string(), + needs_crate_name: what.to_string(), + deps_crate_name: data.name().to_string(), + }); } } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 5edc59bf9e923..3d025e89857c9 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -300,3 +300,55 @@ pub struct FailSeekFile { pub struct FailWriteFile { pub err: String, } + +#[derive(SessionDiagnostic)] +#[diag(metadata::crate_not_panic_runtime)] +pub struct CrateNotPanicRuntime { + pub crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_panic_strategy)] +pub struct NoPanicStrategy { + pub crate_name: String, + pub strategy: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::profiler_builtins_needs_core)] +pub struct ProfilerBuiltinsNeedsCore; + +#[derive(SessionDiagnostic)] +#[diag(metadata::not_profiler_runtime)] +pub struct NotProfilerRuntime { + pub crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_multiple_global_alloc)] +pub struct NoMultipleGlobalAlloc { + #[primary_span] + #[label] + pub span2: Span, + #[label(metadata::prev_global_alloc)] + pub span1: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::conflicting_global_alloc)] +pub struct ConflictingGlobalAlloc { + pub crate_name: String, + pub other_crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::global_alloc_required)] +pub struct GlobalAllocRequired; + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_transitive_needs_dep)] +pub struct NoTransitiveNeedsDep { + pub crate_name: String, + pub needs_crate_name: String, + pub deps_crate_name: String, +} From bd8e312d73f07517e24a58a201e8524ebe4da8da Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Tue, 23 Aug 2022 17:16:04 -0600 Subject: [PATCH 5/8] port fs.rs to SessionDiagnostics --- .../locales/en-US/metadata.ftl | 12 +++++++++ compiler/rustc_metadata/src/errors.rs | 26 +++++++++++++++++++ compiler/rustc_metadata/src/fs.rs | 26 ++++++++++++------- 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index 3ce1275a89919..a4881dbc76455 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -158,3 +158,15 @@ metadata_global_alloc_required = metadata_no_transitive_needs_dep = the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}` + +metadata_failed_write_error = + failed to write {$filename}: {$err} + +metadata_failed_create_tempdir = + couldn't create a temp dir: {$err} + +metadata_failed_create_file = + failed to create the file {$filename}: {$err} + +metadata_failed_create_encoded_metadata = + failed to create encoded metadata from file: {$err} diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 3d025e89857c9..c373e49ba4958 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -352,3 +352,29 @@ pub struct NoTransitiveNeedsDep { pub needs_crate_name: String, pub deps_crate_name: String, } + +#[derive(SessionDiagnostic)] +#[diag(metadata::failed_write_error)] +pub struct FailedWriteError { + pub filename: String, + pub err: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::failed_create_tempdir)] +pub struct FailedCreateTempdir { + pub err: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::failed_create_file)] +pub struct FailedCreateFile { + pub filename: String, + pub err: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::failed_create_encoded_metadata)] +pub struct FailedCreateEncodedMetadata { + pub err: String, +} diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index e6072901aaa43..67c18766c5959 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -1,3 +1,6 @@ +use crate::errors::{ + FailedCreateEncodedMetadata, FailedCreateFile, FailedCreateTempdir, FailedWriteError, +}; use crate::{encode_metadata, EncodedMetadata}; use rustc_data_structures::temp_dir::MaybeTempDir; @@ -24,7 +27,10 @@ pub fn emit_metadata(sess: &Session, metadata: &[u8], tmpdir: &MaybeTempDir) -> let result = fs::write(&out_filename, metadata); if let Err(e) = result { - sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)); + sess.emit_fatal(FailedWriteError { + filename: out_filename.display().to_string(), + err: e.to_string(), + }); } out_filename @@ -65,7 +71,7 @@ pub fn encode_and_write_metadata( let metadata_tmpdir = TempFileBuilder::new() .prefix("rmeta") .tempdir_in(out_filename.parent().unwrap_or_else(|| Path::new(""))) - .unwrap_or_else(|err| tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err))); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailedCreateTempdir { err: err.to_string() })); let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps); let metadata_filename = metadata_tmpdir.as_ref().join(METADATA_FILENAME); @@ -74,11 +80,10 @@ pub fn encode_and_write_metadata( match metadata_kind { MetadataKind::None => { std::fs::File::create(&metadata_filename).unwrap_or_else(|e| { - tcx.sess.fatal(&format!( - "failed to create the file {}: {}", - metadata_filename.display(), - e - )) + tcx.sess.emit_fatal(FailedCreateFile { + filename: metadata_filename.display().to_string(), + err: e.to_string(), + }); }); } MetadataKind::Uncompressed | MetadataKind::Compressed => { @@ -94,7 +99,10 @@ pub fn encode_and_write_metadata( let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata); let (metadata_filename, metadata_tmpdir) = if need_metadata_file { if let Err(e) = non_durable_rename(&metadata_filename, &out_filename) { - tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)); + tcx.sess.emit_fatal(FailedWriteError { + filename: out_filename.display().to_string(), + err: e.to_string(), + }); } if tcx.sess.opts.json_artifact_notifications { tcx.sess @@ -110,7 +118,7 @@ pub fn encode_and_write_metadata( // Load metadata back to memory: codegen may need to include it in object files. let metadata = EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|e| { - tcx.sess.fatal(&format!("failed to create encoded metadata from file: {}", e)) + tcx.sess.emit_fatal(FailedCreateEncodedMetadata { err: e.to_string() }); }); let need_metadata_module = metadata_kind == MetadataKind::Compressed; From d0ba1fbaa4f73b6edf27346817b1f74fb352945e Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Wed, 24 Aug 2022 12:14:41 -0600 Subject: [PATCH 6/8] port of locator.rs to SessionDiagnostics, fix some of the errors revealed by tests, manually add a panic to test for dead code --- .../locales/en-US/metadata.ftl | 55 +++ compiler/rustc_metadata/src/errors.rs | 257 ++++++++++++- compiler/rustc_metadata/src/locator.rs | 348 +++++++----------- compiler/rustc_metadata/src/native_libs.rs | 1 - 4 files changed, 448 insertions(+), 213 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index a4881dbc76455..e3e58cf8bed7e 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -170,3 +170,58 @@ metadata_failed_create_file = metadata_failed_create_encoded_metadata = failed to create encoded metadata from file: {$err} + +metadata_non_ascii_name = + cannot load a crate with a non-ascii name `{$crate_name}` + +metadata_extern_location_not_exist = + extern location for {$crate_name} does not exist: {$location} + +metadata_extern_location_not_file = + extern location for {$crate_name} is not a file: {$location} + +metadata_multiple_candidates = + multiple {$flavor} candidates for `{$crate_name}` found + +metadata_multiple_matching_crates = + multiple matching crates for `{$crate_name}` + .note = candidates:{$candidates} + +metadata_symbol_conflicts_current = + the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two. + +metadata_symbol_conflicts_others = + found two different crates with name `{$crate_name}` that are not distinguished by differing `-C metadata`. This will result in symbol conflicts between the two. + +metadata_stable_crate_id_collision = + found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values. + +metadata_dl_error = + {$err} + +metadata_newer_crate_version = + found possibly newer version of crate `{$crate_name}`{$add_info} + .note = perhaps that crate needs to be recompiled? + +metadata_found_crate_versions = + the following crate versions were found:{$found_crates} + +metadata_no_crate_with_triple = + couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info} + +metadata_found_staticlib = + found staticlib `{$crate_name}` instead of rlib or dylib{$add_info} + .help = please recompile that crate using --crate-type lib + +metadata_incompatible_rustc = + found crate `{$crate_name}` compiled by an incompatible version of rustc{$add_info} + .help = please recompile that crate using this compiler ({$rustc_version}) (consider running `cargo clean` first) + +metadata_invalid_meta_files = + found invalid metadata files for crate `{$crate_name}`{$add_info} + +metadata_cannot_find_crate = + can't find crate for `{$crate_name}`{$add_info} + +metadata_no_dylib_plugin = + plugin `{$crate_name}` only found in rlib format, but must be available in dylib format diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index c373e49ba4958..d3f35ca8d164f 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -1,6 +1,10 @@ -// use rustc_errors::ErrorGuaranteed; +use std::path::PathBuf; + +use rustc_errors::{DiagnosticId, ErrorGuaranteed}; use rustc_macros::SessionDiagnostic; -use rustc_span::Span; +use rustc_session::{config, SessionDiagnostic}; +use rustc_span::{sym, Span, Symbol}; +use rustc_target::spec::TargetTriple; #[derive(SessionDiagnostic)] #[diag(metadata::rlib_required)] @@ -104,8 +108,8 @@ pub struct WasmImportForm { #[derive(SessionDiagnostic)] #[diag(metadata::empty_link_name, code = "E0454")] pub struct EmptyLinkName { - #[label] #[primary_span] + #[label] pub span: Span, } @@ -126,8 +130,8 @@ pub struct FrameworkOnlyWindows { #[derive(SessionDiagnostic)] #[diag(metadata::unknown_link_kind, code = "E0458")] pub struct UnknownLinkKind { - #[label] #[primary_span] + #[label] pub span: Span, pub kind: String, } @@ -221,8 +225,8 @@ pub struct IncompatibleWasmLink { #[derive(SessionDiagnostic)] #[diag(metadata::link_requires_name, code = "E0459")] pub struct LinkRequiresName { - #[label] #[primary_span] + #[label] pub span: Span, } @@ -378,3 +382,246 @@ pub struct FailedCreateFile { pub struct FailedCreateEncodedMetadata { pub err: String, } + +#[derive(SessionDiagnostic)] +#[diag(metadata::non_ascii_name)] +pub struct NonAsciiName { + #[primary_span] + pub span: Span, + pub crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::extern_location_not_exist)] +pub struct ExternLocationNotExist { + #[primary_span] + pub span: Span, + pub crate_name: String, + pub location: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::extern_location_not_file)] +pub struct ExternLocationNotFile { + #[primary_span] + pub span: Span, + pub crate_name: String, + pub location: String, +} + +pub struct MultipleCandidates { + pub span: Span, + pub flavor: String, + pub crate_name: String, + pub candidates: Vec, +} + +impl SessionDiagnostic<'_> for MultipleCandidates { + fn into_diagnostic( + self, + sess: &'_ rustc_session::parse::ParseSess, + ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = sess.struct_err(rustc_errors::fluent::metadata::multiple_candidates); + diag.set_arg("crate_name", self.crate_name); + diag.set_arg("flavor", self.flavor); + diag.code(DiagnosticId::Error("E0465".into())); + diag.set_span(self.span); + for (i, candidate) in self.candidates.iter().enumerate() { + diag.span_note(self.span, &format!("candidate #{}: {}", i + 1, candidate.display())); + } + diag + } +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_matching_crates, code = "E0464")] +#[note] +pub struct MultipleMatchingCrates { + #[primary_span] + pub span: Span, + pub crate_name: String, + pub candidates: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::symbol_conflicts_current, code = "E0519")] +pub struct SymbolConflictsCurrent { + #[primary_span] + pub span: Span, + pub crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::symbol_conflicts_others, code = "E0523")] +pub struct SymbolConflictsOthers { + #[primary_span] + pub span: Span, + pub crate_name: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::stable_crate_id_collision)] +pub struct StableCrateIdCollision { + #[primary_span] + pub span: Span, + pub crate_name0: String, + pub crate_name1: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::dl_error)] +pub struct DlError { + #[primary_span] + pub span: Span, + pub err: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::newer_crate_version, code = "E0460")] +#[note] +#[note(metadata::found_crate_versions)] +pub struct NewerCrateVersion { + #[primary_span] + pub span: Span, + pub crate_name: String, + pub add_info: String, + pub found_crates: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_crate_with_triple, code = "E0461")] +#[note(metadata::found_crate_versions)] +pub struct NoCrateWithTriple { + #[primary_span] + pub span: Span, + pub crate_name: String, + pub locator_triple: String, + pub add_info: String, + pub found_crates: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::found_staticlib, code = "E0462")] +#[note(metadata::found_crate_versions)] +#[help] +pub struct FoundStaticlib { + #[primary_span] + pub span: Span, + pub crate_name: String, + pub add_info: String, + pub found_crates: String, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::incompatible_rustc, code = "E0514")] +#[note(metadata::found_crate_versions)] +#[help] +pub struct IncompatibleRustc { + #[primary_span] + pub span: Span, + pub crate_name: String, + pub add_info: String, + pub found_crates: String, + pub rustc_version: String, +} + +pub struct InvalidMetadataFiles { + pub span: Span, + pub crate_name: String, + pub add_info: String, + pub crate_rejections: Vec, +} + +impl SessionDiagnostic<'_> for InvalidMetadataFiles { + fn into_diagnostic( + self, + sess: &'_ rustc_session::parse::ParseSess, + ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = sess.struct_err(rustc_errors::fluent::metadata::invalid_meta_files); + diag.set_arg("crate_name", self.crate_name); + diag.set_arg("add_info", self.add_info); + diag.code(DiagnosticId::Error("E0786".into())); + diag.set_span(self.span); + for crate_rejection in self.crate_rejections { + diag.note(crate_rejection); + } + diag + } +} + +pub struct CannotFindCrate { + pub span: Span, + pub crate_name: String, + pub crate_name_symbol: Symbol, + pub add_info: String, + pub missing_core: bool, + pub current_crate: String, + pub is_nightly_build: bool, + pub profiler_runtime: Symbol, + pub locator_triple: TargetTriple, +} + +impl SessionDiagnostic<'_> for CannotFindCrate { + fn into_diagnostic( + self, + sess: &'_ rustc_session::parse::ParseSess, + ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = sess.struct_err(rustc_errors::fluent::metadata::cannot_find_crate); + diag.set_arg("crate_name", self.crate_name.clone()); + diag.set_arg("add_info", self.add_info); + diag.code(DiagnosticId::Error("E0463".into())); + diag.set_span(self.span); + // FIXME: Find a way to distill this logic down into the derived SessionDiagnostic form + if (self.crate_name_symbol == sym::std || self.crate_name_symbol == sym::core) + && self.locator_triple != TargetTriple::from_triple(config::host_triple()) + { + if self.missing_core { + diag.note(&format!("the `{}` target may not be installed", self.locator_triple)); + } else { + diag.note(&format!( + "the `{}` target may not support the standard library", + self.locator_triple + )); + } + // NOTE: this suggests using rustup, even though the user may not have it installed. + // That's because they could choose to install it; or this may give them a hint which + // target they need to install from their distro. + if self.missing_core { + diag.help(&format!( + "consider downloading the target with `rustup target add {}`", + self.locator_triple + )); + } + // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway. + // NOTE: this is a dummy span if `extern crate std` was injected by the compiler. + // If it's not a dummy, that means someone added `extern crate std` explicitly and + // `#![no_std]` won't help. + if !self.missing_core && self.span.is_dummy() { + diag.note(&format!( + "`std` is required by `{}` because it does not declare `#![no_std]`", + self.current_crate + )); + } + if self.is_nightly_build { + diag.help("consider building the standard library from source with `cargo build -Zbuild-std`"); + } + } else if self.crate_name_symbol == self.profiler_runtime { + diag.note("the compiler may have been built without the profiler runtime"); + } else if self.crate_name.starts_with("rustc_") { + diag.help( + "maybe you need to install the missing components with: \ + `rustup component add rust-src rustc-dev llvm-tools-preview`", + ); + } + diag.span_label(self.span, "can't find crate"); + diag + } +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::no_dylib_plugin, code = "E0457")] +pub struct NoDylibPlugin { + #[primary_span] + pub span: Span, + pub crate_name: String, +} diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 2c1c84b0be26a..83c8756078ec4 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -213,6 +213,12 @@ //! metadata::locator or metadata::creader for all the juicy details! use crate::creader::Library; +use crate::errors::{ + CannotFindCrate, DlError, ExternLocationNotExist, ExternLocationNotFile, FoundStaticlib, + IncompatibleRustc, InvalidMetadataFiles, MultipleCandidates, MultipleMatchingCrates, + NewerCrateVersion, NoCrateWithTriple, NoDylibPlugin, NonAsciiName, StableCrateIdCollision, + SymbolConflictsCurrent, SymbolConflictsOthers, +}; use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -220,14 +226,14 @@ 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, FatalError}; +use rustc_errors::FatalError; use rustc_session::config::{self, CrateType}; use rustc_session::cstore::{CrateSource, MetadataLoader}; use rustc_session::filesearch::FileSearch; use rustc_session::search_paths::PathKind; use rustc_session::utils::CanonicalizedPath; use rustc_session::Session; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::Symbol; use rustc_span::Span; use rustc_target::spec::{Target, TargetTriple}; @@ -938,41 +944,33 @@ impl fmt::Display for MetadataError<'_> { impl CrateError { pub(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), - ), - CrateError::ExternLocationNotExist(crate_name, loc) => sess.struct_span_err( - span, - &format!("extern location for {} does not exist: {}", crate_name, loc.display()), - ), - CrateError::ExternLocationNotFile(crate_name, loc) => sess.struct_span_err( - span, - &format!("extern location for {} is not a file: {}", crate_name, loc.display()), - ), + match self { + CrateError::NonAsciiName(crate_name) => { + sess.emit_err(NonAsciiName { span, crate_name: crate_name.to_string() }); + } + CrateError::ExternLocationNotExist(crate_name, loc) => { + sess.emit_err(ExternLocationNotExist { + span, + crate_name: crate_name.to_string(), + location: loc.display().to_string(), + }); + } + CrateError::ExternLocationNotFile(crate_name, loc) => { + sess.emit_err(ExternLocationNotFile { + span, + crate_name: crate_name.to_string(), + location: loc.display().to_string(), + }); + } CrateError::MultipleCandidates(crate_name, flavor, candidates) => { - let mut err = struct_span_err!( - sess, + sess.emit_err(MultipleCandidates { span, - E0465, - "multiple {} candidates for `{}` found", - flavor, - crate_name, - ); - for (i, candidate) in candidates.iter().enumerate() { - err.span_note(span, &format!("candidate #{}: {}", i + 1, candidate.display())); - } - err + flavor: flavor.to_string(), + crate_name: crate_name.to_string(), + candidates, + }); } CrateError::MultipleMatchingCrates(crate_name, libraries) => { - let mut err = struct_span_err!( - sess, - span, - E0464, - "multiple matching crates for `{}`", - crate_name - ); let mut libraries: Vec<_> = libraries.into_values().collect(); // Make ordering of candidates deterministic. // This has to `clone()` to work around lifetime restrictions with `sort_by_key()`. @@ -1000,223 +998,159 @@ impl CrateError { s }) .collect::(); - err.note(&format!("candidates:{}", candidates)); - err + sess.emit_err(MultipleMatchingCrates { + span, + crate_name: crate_name.to_string(), + candidates, + }); + } + CrateError::SymbolConflictsCurrent(root_name) => { + sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name.to_string() }); + } + CrateError::SymbolConflictsOthers(root_name) => { + sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name.to_string() }); } - CrateError::SymbolConflictsCurrent(root_name) => struct_span_err!( - sess, - span, - E0519, - "the current crate is indistinguishable from one of its dependencies: it has the \ - same crate-name `{}` and was compiled with the same `-C metadata` arguments. \ - This will result in symbol conflicts between the two.", - root_name, - ), - CrateError::SymbolConflictsOthers(root_name) => struct_span_err!( - sess, - span, - E0523, - "found two different crates with name `{}` that are not distinguished by differing \ - `-C metadata`. This will result in symbol conflicts between the two.", - root_name, - ), CrateError::StableCrateIdCollision(crate_name0, crate_name1) => { - let msg = format!( - "found crates (`{}` and `{}`) with colliding StableCrateId values.", - crate_name0, crate_name1 - ); - sess.struct_span_err(span, &msg) + sess.emit_err(StableCrateIdCollision { + span, + crate_name0: crate_name0.to_string(), + crate_name1: crate_name1.to_string(), + }); + } + CrateError::DlOpen(s) | CrateError::DlSym(s) => { + sess.emit_err(DlError { span, err: s.to_string() }); } - CrateError::DlOpen(s) | CrateError::DlSym(s) => sess.struct_span_err(span, &s), CrateError::LocatorCombined(locator) => { let crate_name = locator.crate_name; - let add = match &locator.root { + let add_info = match &locator.root { None => String::new(), Some(r) => format!(" which `{}` depends on", r.name), }; - let mut msg = "the following crate versions were found:".to_string(); - let mut err = if !locator.crate_rejections.via_hash.is_empty() { - let mut err = struct_span_err!( - sess, - span, - E0460, - "found possibly newer version of crate `{}`{}", - crate_name, - add, - ); - err.note("perhaps that crate needs to be recompiled?"); + // FIXME: Is there any way to get these notes and helps onto every diagnostic in this + // huge branch arm without changing them all to manual implementations? + let mut global_loc_notes = Vec::new(); + let mut global_loc_helps = Vec::new(); + if !locator.crate_rejections.via_filename.is_empty() { + let mismatches = locator.crate_rejections.via_filename.iter(); + for CrateMismatch { path, .. } in mismatches { + global_loc_notes.push(format!( + "extern location for {} is of an unknown type: {}", + crate_name, + path.display(), + )); + global_loc_helps.push(format!( + "file name should be lib*.rlib or {}*.{}", + locator.dll_prefix, locator.dll_suffix + )); + } + panic!("!!!!! REVERT THIS COMMIT !!!!!"); + } + let mut found_crates = String::new(); + if !locator.crate_rejections.via_hash.is_empty() { let mismatches = locator.crate_rejections.via_hash.iter(); for CrateMismatch { path, .. } in mismatches { - msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display())); + found_crates.push_str(&format!( + "\ncrate `{}`: {}", + crate_name, + path.display() + )); } if let Some(r) = locator.root { for path in r.source.paths() { - msg.push_str(&format!("\ncrate `{}`: {}", r.name, path.display())); + found_crates.push_str(&format!( + "\ncrate `{}`: {}", + r.name, + path.display() + )); } } - err.note(&msg); - err - } else if !locator.crate_rejections.via_triple.is_empty() { - let mut err = struct_span_err!( - sess, + sess.emit_err(NewerCrateVersion { span, - E0461, - "couldn't find crate `{}` with expected target triple {}{}", - crate_name, - locator.triple, - add, - ); + crate_name: crate_name.to_string(), + add_info, + found_crates, + }); + } else if !locator.crate_rejections.via_triple.is_empty() { let mismatches = locator.crate_rejections.via_triple.iter(); for CrateMismatch { path, got } in mismatches { - msg.push_str(&format!( + found_crates.push_str(&format!( "\ncrate `{}`, target triple {}: {}", crate_name, got, path.display(), )); } - err.note(&msg); - err - } else if !locator.crate_rejections.via_kind.is_empty() { - let mut err = struct_span_err!( - sess, + sess.emit_err(NoCrateWithTriple { span, - E0462, - "found staticlib `{}` instead of rlib or dylib{}", - crate_name, - add, - ); - err.help("please recompile that crate using --crate-type lib"); + crate_name: crate_name.to_string(), + locator_triple: locator.triple.to_string(), + add_info, + found_crates, + }); + } else if !locator.crate_rejections.via_kind.is_empty() { let mismatches = locator.crate_rejections.via_kind.iter(); for CrateMismatch { path, .. } in mismatches { - msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display())); + found_crates.push_str(&format!( + "\ncrate `{}`: {}", + crate_name, + path.display() + )); } - err.note(&msg); - err - } else if !locator.crate_rejections.via_version.is_empty() { - let mut err = struct_span_err!( - sess, + sess.emit_err(FoundStaticlib { span, - E0514, - "found crate `{}` compiled by an incompatible version of rustc{}", - crate_name, - add, - ); - err.help(&format!( - "please recompile that crate using this compiler ({}) \ - (consider running `cargo clean` first)", - rustc_version(), - )); + crate_name: crate_name.to_string(), + add_info, + found_crates, + }); + } else if !locator.crate_rejections.via_version.is_empty() { let mismatches = locator.crate_rejections.via_version.iter(); for CrateMismatch { path, got } in mismatches { - msg.push_str(&format!( + found_crates.push_str(&format!( "\ncrate `{}` compiled by {}: {}", crate_name, got, path.display(), )); } - err.note(&msg); - err - } else if !locator.crate_rejections.via_invalid.is_empty() { - let mut err = struct_span_err!( - sess, + sess.emit_err(IncompatibleRustc { span, - E0786, - "found invalid metadata files for crate `{}`{}", - crate_name, - add, - ); + crate_name: crate_name.to_string(), + add_info, + found_crates, + rustc_version: rustc_version(), + }); + } else if !locator.crate_rejections.via_invalid.is_empty() { + let mut crate_rejections = Vec::new(); for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid { - err.note(&got); + crate_rejections.push(got); } - err + sess.emit_err(InvalidMetadataFiles { + span, + crate_name: crate_name.to_string(), + add_info, + crate_rejections, + }); } else { - let mut err = struct_span_err!( - sess, + sess.emit_err(CannotFindCrate { span, - E0463, - "can't find crate for `{}`{}", - crate_name, - add, - ); - - if (crate_name == sym::std || crate_name == sym::core) - && locator.triple != TargetTriple::from_triple(config::host_triple()) - { - if missing_core { - err.note(&format!( - "the `{}` target may not be installed", - locator.triple - )); - } else { - err.note(&format!( - "the `{}` target may not support the standard library", - locator.triple - )); - } - // NOTE: this suggests using rustup, even though the user may not have it installed. - // That's because they could choose to install it; or this may give them a hint which - // target they need to install from their distro. - if missing_core { - err.help(&format!( - "consider downloading the target with `rustup target add {}`", - locator.triple - )); - } - // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway. - // NOTE: this is a dummy span if `extern crate std` was injected by the compiler. - // If it's not a dummy, that means someone added `extern crate std` explicitly and `#![no_std]` won't help. - if !missing_core && span.is_dummy() { - let current_crate = - sess.opts.crate_name.as_deref().unwrap_or(""); - err.note(&format!( - "`std` is required by `{}` because it does not declare `#![no_std]`", - current_crate - )); - } - if sess.is_nightly_build() { - err.help("consider building the standard library from source with `cargo build -Zbuild-std`"); - } - } else if crate_name - == Symbol::intern(&sess.opts.unstable_opts.profiler_runtime) - { - err.note("the compiler may have been built without the profiler runtime"); - } else if crate_name.as_str().starts_with("rustc_") { - err.help( - "maybe you need to install the missing components with: \ - `rustup component add rust-src rustc-dev llvm-tools-preview`", - ); - } - err.span_label(span, "can't find crate"); - err - }; - - if !locator.crate_rejections.via_filename.is_empty() { - let mismatches = locator.crate_rejections.via_filename.iter(); - for CrateMismatch { path, .. } in mismatches { - err.note(&format!( - "extern location for {} is of an unknown type: {}", - crate_name, - path.display(), - )) - .help(&format!( - "file name should be lib*.rlib or {}*.{}", - locator.dll_prefix, locator.dll_suffix - )); - } + crate_name: crate_name.to_string(), + crate_name_symbol: crate_name, + add_info, + missing_core, + current_crate: sess + .opts + .crate_name + .clone() + .unwrap_or("".to_string()), + is_nightly_build: sess.is_nightly_build(), + profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), + locator_triple: locator.triple, + }); } - err } - CrateError::NonDylibPlugin(crate_name) => struct_span_err!( - sess, - span, - E0457, - "plugin `{}` only found in rlib format, but must be available in dylib format", - crate_name, - ), - }; - - diag.emit(); + CrateError::NonDylibPlugin(crate_name) => { + sess.emit_err(NoDylibPlugin { span, crate_name: crate_name.to_string() }); + } + } } } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index e8489232fbda6..dbaa2e9defa1a 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -1,7 +1,6 @@ use rustc_ast::{NestedMetaItem, CRATE_NODE_ID}; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; From 0d65819d529f222e47164f6c8132d8134909f2a4 Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Fri, 26 Aug 2022 14:39:59 -0600 Subject: [PATCH 7/8] respond to review feedback: mainly eliminate as many conversions as possible... - ... when creating diagnostics in rustc_metadata - use the error_code! macro - pass macro output to diag.code() - use fluent from within manual implementation of SessionDiagnostic - emit the untested errors in case they occur in the wild - stop panicking in the probably-not-dead code, add fixme to write test --- Cargo.lock | 1 + .../locales/en-US/metadata.ftl | 30 +++ compiler/rustc_errors/Cargo.toml | 5 +- compiler/rustc_errors/src/diagnostic.rs | 7 + compiler/rustc_metadata/src/creader.rs | 19 +- .../rustc_metadata/src/dependency_format.rs | 30 ++- compiler/rustc_metadata/src/errors.rs | 215 +++++++++--------- compiler/rustc_metadata/src/fs.rs | 27 +-- compiler/rustc_metadata/src/locator.rs | 102 ++++----- compiler/rustc_metadata/src/native_libs.rs | 18 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 6 +- 11 files changed, 234 insertions(+), 226 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 002d73be7d1de..0ce329ff07086 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3514,6 +3514,7 @@ dependencies = [ "rustc_macros", "rustc_serialize", "rustc_span", + "rustc_target", "serde", "serde_json", "termcolor", diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index e3e58cf8bed7e..dee01bcad4bbc 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -225,3 +225,33 @@ metadata_cannot_find_crate = metadata_no_dylib_plugin = plugin `{$crate_name}` only found in rlib format, but must be available in dylib format + +metadata_target_not_installed = + the `{$locator_triple}` target may not be installed + +metadata_target_no_std_support = + the `{$locator_triple}` target may not support the standard library + +metadata_consider_downloading_target = + consider downloading the target with `rustup target add {$locator_triple}` + +metadata_std_required = + `std` is required by `{$current_crate}` because it does not declare `#![no_std]` + +metadata_consider_building_std = + consider building the standard library from source with `cargo build -Zbuild-std` + +metadata_compiler_missing_profiler = + the compiler may have been built without the profiler runtime + +metadata_install_missing_components = + maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview` + +metadata_cant_find_crate = + can't find crate + +metadata_crate_location_unknown_type = + extern location for {$crate_name} is of an unknown type: {$path} + +metadata_lib_filename_form = + file name should be lib*.rlib or {dll_prefix}*.{dll_suffix} diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index 36805aa874fe7..4d207fd17fb2d 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -15,13 +15,14 @@ rustc_macros = { path = "../rustc_macros" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_hir = { path = "../rustc_hir" } rustc_lint_defs = { path = "../rustc_lint_defs" } +rustc_target = { path = "../rustc_target" } unicode-width = "0.1.4" atty = "0.2" termcolor = "1.0" annotate-snippets = "0.9" termize = "0.1.1" -serde = { version = "1.0.125", features = ["derive"] } +serde = { version = "1.0.125", features = [ "derive" ] } serde_json = "1.0.59" [target.'cfg(windows)'.dependencies] -winapi = { version = "0.3", features = ["handleapi", "synchapi", "winbase"] } +winapi = { version = "0.3", features = [ "handleapi", "synchapi", "winbase" ] } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index f75e2596f361b..b569ef4fc2c91 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -10,6 +10,7 @@ use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_span::edition::LATEST_STABLE_EDITION; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol}; use rustc_span::{edition::Edition, Span, DUMMY_SP}; +use rustc_target::spec::PanicStrategy; use std::borrow::Cow; use std::fmt; use std::hash::{Hash, Hasher}; @@ -144,6 +145,12 @@ impl IntoDiagnosticArg for usize { } } +impl IntoDiagnosticArg for PanicStrategy { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.desc().to_string())) + } +} + impl<'source> Into> for DiagnosticArgValue<'source> { fn into(self) -> FluentValue<'source> { match self { diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index f9aa3733f6a37..edffec8ab55c4 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -750,13 +750,10 @@ impl<'a> CrateLoader<'a> { // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. if !data.is_panic_runtime() { - self.sess.emit_err(CrateNotPanicRuntime { crate_name: name.to_string() }); + self.sess.emit_err(CrateNotPanicRuntime { crate_name: name }); } if data.required_panic_strategy() != Some(desired_strategy) { - self.sess.emit_err(NoPanicStrategy { - crate_name: name.to_string(), - strategy: desired_strategy.desc().to_string(), - }); + self.sess.emit_err(NoPanicStrategy { crate_name: name, strategy: desired_strategy }); } self.cstore.injected_panic_runtime = Some(cnum); @@ -784,7 +781,7 @@ impl<'a> CrateLoader<'a> { // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !data.is_profiler_runtime() { - self.sess.emit_err(NotProfilerRuntime { crate_name: name.to_string() }); + self.sess.emit_err(NotProfilerRuntime { crate_name: name }); } } @@ -828,8 +825,8 @@ impl<'a> CrateLoader<'a> { match global_allocator { Some(other_crate) => { self.sess.emit_err(ConflictingGlobalAlloc { - crate_name: data.name().to_string(), - other_crate_name: other_crate.to_string(), + crate_name: data.name(), + other_crate_name: other_crate, }); } None => global_allocator = Some(data.name()), @@ -874,9 +871,9 @@ impl<'a> CrateLoader<'a> { let data = self.cstore.get_crate_data(dep); if needs_dep(&data) { self.sess.emit_err(NoTransitiveNeedsDep { - crate_name: self.cstore.get_crate_data(krate).name().to_string(), - needs_crate_name: what.to_string(), - deps_crate_name: data.name().to_string(), + crate_name: self.cstore.get_crate_data(krate).name(), + needs_crate_name: what, + deps_crate_name: data.name(), }); } } diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 5d1082acc0beb..9ad0099ad251b 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -140,7 +140,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { if src.rlib.is_some() { continue; } - sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum).to_string() }); + sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) }); } return Vec::new(); } @@ -224,10 +224,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { Linkage::Static => "rlib", _ => "dylib", }; - sess.emit_err(LibRequired { - crate_name: tcx.crate_name(cnum).to_string(), - kind: kind.to_string(), - }); + sess.emit_err(LibRequired { crate_name: tcx.crate_name(cnum), kind: kind }); } } } @@ -251,8 +248,7 @@ fn add_library( // This error is probably a little obscure, but I imagine that it // can be refined over time. if link2 != link || link == RequireStatic { - tcx.sess - .emit_err(CrateDepMultiple { crate_name: tcx.crate_name(cnum).to_string() }); + tcx.sess.emit_err(CrateDepMultiple { crate_name: tcx.crate_name(cnum) }); } } None => { @@ -347,8 +343,8 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { if tcx.is_panic_runtime(cnum) { if let Some((prev, _)) = panic_runtime { - let prev_name = tcx.crate_name(prev).to_string(); - let cur_name = tcx.crate_name(cnum).to_string(); + let prev_name = tcx.crate_name(prev); + let cur_name = tcx.crate_name(cnum); sess.emit_err(TwoPanicRuntimes { prev_name, cur_name }); } panic_runtime = Some(( @@ -370,8 +366,8 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { // our same strategy. if found_strategy != desired_strategy { sess.emit_err(BadPanicStrategy { - runtime: tcx.crate_name(runtime_cnum).to_string(), - strategy: desired_strategy.desc().to_string(), + runtime: tcx.crate_name(runtime_cnum), + strategy: desired_strategy, }); } @@ -390,17 +386,17 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { if let Some(found_strategy) = tcx.required_panic_strategy(cnum) && desired_strategy != found_strategy { sess.emit_err(RequiredPanicStrategy { - crate_name: tcx.crate_name(cnum).to_string(), - found_strategy: found_strategy.desc().to_string(), - desired_strategy: desired_strategy.desc().to_string() }); + crate_name: tcx.crate_name(cnum), + found_strategy, + desired_strategy}); } let found_drop_strategy = tcx.panic_in_drop_strategy(cnum); if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy { sess.emit_err(IncompatiblePanicInDropStrategy { - crate_name: tcx.crate_name(cnum).to_string(), - found_strategy: found_drop_strategy.desc().to_string(), - desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop.desc().to_string(), + crate_name: tcx.crate_name(cnum), + found_strategy: found_drop_strategy, + desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop, }); } } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index d3f35ca8d164f..565c96917e2fc 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -1,59 +1,64 @@ -use std::path::PathBuf; +use std::{ + io::Error, + path::{Path, PathBuf}, +}; -use rustc_errors::{DiagnosticId, ErrorGuaranteed}; +use rustc_errors::{error_code, ErrorGuaranteed}; use rustc_macros::SessionDiagnostic; use rustc_session::{config, SessionDiagnostic}; use rustc_span::{sym, Span, Symbol}; -use rustc_target::spec::TargetTriple; +use rustc_target::spec::{PanicStrategy, TargetTriple}; + +use crate::locator::CrateFlavor; #[derive(SessionDiagnostic)] #[diag(metadata::rlib_required)] pub struct RlibRequired { - pub crate_name: String, + pub crate_name: Symbol, } #[derive(SessionDiagnostic)] #[diag(metadata::lib_required)] -pub struct LibRequired { - pub crate_name: String, - pub kind: String, +pub struct LibRequired<'a> { + pub crate_name: Symbol, + pub kind: &'a str, } #[derive(SessionDiagnostic)] #[diag(metadata::crate_dep_multiple)] #[help] pub struct CrateDepMultiple { - pub crate_name: String, + pub crate_name: Symbol, } #[derive(SessionDiagnostic)] #[diag(metadata::two_panic_runtimes)] pub struct TwoPanicRuntimes { - pub prev_name: String, - pub cur_name: String, + pub prev_name: Symbol, + pub cur_name: Symbol, } #[derive(SessionDiagnostic)] #[diag(metadata::bad_panic_strategy)] pub struct BadPanicStrategy { - pub runtime: String, - pub strategy: String, + pub runtime: Symbol, + pub strategy: PanicStrategy, } #[derive(SessionDiagnostic)] #[diag(metadata::required_panic_strategy)] pub struct RequiredPanicStrategy { - pub crate_name: String, - pub found_strategy: String, - pub desired_strategy: String, + pub crate_name: Symbol, + pub found_strategy: PanicStrategy, + pub desired_strategy: PanicStrategy, } #[derive(SessionDiagnostic)] #[diag(metadata::incompatible_panic_in_drop_strategy)] pub struct IncompatiblePanicInDropStrategy { - pub crate_name: String, - pub found_strategy: String, - pub desired_strategy: String, + pub crate_name: Symbol, + pub found_strategy: PanicStrategy, + pub desired_strategy: PanicStrategy, } #[derive(SessionDiagnostic)] @@ -129,11 +134,11 @@ pub struct FrameworkOnlyWindows { #[derive(SessionDiagnostic)] #[diag(metadata::unknown_link_kind, code = "E0458")] -pub struct UnknownLinkKind { +pub struct UnknownLinkKind<'a> { #[primary_span] #[label] pub span: Span, - pub kind: String, + pub kind: &'a str, } #[derive(SessionDiagnostic)] @@ -180,10 +185,10 @@ pub struct InvalidLinkModifier { #[derive(SessionDiagnostic)] #[diag(metadata::multiple_modifiers)] -pub struct MultipleModifiers { +pub struct MultipleModifiers<'a> { #[primary_span] pub span: Span, - pub modifier: String, + pub modifier: &'a str, } #[derive(SessionDiagnostic)] @@ -209,10 +214,10 @@ pub struct AsNeededCompatibility { #[derive(SessionDiagnostic)] #[diag(metadata::unknown_link_modifier)] -pub struct UnknownLinkModifier { +pub struct UnknownLinkModifier<'a> { #[primary_span] pub span: Span, - pub modifier: String, + pub modifier: &'a str, } #[derive(SessionDiagnostic)] @@ -250,20 +255,20 @@ pub struct LibFrameworkApple; #[derive(SessionDiagnostic)] #[diag(metadata::empty_renaming_target)] -pub struct EmptyRenamingTarget { - pub lib_name: String, +pub struct EmptyRenamingTarget<'a> { + pub lib_name: &'a str, } #[derive(SessionDiagnostic)] #[diag(metadata::renaming_no_link)] -pub struct RenamingNoLink { - pub lib_name: String, +pub struct RenamingNoLink<'a> { + pub lib_name: &'a str, } #[derive(SessionDiagnostic)] #[diag(metadata::multiple_renamings)] -pub struct MultipleRenamings { - pub lib_name: String, +pub struct MultipleRenamings<'a> { + pub lib_name: &'a str, } #[derive(SessionDiagnostic)] @@ -290,32 +295,32 @@ pub struct UnsupportedAbi { #[derive(SessionDiagnostic)] #[diag(metadata::fail_create_file_encoder)] pub struct FailCreateFileEncoder { - pub err: String, + pub err: Error, } #[derive(SessionDiagnostic)] #[diag(metadata::fail_seek_file)] pub struct FailSeekFile { - pub err: String, + pub err: Error, } #[derive(SessionDiagnostic)] #[diag(metadata::fail_write_file)] pub struct FailWriteFile { - pub err: String, + pub err: Error, } #[derive(SessionDiagnostic)] #[diag(metadata::crate_not_panic_runtime)] pub struct CrateNotPanicRuntime { - pub crate_name: String, + pub crate_name: Symbol, } #[derive(SessionDiagnostic)] #[diag(metadata::no_panic_strategy)] pub struct NoPanicStrategy { - pub crate_name: String, - pub strategy: String, + pub crate_name: Symbol, + pub strategy: PanicStrategy, } #[derive(SessionDiagnostic)] @@ -325,7 +330,7 @@ pub struct ProfilerBuiltinsNeedsCore; #[derive(SessionDiagnostic)] #[diag(metadata::not_profiler_runtime)] pub struct NotProfilerRuntime { - pub crate_name: String, + pub crate_name: Symbol, } #[derive(SessionDiagnostic)] @@ -341,8 +346,8 @@ pub struct NoMultipleGlobalAlloc { #[derive(SessionDiagnostic)] #[diag(metadata::conflicting_global_alloc)] pub struct ConflictingGlobalAlloc { - pub crate_name: String, - pub other_crate_name: String, + pub crate_name: Symbol, + pub other_crate_name: Symbol, } #[derive(SessionDiagnostic)] @@ -351,36 +356,36 @@ pub struct GlobalAllocRequired; #[derive(SessionDiagnostic)] #[diag(metadata::no_transitive_needs_dep)] -pub struct NoTransitiveNeedsDep { - pub crate_name: String, - pub needs_crate_name: String, - pub deps_crate_name: String, +pub struct NoTransitiveNeedsDep<'a> { + pub crate_name: Symbol, + pub needs_crate_name: &'a str, + pub deps_crate_name: Symbol, } #[derive(SessionDiagnostic)] #[diag(metadata::failed_write_error)] pub struct FailedWriteError { - pub filename: String, - pub err: String, + pub filename: PathBuf, + pub err: Error, } #[derive(SessionDiagnostic)] #[diag(metadata::failed_create_tempdir)] pub struct FailedCreateTempdir { - pub err: String, + pub err: Error, } #[derive(SessionDiagnostic)] #[diag(metadata::failed_create_file)] -pub struct FailedCreateFile { - pub filename: String, - pub err: String, +pub struct FailedCreateFile<'a> { + pub filename: &'a Path, + pub err: Error, } #[derive(SessionDiagnostic)] #[diag(metadata::failed_create_encoded_metadata)] pub struct FailedCreateEncodedMetadata { - pub err: String, + pub err: Error, } #[derive(SessionDiagnostic)] @@ -388,31 +393,31 @@ pub struct FailedCreateEncodedMetadata { pub struct NonAsciiName { #[primary_span] pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, } #[derive(SessionDiagnostic)] #[diag(metadata::extern_location_not_exist)] -pub struct ExternLocationNotExist { +pub struct ExternLocationNotExist<'a> { #[primary_span] pub span: Span, - pub crate_name: String, - pub location: String, + pub crate_name: Symbol, + pub location: &'a Path, } #[derive(SessionDiagnostic)] #[diag(metadata::extern_location_not_file)] -pub struct ExternLocationNotFile { +pub struct ExternLocationNotFile<'a> { #[primary_span] pub span: Span, - pub crate_name: String, - pub location: String, + pub crate_name: Symbol, + pub location: &'a Path, } -pub struct MultipleCandidates { +pub(crate) struct MultipleCandidates { pub span: Span, - pub flavor: String, - pub crate_name: String, + pub flavor: CrateFlavor, + pub crate_name: Symbol, pub candidates: Vec, } @@ -424,7 +429,7 @@ impl SessionDiagnostic<'_> for MultipleCandidates { let mut diag = sess.struct_err(rustc_errors::fluent::metadata::multiple_candidates); diag.set_arg("crate_name", self.crate_name); diag.set_arg("flavor", self.flavor); - diag.code(DiagnosticId::Error("E0465".into())); + diag.code(error_code!(E0465)); diag.set_span(self.span); for (i, candidate) in self.candidates.iter().enumerate() { diag.span_note(self.span, &format!("candidate #{}: {}", i + 1, candidate.display())); @@ -439,7 +444,7 @@ impl SessionDiagnostic<'_> for MultipleCandidates { pub struct MultipleMatchingCrates { #[primary_span] pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, pub candidates: String, } @@ -448,7 +453,7 @@ pub struct MultipleMatchingCrates { pub struct SymbolConflictsCurrent { #[primary_span] pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, } #[derive(SessionDiagnostic)] @@ -456,7 +461,7 @@ pub struct SymbolConflictsCurrent { pub struct SymbolConflictsOthers { #[primary_span] pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, } #[derive(SessionDiagnostic)] @@ -464,8 +469,8 @@ pub struct SymbolConflictsOthers { pub struct StableCrateIdCollision { #[primary_span] pub span: Span, - pub crate_name0: String, - pub crate_name1: String, + pub crate_name0: Symbol, + pub crate_name1: Symbol, } #[derive(SessionDiagnostic)] @@ -483,7 +488,7 @@ pub struct DlError { pub struct NewerCrateVersion { #[primary_span] pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, pub add_info: String, pub found_crates: String, } @@ -491,11 +496,11 @@ pub struct NewerCrateVersion { #[derive(SessionDiagnostic)] #[diag(metadata::no_crate_with_triple, code = "E0461")] #[note(metadata::found_crate_versions)] -pub struct NoCrateWithTriple { +pub struct NoCrateWithTriple<'a> { #[primary_span] pub span: Span, - pub crate_name: String, - pub locator_triple: String, + pub crate_name: Symbol, + pub locator_triple: &'a str, pub add_info: String, pub found_crates: String, } @@ -507,7 +512,7 @@ pub struct NoCrateWithTriple { pub struct FoundStaticlib { #[primary_span] pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, pub add_info: String, pub found_crates: String, } @@ -519,7 +524,7 @@ pub struct FoundStaticlib { pub struct IncompatibleRustc { #[primary_span] pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, pub add_info: String, pub found_crates: String, pub rustc_version: String, @@ -527,7 +532,7 @@ pub struct IncompatibleRustc { pub struct InvalidMetadataFiles { pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, pub add_info: String, pub crate_rejections: Vec, } @@ -540,7 +545,7 @@ impl SessionDiagnostic<'_> for InvalidMetadataFiles { let mut diag = sess.struct_err(rustc_errors::fluent::metadata::invalid_meta_files); diag.set_arg("crate_name", self.crate_name); diag.set_arg("add_info", self.add_info); - diag.code(DiagnosticId::Error("E0786".into())); + diag.code(error_code!(E0786)); diag.set_span(self.span); for crate_rejection in self.crate_rejections { diag.note(crate_rejection); @@ -551,8 +556,7 @@ impl SessionDiagnostic<'_> for InvalidMetadataFiles { pub struct CannotFindCrate { pub span: Span, - pub crate_name: String, - pub crate_name_symbol: Symbol, + pub crate_name: Symbol, pub add_info: String, pub missing_core: bool, pub current_crate: String, @@ -567,53 +571,41 @@ impl SessionDiagnostic<'_> for CannotFindCrate { sess: &'_ rustc_session::parse::ParseSess, ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { let mut diag = sess.struct_err(rustc_errors::fluent::metadata::cannot_find_crate); - diag.set_arg("crate_name", self.crate_name.clone()); + diag.set_arg("crate_name", self.crate_name); diag.set_arg("add_info", self.add_info); - diag.code(DiagnosticId::Error("E0463".into())); + diag.set_arg("locator_triple", self.locator_triple.triple()); + diag.code(error_code!(E0463)); diag.set_span(self.span); - // FIXME: Find a way to distill this logic down into the derived SessionDiagnostic form - if (self.crate_name_symbol == sym::std || self.crate_name_symbol == sym::core) + if (self.crate_name == sym::std || self.crate_name == sym::core) && self.locator_triple != TargetTriple::from_triple(config::host_triple()) { if self.missing_core { - diag.note(&format!("the `{}` target may not be installed", self.locator_triple)); + diag.note(rustc_errors::fluent::metadata::target_not_installed); } else { - diag.note(&format!( - "the `{}` target may not support the standard library", - self.locator_triple - )); + diag.note(rustc_errors::fluent::metadata::target_no_std_support); } // NOTE: this suggests using rustup, even though the user may not have it installed. // That's because they could choose to install it; or this may give them a hint which // target they need to install from their distro. if self.missing_core { - diag.help(&format!( - "consider downloading the target with `rustup target add {}`", - self.locator_triple - )); + diag.help(rustc_errors::fluent::metadata::consider_downloading_target); } // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway. // NOTE: this is a dummy span if `extern crate std` was injected by the compiler. // If it's not a dummy, that means someone added `extern crate std` explicitly and // `#![no_std]` won't help. if !self.missing_core && self.span.is_dummy() { - diag.note(&format!( - "`std` is required by `{}` because it does not declare `#![no_std]`", - self.current_crate - )); + diag.note(rustc_errors::fluent::metadata::std_required); } if self.is_nightly_build { - diag.help("consider building the standard library from source with `cargo build -Zbuild-std`"); + diag.help(rustc_errors::fluent::metadata::consider_building_std); } - } else if self.crate_name_symbol == self.profiler_runtime { - diag.note("the compiler may have been built without the profiler runtime"); - } else if self.crate_name.starts_with("rustc_") { - diag.help( - "maybe you need to install the missing components with: \ - `rustup component add rust-src rustc-dev llvm-tools-preview`", - ); + } else if self.crate_name == self.profiler_runtime { + diag.note(rustc_errors::fluent::metadata::compiler_missing_profiler); + } else if self.crate_name.as_str().starts_with("rustc_") { + diag.help(rustc_errors::fluent::metadata::install_missing_components); } - diag.span_label(self.span, "can't find crate"); + diag.span_label(self.span, rustc_errors::fluent::metadata::cant_find_crate); diag } } @@ -623,5 +615,22 @@ impl SessionDiagnostic<'_> for CannotFindCrate { pub struct NoDylibPlugin { #[primary_span] pub span: Span, - pub crate_name: String, + pub crate_name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::crate_location_unknown_type)] +pub struct CrateLocationUnknownType<'a> { + #[primary_span] + pub span: Span, + pub path: &'a Path, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::lib_filename_form)] +pub struct LibFilenameForm<'a> { + #[primary_span] + pub span: Span, + pub dll_prefix: &'a str, + pub dll_suffix: &'a str, } diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index 67c18766c5959..f360a586476e7 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -26,11 +26,8 @@ pub fn emit_metadata(sess: &Session, metadata: &[u8], tmpdir: &MaybeTempDir) -> let out_filename = tmpdir.as_ref().join(METADATA_FILENAME); let result = fs::write(&out_filename, metadata); - if let Err(e) = result { - sess.emit_fatal(FailedWriteError { - filename: out_filename.display().to_string(), - err: e.to_string(), - }); + if let Err(err) = result { + sess.emit_fatal(FailedWriteError { filename: out_filename, err }); } out_filename @@ -71,7 +68,7 @@ pub fn encode_and_write_metadata( let metadata_tmpdir = TempFileBuilder::new() .prefix("rmeta") .tempdir_in(out_filename.parent().unwrap_or_else(|| Path::new(""))) - .unwrap_or_else(|err| tcx.sess.emit_fatal(FailedCreateTempdir { err: err.to_string() })); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailedCreateTempdir { err })); let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps); let metadata_filename = metadata_tmpdir.as_ref().join(METADATA_FILENAME); @@ -79,11 +76,8 @@ pub fn encode_and_write_metadata( // This simplifies the creation of the output `out_filename` when requested. match metadata_kind { MetadataKind::None => { - std::fs::File::create(&metadata_filename).unwrap_or_else(|e| { - tcx.sess.emit_fatal(FailedCreateFile { - filename: metadata_filename.display().to_string(), - err: e.to_string(), - }); + std::fs::File::create(&metadata_filename).unwrap_or_else(|err| { + tcx.sess.emit_fatal(FailedCreateFile { filename: &metadata_filename, err }); }); } MetadataKind::Uncompressed | MetadataKind::Compressed => { @@ -98,11 +92,8 @@ pub fn encode_and_write_metadata( // this file always exists. let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata); let (metadata_filename, metadata_tmpdir) = if need_metadata_file { - if let Err(e) = non_durable_rename(&metadata_filename, &out_filename) { - tcx.sess.emit_fatal(FailedWriteError { - filename: out_filename.display().to_string(), - err: e.to_string(), - }); + if let Err(err) = non_durable_rename(&metadata_filename, &out_filename) { + tcx.sess.emit_fatal(FailedWriteError { filename: out_filename, err }); } if tcx.sess.opts.json_artifact_notifications { tcx.sess @@ -117,8 +108,8 @@ pub fn encode_and_write_metadata( // Load metadata back to memory: codegen may need to include it in object files. let metadata = - EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|e| { - tcx.sess.emit_fatal(FailedCreateEncodedMetadata { err: e.to_string() }); + EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|err| { + tcx.sess.emit_fatal(FailedCreateEncodedMetadata { err }); }); let need_metadata_module = metadata_kind == MetadataKind::Compressed; diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 83c8756078ec4..5edad819e7e3c 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -214,10 +214,11 @@ use crate::creader::Library; use crate::errors::{ - CannotFindCrate, DlError, ExternLocationNotExist, ExternLocationNotFile, FoundStaticlib, - IncompatibleRustc, InvalidMetadataFiles, MultipleCandidates, MultipleMatchingCrates, - NewerCrateVersion, NoCrateWithTriple, NoDylibPlugin, NonAsciiName, StableCrateIdCollision, - SymbolConflictsCurrent, SymbolConflictsOthers, + CannotFindCrate, CrateLocationUnknownType, DlError, ExternLocationNotExist, + ExternLocationNotFile, FoundStaticlib, IncompatibleRustc, InvalidMetadataFiles, + LibFilenameForm, MultipleCandidates, MultipleMatchingCrates, NewerCrateVersion, + NoCrateWithTriple, NoDylibPlugin, NonAsciiName, StableCrateIdCollision, SymbolConflictsCurrent, + SymbolConflictsOthers, }; use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; @@ -226,7 +227,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::FatalError; +use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg}; use rustc_session::config::{self, CrateType}; use rustc_session::cstore::{CrateSource, MetadataLoader}; use rustc_session::filesearch::FileSearch; @@ -238,6 +239,7 @@ use rustc_span::Span; use rustc_target::spec::{Target, TargetTriple}; use snap::read::FrameDecoder; +use std::borrow::Cow; use std::fmt::Write as _; use std::io::{Read, Result as IoResult, Write}; use std::path::{Path, PathBuf}; @@ -294,6 +296,16 @@ impl fmt::Display for CrateFlavor { } } +impl IntoDiagnosticArg for CrateFlavor { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + match self { + CrateFlavor::Rlib => DiagnosticArgValue::Str(Cow::Borrowed("rlib")), + CrateFlavor::Rmeta => DiagnosticArgValue::Str(Cow::Borrowed("rmeta")), + CrateFlavor::Dylib => DiagnosticArgValue::Str(Cow::Borrowed("dylib")), + } + } +} + impl<'a> CrateLocator<'a> { pub(crate) fn new( sess: &'a Session, @@ -946,29 +958,16 @@ impl CrateError { pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) { match self { CrateError::NonAsciiName(crate_name) => { - sess.emit_err(NonAsciiName { span, crate_name: crate_name.to_string() }); + sess.emit_err(NonAsciiName { span, crate_name }); } CrateError::ExternLocationNotExist(crate_name, loc) => { - sess.emit_err(ExternLocationNotExist { - span, - crate_name: crate_name.to_string(), - location: loc.display().to_string(), - }); + sess.emit_err(ExternLocationNotExist { span, crate_name, location: &loc }); } CrateError::ExternLocationNotFile(crate_name, loc) => { - sess.emit_err(ExternLocationNotFile { - span, - crate_name: crate_name.to_string(), - location: loc.display().to_string(), - }); + sess.emit_err(ExternLocationNotFile { span, crate_name, location: &loc }); } CrateError::MultipleCandidates(crate_name, flavor, candidates) => { - sess.emit_err(MultipleCandidates { - span, - flavor: flavor.to_string(), - crate_name: crate_name.to_string(), - candidates, - }); + sess.emit_err(MultipleCandidates { span, flavor: flavor, crate_name, candidates }); } CrateError::MultipleMatchingCrates(crate_name, libraries) => { let mut libraries: Vec<_> = libraries.into_values().collect(); @@ -998,27 +997,23 @@ impl CrateError { s }) .collect::(); - sess.emit_err(MultipleMatchingCrates { - span, - crate_name: crate_name.to_string(), - candidates, - }); + sess.emit_err(MultipleMatchingCrates { span, crate_name, candidates }); } CrateError::SymbolConflictsCurrent(root_name) => { - sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name.to_string() }); + sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name }); } CrateError::SymbolConflictsOthers(root_name) => { - sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name.to_string() }); + sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name }); } CrateError::StableCrateIdCollision(crate_name0, crate_name1) => { sess.emit_err(StableCrateIdCollision { span, - crate_name0: crate_name0.to_string(), - crate_name1: crate_name1.to_string(), + crate_name0: crate_name0, + crate_name1: crate_name1, }); } CrateError::DlOpen(s) | CrateError::DlSym(s) => { - sess.emit_err(DlError { span, err: s.to_string() }); + sess.emit_err(DlError { span, err: s }); } CrateError::LocatorCombined(locator) => { let crate_name = locator.crate_name; @@ -1026,24 +1021,17 @@ impl CrateError { None => String::new(), Some(r) => format!(" which `{}` depends on", r.name), }; - // FIXME: Is there any way to get these notes and helps onto every diagnostic in this - // huge branch arm without changing them all to manual implementations? - let mut global_loc_notes = Vec::new(); - let mut global_loc_helps = Vec::new(); + // FIXME: There are no tests for CrateLocationUnknownType or LibFilenameForm if !locator.crate_rejections.via_filename.is_empty() { let mismatches = locator.crate_rejections.via_filename.iter(); for CrateMismatch { path, .. } in mismatches { - global_loc_notes.push(format!( - "extern location for {} is of an unknown type: {}", - crate_name, - path.display(), - )); - global_loc_helps.push(format!( - "file name should be lib*.rlib or {}*.{}", - locator.dll_prefix, locator.dll_suffix - )); + sess.emit_err(CrateLocationUnknownType { span, path: &path }); + sess.emit_err(LibFilenameForm { + span, + dll_prefix: &locator.dll_prefix, + dll_suffix: &locator.dll_suffix, + }); } - panic!("!!!!! REVERT THIS COMMIT !!!!!"); } let mut found_crates = String::new(); if !locator.crate_rejections.via_hash.is_empty() { @@ -1066,7 +1054,7 @@ impl CrateError { } sess.emit_err(NewerCrateVersion { span, - crate_name: crate_name.to_string(), + crate_name: crate_name, add_info, found_crates, }); @@ -1082,8 +1070,8 @@ impl CrateError { } sess.emit_err(NoCrateWithTriple { span, - crate_name: crate_name.to_string(), - locator_triple: locator.triple.to_string(), + crate_name: crate_name, + locator_triple: locator.triple.triple(), add_info, found_crates, }); @@ -1096,12 +1084,7 @@ impl CrateError { path.display() )); } - sess.emit_err(FoundStaticlib { - span, - crate_name: crate_name.to_string(), - add_info, - found_crates, - }); + sess.emit_err(FoundStaticlib { span, crate_name, add_info, found_crates }); } else if !locator.crate_rejections.via_version.is_empty() { let mismatches = locator.crate_rejections.via_version.iter(); for CrateMismatch { path, got } in mismatches { @@ -1114,7 +1097,7 @@ impl CrateError { } sess.emit_err(IncompatibleRustc { span, - crate_name: crate_name.to_string(), + crate_name, add_info, found_crates, rustc_version: rustc_version(), @@ -1126,15 +1109,14 @@ impl CrateError { } sess.emit_err(InvalidMetadataFiles { span, - crate_name: crate_name.to_string(), + crate_name, add_info, crate_rejections, }); } else { sess.emit_err(CannotFindCrate { span, - crate_name: crate_name.to_string(), - crate_name_symbol: crate_name, + crate_name, add_info, missing_core, current_crate: sess @@ -1149,7 +1131,7 @@ impl CrateError { } } CrateError::NonDylibPlugin(crate_name) => { - sess.emit_err(NoDylibPlugin { span, crate_name: crate_name.to_string() }); + sess.emit_err(NoDylibPlugin { span, crate_name }); } } } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index dbaa2e9defa1a..19f64ef70c9c6 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -124,7 +124,7 @@ impl<'tcx> Collector<'tcx> { NativeLibKind::RawDylib } kind => { - sess.emit_err(UnknownLinkKind { span, kind: kind.to_string() }); + sess.emit_err(UnknownLinkKind { span, kind }); continue; } }; @@ -249,10 +249,7 @@ impl<'tcx> Collector<'tcx> { } let assign_modifier = |dst: &mut Option| { if dst.is_some() { - sess.emit_err(MultipleModifiers { - span, - modifier: modifier.to_string(), - }); + sess.emit_err(MultipleModifiers { span, modifier }); } else { *dst = Some(value); } @@ -287,10 +284,7 @@ impl<'tcx> Collector<'tcx> { } _ => { - sess.emit_err(UnknownLinkModifier { - span, - modifier: modifier.to_string(), - }); + sess.emit_err(UnknownLinkModifier { span, modifier }); } } } @@ -379,11 +373,11 @@ impl<'tcx> Collector<'tcx> { .filter_map(|lib| lib.name.as_ref()) .any(|n| n.as_str() == lib.name); if new_name.is_empty() { - self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: lib.name.clone() }); + self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: &lib.name }); } else if !any_duplicate { - self.tcx.sess.emit_err(RenamingNoLink { lib_name: lib.name.clone() }); + self.tcx.sess.emit_err(RenamingNoLink { lib_name: &lib.name }); } else if !renames.insert(&lib.name) { - self.tcx.sess.emit_err(MultipleRenamings { lib_name: lib.name.clone() }); + self.tcx.sess.emit_err(MultipleRenamings { lib_name: &lib.name }); } } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 2b1f9f17a3c85..8f55fb59f0bf8 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2270,7 +2270,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { let mut encoder = opaque::FileEncoder::new(path) - .unwrap_or_else(|err| tcx.sess.emit_fatal(FailCreateFileEncoder { err: err.to_string() })); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailCreateFileEncoder { err })); encoder.emit_raw_bytes(METADATA_HEADER); // Will be filled with the root position after encoding everything. @@ -2315,10 +2315,10 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { // Encode the root position. let header = METADATA_HEADER.len(); file.seek(std::io::SeekFrom::Start(header as u64)) - .unwrap_or_else(|err| tcx.sess.emit_fatal(FailSeekFile { err: err.to_string() })); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailSeekFile { err })); let pos = root.position.get(); file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8]) - .unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err: err.to_string() })); + .unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err })); // Return to the position where we are before writing the root position. file.seek(std::io::SeekFrom::Start(pos_before_seek)).unwrap(); From 30adfd6a17bd0d7c4d1302cc4a0f92962577de4a Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Sat, 27 Aug 2022 17:50:11 -0600 Subject: [PATCH 8/8] port 5 new diagnostics that appeared in master --- .../locales/en-US/metadata.ftl | 15 ++++++++ compiler/rustc_metadata/src/errors.rs | 36 +++++++++++++++++++ compiler/rustc_metadata/src/native_libs.rs | 36 +++++++++---------- 3 files changed, 67 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index dee01bcad4bbc..00067a1bf6ad7 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -255,3 +255,18 @@ metadata_crate_location_unknown_type = metadata_lib_filename_form = file name should be lib*.rlib or {dll_prefix}*.{dll_suffix} + +metadata_multiple_import_name_type = + multiple `import_name_type` arguments in a single `#[link]` attribute + +metadata_import_name_type_form = + import name type must be of the form `import_name_type = "string"` + +metadata_import_name_type_x86 = + import name type is only supported on x86 + +metadata_unknown_import_name_type = + unknown import name type `{$import_name_type}`, expected one of: decorated, noprefix, undecorated + +metadata_import_name_type_raw = + import name type can only be used with link kind `raw-dylib` diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 565c96917e2fc..18d0248333a51 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -634,3 +634,39 @@ pub struct LibFilenameForm<'a> { pub dll_prefix: &'a str, pub dll_suffix: &'a str, } + +#[derive(SessionDiagnostic)] +#[diag(metadata::multiple_import_name_type)] +pub struct MultipleImportNameType { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::import_name_type_form)] +pub struct ImportNameTypeForm { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::import_name_type_x86)] +pub struct ImportNameTypeX86 { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::unknown_import_name_type)] +pub struct UnknownImportNameType<'a> { + #[primary_span] + pub span: Span, + pub import_name_type: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(metadata::import_name_type_raw)] +pub struct ImportNameTypeRaw { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 19f64ef70c9c6..87b5e750f1cb1 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -13,13 +13,14 @@ use rustc_target::spec::abi::Abi; use crate::errors::{ AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, EmptyRenamingTarget, - FrameworkOnlyWindows, IncompatibleWasmLink, InvalidLinkModifier, LibFrameworkApple, - LinkCfgForm, LinkCfgSinglePredicate, LinkFrameworkApple, LinkKindForm, LinkModifiersForm, - LinkNameForm, LinkOrdinalRawDylib, LinkRequiresName, MultipleCfgs, MultipleKindsInLink, - MultipleLinkModifiers, MultipleModifiers, MultipleNamesInLink, MultipleRenamings, - MultipleWasmImport, NoLinkModOverride, RawDylibNoNul, RenamingNoLink, UnexpectedLinkArg, - UnknownLinkKind, UnknownLinkModifier, UnsupportedAbi, UnsupportedAbiI686, WasmImportForm, - WholeArchiveNeedsStatic, + FrameworkOnlyWindows, ImportNameTypeForm, ImportNameTypeRaw, ImportNameTypeX86, + IncompatibleWasmLink, InvalidLinkModifier, LibFrameworkApple, LinkCfgForm, + LinkCfgSinglePredicate, LinkFrameworkApple, LinkKindForm, LinkModifiersForm, LinkNameForm, + LinkOrdinalRawDylib, LinkRequiresName, MultipleCfgs, MultipleImportNameType, + MultipleKindsInLink, MultipleLinkModifiers, MultipleModifiers, MultipleNamesInLink, + MultipleRenamings, MultipleWasmImport, NoLinkModOverride, RawDylibNoNul, RenamingNoLink, + UnexpectedLinkArg, UnknownImportNameType, UnknownLinkKind, UnknownLinkModifier, UnsupportedAbi, + UnsupportedAbiI686, WasmImportForm, WholeArchiveNeedsStatic, }; pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec { @@ -178,18 +179,15 @@ impl<'tcx> Collector<'tcx> { } sym::import_name_type => { if import_name_type.is_some() { - let msg = "multiple `import_name_type` arguments in a single `#[link]` attribute"; - sess.span_err(item.span(), msg); + sess.emit_err(MultipleImportNameType { span: item.span() }); continue; } let Some(link_import_name_type) = item.value_str() else { - let msg = "import name type must be of the form `import_name_type = \"string\"`"; - sess.span_err(item.span(), msg); + sess.emit_err(ImportNameTypeForm { span: item.span() }); continue; }; if self.tcx.sess.target.arch != "x86" { - let msg = "import name type is only supported on x86"; - sess.span_err(item.span(), msg); + sess.emit_err(ImportNameTypeX86 { span: item.span() }); continue; } @@ -198,11 +196,10 @@ impl<'tcx> Collector<'tcx> { "noprefix" => PeImportNameType::NoPrefix, "undecorated" => PeImportNameType::Undecorated, import_name_type => { - let msg = format!( - "unknown import name type `{import_name_type}`, expected one of: \ - decorated, noprefix, undecorated" - ); - sess.span_err(item.span(), msg); + sess.emit_err(UnknownImportNameType { + span: item.span(), + import_name_type, + }); continue; } }; @@ -301,8 +298,7 @@ impl<'tcx> Collector<'tcx> { // Do this outside of the loop so that `import_name_type` can be specified before `kind`. if let Some((_, span)) = import_name_type { if kind != Some(NativeLibKind::RawDylib) { - let msg = "import name type can only be used with link kind `raw-dylib`"; - sess.span_err(span, msg); + sess.emit_err(ImportNameTypeRaw { span }); } }