From eb5690ab85ce600e2e2611f711dc8ac3f6f9536b Mon Sep 17 00:00:00 2001 From: Xiretza Date: Mon, 15 Apr 2024 18:07:22 +0000 Subject: [PATCH] Make early lints translatable --- .../rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_expand/src/base.rs | 16 +- compiler/rustc_lint/messages.ftl | 183 +++- compiler/rustc_lint/src/context.rs | 21 +- .../rustc_lint/src/context/diagnostics.rs | 791 ++++++++---------- .../src/context/diagnostics/check_cfg.rs | 19 +- .../src/context/diagnostics/tests.rs | 40 - compiler/rustc_lint/src/early.rs | 4 +- compiler/rustc_lint/src/lints.rs | 584 ++++++++++++- compiler/rustc_lint_defs/src/lib.rs | 19 +- compiler/rustc_metadata/src/creader.rs | 2 +- compiler/rustc_middle/src/middle/stability.rs | 21 +- compiler/rustc_resolve/src/check_unused.rs | 34 +- compiler/rustc_resolve/src/macros.rs | 5 +- ...sue-43106-gating-of-builtin-attrs-error.rs | 2 +- ...43106-gating-of-builtin-attrs-error.stderr | 2 +- .../imports/no-pub-reexports-but-used.stderr | 2 +- tests/ui/imports/reexports.stderr | 2 +- tests/ui/lint/anonymous-reexport.stderr | 2 +- .../ui/lint/unused/import_remove_line.stderr | 2 +- tests/ui/lint/unused/lint-unused-imports.rs | 2 +- .../ui/lint/unused/lint-unused-imports.stderr | 2 +- tests/ui/malformed/malformed-regressions.rs | 6 +- .../ui/malformed/malformed-regressions.stderr | 6 +- ...sue-46209-private-enum-variant-reexport.rs | 2 +- ...46209-private-enum-variant-reexport.stderr | 8 +- .../privacy/private-variant-reexport.stderr | 2 +- tests/ui/span/multispan-import-lint.stderr | 2 +- tests/ui/suggestions/unused-imports.stderr | 4 +- .../use/use-nested-groups-unused-imports.rs | 2 +- .../use-nested-groups-unused-imports.stderr | 2 +- 31 files changed, 1181 insertions(+), 610 deletions(-) delete mode 100644 compiler/rustc_lint/src/context/diagnostics/tests.rs diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 3c34001cf0eac..4256eeb52936c 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1509,7 +1509,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { DEPRECATED_WHERE_CLAUSE_LOCATION, item.id, err.span, - BuiltinLintDiag::DeprecatedWhereclauseLocation(sugg), + BuiltinLintDiag::DeprecatedWhereclauseLocation(err.span, sugg), ); } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index c7ca515afc464..38f5e8d62b4a0 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1367,14 +1367,14 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) -> bool { // FIXME: make this translatable #[allow(rustc::untranslatable_diagnostic)] sess.psess.buffer_lint_with_diagnostic( - PROC_MACRO_BACK_COMPAT, - item.ident.span, - ast::CRATE_NODE_ID, - BuiltinLintDiag::ProcMacroBackCompat( - "older versions of the `rental` crate will stop compiling in future versions of Rust; \ - please update to `rental` v0.5.6, or switch to one of the `rental` alternatives".to_string() - ) - ); + PROC_MACRO_BACK_COMPAT, + item.ident.span, + ast::CRATE_NODE_ID, + BuiltinLintDiag::ProcMacroBackCompat { + crate_name: "rental".to_string(), + fixed_version: "0.5.6".to_string(), + }, + ); return true; } } diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 29835e7717e6e..918fc85151538 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -1,3 +1,10 @@ +lint_abs_path_with_module = absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + .suggestion = use `crate` + +lint_ambiguous_glob_reexport = ambiguous glob re-exports + .label_first_reexport = the name `{$name}` in the {$namespace} namespace is first re-exported here + .label_duplicate_reexport = but the name `{$name}` in the {$namespace} namespace is also re-exported here + lint_ambiguous_wide_pointer_comparisons = ambiguous wide pointer comparison, the comparison includes metadata which may not be expected .addr_metadata_suggestion = use explicit `std::ptr::eq` method to compare metadata and addresses .addr_suggestion = use `std::ptr::addr_eq` or untyped pointers to only compare their addresses @@ -9,6 +16,12 @@ lint_array_into_iter = .use_explicit_into_iter_suggestion = or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value +lint_associated_const_elided_lifetime = {$elided -> + [true] `&` without an explicit lifetime name cannot be used here + *[false] `'_` cannot be used here + } + .suggestion = use the `'static` lifetime + lint_async_fn_in_trait = use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified .note = you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future` .suggestion = you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send`, but these cannot be relaxed without a breaking API change @@ -26,10 +39,19 @@ lint_atomic_ordering_load = atomic loads cannot have `Release` or `AcqRel` order lint_atomic_ordering_store = atomic stores cannot have `Acquire` or `AcqRel` ordering .help = consider using ordering modes `Release`, `SeqCst` or `Relaxed` +lint_avoid_att_syntax = + avoid using `.att_syntax`, prefer using `options(att_syntax)` instead + +lint_avoid_intel_syntax = + avoid using `.intel_syntax`, Intel syntax is the default + lint_bad_attribute_argument = bad attribute argument lint_bad_opt_access = {$msg} +lint_break_with_label_and_loop = this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression + .suggestion = wrap this expression in parentheses + lint_builtin_allow_internal_unsafe = `allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site @@ -163,6 +185,9 @@ lint_builtin_unused_doc_comment = unused doc comment lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}` .suggestion = use `loop` +lint_byte_slice_in_packed_struct_with_derive = {$ty} slice in a packed struct that derives a built-in trait + .help = consider implementing the trait by hand, or remove the `packed` attribute + lint_cfg_attr_no_attributes = `#[cfg_attr]` does not expand to any attributes @@ -186,6 +211,8 @@ lint_cstring_ptr = getting the inner pointer of a temporary `CString` .note = pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned .help = for more information, see https://doc.rust-lang.org/reference/destructors.html +lint_custom_inner_attribute_unstable = custom inner attributes are unstable + lint_default_hash_types = prefer `{$preferred}` over `{$used}`, it has better performance .note = a `use rustc_data_structures::fx::{$preferred}` may be necessary @@ -196,8 +223,10 @@ lint_deprecated_lint_name = .suggestion = change it to .help = change it to {$replace} -lint_deprecated_where_clause_location = - where clause not allowed here +lint_deprecated_where_clause_location = where clause not allowed here + .note = see issue #89122 for more information + .suggestion_move_to_end = move it to the end of the type declaration + .suggestion_remove_where = remove this `where` lint_diag_out_of_impl = diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls @@ -216,6 +245,11 @@ lint_dropping_references = calls to `std::mem::drop` with a reference instead of .label = argument has type `{$arg_ty}` .note = use `let _ = ...` to ignore the expression or result +lint_duplicate_macro_attribute = + duplicated attribute + +lint_duplicate_matcher_binding = duplicate matcher binding + lint_enum_intrinsics_mem_discriminant = the return value of `mem::discriminant` is unspecified when called with a non-enum type .note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum. @@ -228,7 +262,12 @@ lint_expectation = this lint expectation is unfulfilled .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message .rationale = {$rationale} +lint_extern_crate_not_idiomatic = `extern crate` is not idiomatic in the new edition + .suggestion = convert it to a `use` + lint_extern_without_abi = extern declarations without an explicit ABI are deprecated + .label = ABI should be specified here + .help = the default ABI is {$default_abi} lint_for_loops_over_fallibles = for loop over {$article} `{$ty}`. This is more readably written as an `if let` statement @@ -244,6 +283,12 @@ lint_forgetting_references = calls to `std::mem::forget` with a reference instea .label = argument has type `{$arg_ty}` .note = use `let _ = ...` to ignore the expression or result +lint_hidden_glob_reexport = private item shadows public glob re-export + .note_glob_reexport = the name `{$name}` in the {$namespace} namespace is supposed to be publicly re-exported here + .note_private_item = but the private item here shadows it + +lint_hidden_lifetime_parameters = hidden lifetime parameters in types are deprecated + lint_hidden_unicode_codepoints = unicode codepoint changing visible direction of text present in {$label} .label = this {$label} contains {$count -> [one] an invisible @@ -285,6 +330,11 @@ lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len -> lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level +lint_ill_formed_attribute_input = {$num_suggestions -> + [1] attribute must be of the form {$suggestions} + *[other] valid forms for the attribute are {$suggestions} + } + lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe .label = not FFI-safe .note = the type is defined here @@ -344,6 +394,14 @@ lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[re lint_improper_ctypes_union_layout_reason = this union has unspecified layout lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive +lint_incomplete_include = + include macro expected single expression in source + +lint_inner_macro_attribute_unstable = inner macro attributes are unstable + +lint_invalid_crate_type_value = invalid `crate_type` value + .suggestion = did you mean + # FIXME: we should ordinalize $valid_up_to when we add support for doing so lint_invalid_from_utf8_checked = calls to `{$method}` with a invalid literal always return an error .label = the literal was valid UTF-8 up to the {$valid_up_to} bytes @@ -372,9 +430,28 @@ lint_invalid_reference_casting_note_book = for more information, visit + [1] first + [one] {$n}st + [two] {$n}nd + [few] {$n}rd + *[other] {$n}th + } rule of macro `{$name}` is never used + +lint_macro_use_deprecated = + deprecated `#[macro_use]` attribute used to import macros should be replaced at use sites with a `use` item to import the macro instead + lint_malformed_attribute = malformed lint attribute input lint_map_unit_fn = `Iterator::map` call that discard the iterator's values @@ -384,6 +461,12 @@ lint_map_unit_fn = `Iterator::map` call that discard the iterator's values .map_label = after this call to map, the resulting iterator is `impl Iterator`, which means the only information carried by the iterator is the number of items .suggestion = you might have meant to use `Iterator::for_each` +lint_metavariable_still_repeating = variable '{$name}' is still repeating at this depth + +lint_metavariable_wrong_operator = meta-variable repeats with different Kleene operator + +lint_missing_fragment_specifier = missing fragment specifier + lint_mixed_script_confusables = the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables .includes_note = the usage includes {$includes} @@ -391,6 +474,11 @@ lint_mixed_script_confusables = lint_multiple_supertrait_upcastable = `{$ident}` is object-safe and has multiple supertraits +lint_named_argument_used_positionally = named argument `{$named_arg_name}` is not used by name + .label_named_arg = this named argument is referred to by position in formatting string + .label_position_arg = this formatting argument uses named argument `{$named_arg_name}` by position + .suggestion = use the named argument by name to avoid ambiguity + lint_node_source = `forbid` level set here .note = {$reason} @@ -502,6 +590,9 @@ lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its ass lint_opaque_hidden_inferred_bound_sugg = add this bound +lint_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro + .suggestion = use pat_param to preserve semantics + lint_overflowing_bin_hex = literal out of range for `{$ty}` .negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` .negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}` @@ -537,6 +628,15 @@ lint_pattern_in_bodiless = patterns aren't allowed in functions without bodies lint_pattern_in_foreign = patterns aren't allowed in foreign function declarations .label = pattern not allowed in foreign function +lint_private_extern_crate_reexport = + extern crate `{$ident}` is private, and cannot be re-exported (error E0365), consider declaring with `pub` + +lint_proc_macro_back_compat = using an old version of `{$crate_name}` + .note = older versions of the `{$crate_name}` crate will stop compiling in future versions of Rust; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives + +lint_proc_macro_derive_resolution_fallback = cannot find {$ns} `{$ident}` in this scope + .label = names from parent modules are not accessible without an explicit import + lint_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value .label = expression has type `{$orig_ty}` @@ -558,6 +658,16 @@ lint_reason_must_be_string_literal = reason must be a string literal lint_reason_must_come_last = reason in lint attribute must come last +lint_redundant_import = the item `{$ident}` is imported redundantly + .label_imported_here = the item `{ident}` is already imported here + .label_defined_here = the item `{ident}` is already defined here + .label_imported_prelude = the item `{ident}` is already imported by the extern prelude + .label_defined_prelude = the item `{ident}` is already defined by the extern prelude + +lint_redundant_import_visibility = glob import doesn't reexport anything with visibility `{$import_vis}` because no imported item is public enough + .note = the most public imported item is `{$max_vis}` + .help = reduce the glob import's visibility or increase visibility of imported items + lint_redundant_semicolons = unnecessary trailing {$multiple -> [true] semicolons @@ -568,6 +678,8 @@ lint_redundant_semicolons = *[false] this semicolon } +lint_remove_mut_from_pattern = remove `mut` from the parameter + lint_removed_lint = lint `{$name}` has been removed: {$reason} lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}` @@ -576,6 +688,15 @@ lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}` lint_requested_level = requested on the command line with `{$level} {$lint_name}` +lint_reserved_prefix = prefix `{$prefix}` is unknown + .label = unknown prefix + .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021 + +lint_single_use_lifetime = lifetime parameter `{$ident}` only used once + .label_param = this lifetime... + .label_use = ...is used only here + .suggestion = elide the single-use lifetime + lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()` lint_supertrait_as_deref_target = this `Deref` implementation is covered by an implicit supertrait coercion @@ -589,6 +710,10 @@ lint_suspicious_double_ref_clone = lint_suspicious_double_ref_deref = using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type +lint_trailing_semi_macro = trailing semicolon in macro used in expression position + .note1 = macro invocations at the end of a block are treated as expressions + .note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}` + lint_ty_qualified = usage of qualified `ty::{$ty}` .suggestion = try importing it and using it unqualified @@ -602,6 +727,7 @@ lint_undropped_manually_drops = calls to `std::mem::drop` with `std::mem::Manual .label = argument has type `{$arg_ty}` .suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value +lint_unexpected_cfg_name = unexpected `cfg` condition name: `{$name}` lint_unexpected_cfg_name_add_cargo_feature = consider using a Cargo feature instead or adding `{$build_rs_println}` to the top of the `build.rs` lint_unexpected_cfg_name_add_cmdline_arg = to expect this configuration use `{$cmdline_arg}` lint_unexpected_cfg_name_define_features = consider defining some features in `Cargo.toml` @@ -618,6 +744,10 @@ lint_unexpected_cfg_name_similar_name_no_value = there is a config with a simila lint_unexpected_cfg_name_similar_name_value = there is a config with a similar name and value lint_unexpected_cfg_name_with_similar_value = found config with similar value +lint_unexpected_cfg_value = unexpected `cfg` condition value: {$has_value -> + [true] `{$value}` + *[false] (none) + } lint_unexpected_cfg_value_add_cmdline_arg = to expect this configuration use `{$cmdline_arg}` lint_unexpected_cfg_value_add_feature = consider adding `{$value}` as a feature in `Cargo.toml` lint_unexpected_cfg_value_define_features = consider defining some features in `Cargo.toml` @@ -641,9 +771,21 @@ lint_unexpected_cfg_value_use_features_or_build_rs = consider using a Cargo feat lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op .label = this function will not propagate the caller location +lint_unicode_text_flow = unicode codepoint changing visible direction of text present in comment + .label = {$num_codepoints -> + [1] this comment contains an invisible unicode text flow control codepoint + *[other] this comment contains invisible unicode text flow control codepoints + } + .note = these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + .suggestion = if their presence wasn't intentional, you can remove them + .label_comment_char = {$c_debug} + + lint_unit_bindings = binding has unit type `()` .label = this pattern is inferred to be the unit type `()` +lint_unknown_diagnostic_attribute = unknown diagnostic attribute + lint_unknown_gated_lint = unknown lint: `{$name}` .note = the `{$name}` lint is unstable @@ -659,11 +801,16 @@ lint_unknown_lint = *[false] did you mean: `{$replace}` } +lint_unknown_macro_variable = unknown macro variable `{$name}` + lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}` .help = add `#![register_tool({$tool_name})]` to the crate root lint_unnameable_test_items = cannot test inner items +lint_unnecessary_qualification = unnecessary qualification + .suggestion = remove the unnecessary path segments + lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´ lint_untranslatable_diag = diagnostics should be created using translatable messages @@ -671,6 +818,9 @@ lint_untranslatable_diag = diagnostics should be created using translatable mess lint_unused_allocation = unnecessary allocation, use `&` instead lint_unused_allocation_mut = unnecessary allocation, use `&mut` instead +lint_unused_builtin_attribute = unused attribute `{$attr_name}` + .note = the built-in attribute `{$attr_name}` will be ignored, since it's applied to the macro invocation `{$macro_name}` + lint_unused_closure = unused {$pre}{$count -> [one] closure @@ -687,14 +837,43 @@ lint_unused_coroutine = }{$post} that must be used .note = coroutines are lazy and do nothing unless resumed +lint_unused_crate_dependency = external crate `{$extern_crate}` unused in `{$local_crate}`: remove the dependency or add `use {$extern_crate} as _;` + lint_unused_def = unused {$pre}`{$def}`{$post} that must be used .suggestion = use `let _ = ...` to ignore the resulting value lint_unused_delim = unnecessary {$delim} around {$item} .suggestion = remove these {$delim} +lint_unused_doc_comment = unused doc comment + .label = rustdoc does not generate documentation for macro invocations + .help = to document an item produced by a macro, the macro must produce the documentation as part of its expansion + +lint_unused_extern_crate = unused extern crate + .suggestion = remove it + lint_unused_import_braces = braces around {$node} is unnecessary +lint_unused_imports = {$num_snippets -> + [one] unused import: {$span_snippets} + *[other] unused imports: {$span_snippets} + } + .suggestion_remove_whole_use = remove the whole `use` item + .suggestion_remove_imports = {$num_to_remove -> + [one] remove the unused import + *[other] remove the unused imports + } + .help = if this is a test module, consider adding a `#[cfg(test)]` to the containing module + +lint_unused_label = unused label + +lint_unused_lifetime = lifetime parameter `{$ident}` never used + .suggestion = elide the unused lifetime + +lint_unused_macro_definition = unused macro definition: `{$name}` + +lint_unused_macro_use = unused `#[macro_use]` import + lint_unused_op = unused {$op} that must be used .label = the {$op} produces a value .suggestion = use `let _ = ...` to ignore the resulting value diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index a796e81a1f7ee..18e82448f3f8d 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -527,29 +527,24 @@ pub struct EarlyContext<'a> { pub buffered: LintBuffer, } -pub trait LintContext { - fn sess(&self) -> &Session; - +impl<'c> EarlyContext<'c> { /// Emit a lint at the appropriate level, with an optional associated span and an existing /// diagnostic. /// /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature #[rustc_lint_diagnostics] - fn span_lint_with_diagnostics( + pub fn span_lint_with_diagnostics( &self, lint: &'static Lint, - span: Option>, - decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), + span: MultiSpan, diagnostic: BuiltinLintDiag, ) { - // We first generate a blank diagnostic. - self.opt_span_lint(lint, span, diagnostics::builtin_message(&diagnostic), |db| { - // Now, set up surrounding context. - diagnostics::builtin(self.sess(), diagnostic, db); - // Rewrap `db`, and pass control to the user. - decorate(db) - }); + diagnostics::emit_buffered_lint(self, lint, span, diagnostic) } +} + +pub trait LintContext { + fn sess(&self) -> &Session; // FIXME: These methods should not take an Into -- instead, callers should need to // set the span in their `decorate` function (preferably using set_span). diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 1f677e94c9d27..c26f824e3dbcd 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -1,131 +1,150 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +use std::borrow::Cow; + use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; -use rustc_errors::{ - elided_lifetime_in_path_suggestion, pluralize, Diag, DiagMessage, LintDiagnostic, -}; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::Applicability; +use rustc_errors::{elided_lifetime_in_path_suggestion, DiagArgValue, MultiSpan}; use rustc_middle::middle::stability; -use rustc_session::lint::BuiltinLintDiag; -use rustc_session::Session; +use rustc_session::lint::{BuiltinLintDiag, Lint}; use rustc_span::BytePos; -use std::fmt::Write; +use crate::{lints, LintContext}; mod check_cfg; -#[cfg(test)] -mod tests; - -pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) { +pub(super) fn emit_buffered_lint( + ctx: &C, + lint: &'static Lint, + span: MultiSpan, + diagnostic: BuiltinLintDiag, +) { match diagnostic { - BuiltinLintDiag::UnicodeTextFlow(span, content) => { + BuiltinLintDiag::UnicodeTextFlow(comment_span, content) => { let spans: Vec<_> = content .char_indices() .filter_map(|(i, c)| { TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| { - let lo = span.lo() + BytePos(2 + i as u32); - (c, span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32))) + let lo = comment_span.lo() + BytePos(2 + i as u32); + (c, comment_span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32))) }) }) .collect(); - let (an, s) = match spans.len() { - 1 => ("an ", ""), - _ => ("", "s"), - }; - diag.span_label( + let characters = spans + .iter() + .map(|&(c, span)| lints::UnicodeCharNoteSub { span, c_debug: format!("{c:?}") }) + .collect(); + let suggestions = (!spans.is_empty()).then_some(lints::UnicodeTextFlowSuggestion { + spans: spans.iter().map(|(_c, span)| *span).collect(), + }); + ctx.emit_span_lint( + lint, span, - format!( - "this comment contains {an}invisible unicode text flow control codepoint{s}", - ), - ); - for (c, span) in &spans { - diag.span_label(*span, format!("{c:?}")); - } - diag.note( - "these kind of unicode codepoints change the way text flows on \ - applications that support them, but can cause confusion because they \ - change the order of characters on the screen", - ); - if !spans.is_empty() { - diag.multipart_suggestion_with_style( - "if their presence wasn't intentional, you can remove them", - spans.into_iter().map(|(_, span)| (span, "".to_string())).collect(), - Applicability::MachineApplicable, - SuggestionStyle::HideCodeAlways, - ); - } - } - BuiltinLintDiag::AbsPathWithModule(span) => { - let (sugg, app) = match sess.source_map().span_to_snippet(span) { - Ok(ref s) => { - // FIXME(Manishearth) ideally the emitting code - // can tell us whether or not this is global - let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" }; + lints::UnicodeTextFlow { + comment_span, + characters, + suggestions, + num_codepoints: spans.len(), + }, + ) + } + BuiltinLintDiag::AbsPathWithModule(mod_span) => { + let (replacement, applicability) = + match ctx.sess().source_map().span_to_snippet(mod_span) { + Ok(ref s) => { + // FIXME(Manishearth) ideally the emitting code + // can tell us whether or not this is global + let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" }; - (format!("crate{opt_colon}{s}"), Applicability::MachineApplicable) - } - Err(_) => ("crate::".to_string(), Applicability::HasPlaceholders), - }; - diag.span_suggestion(span, "use `crate`", sugg, app); - } - BuiltinLintDiag::ProcMacroDeriveResolutionFallback { span, .. } => { - diag.span_label( + (format!("crate{opt_colon}{s}"), Applicability::MachineApplicable) + } + Err(_) => ("crate::".to_string(), Applicability::HasPlaceholders), + }; + ctx.emit_span_lint( + lint, span, - "names from parent modules are not accessible without an explicit import", + lints::AbsPathWithModule { + sugg: lints::AbsPathWithModuleSugg { + span: mod_span, + applicability, + replacement, + }, + }, ); } - BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => { - diag.span_note(span_def, "the macro is defined here"); - } + BuiltinLintDiag::ProcMacroDeriveResolutionFallback { span: macro_span, ns, ident } => ctx + .emit_span_lint( + lint, + span, + lints::ProcMacroDeriveResolutionFallback { span: macro_span, ns, ident }, + ), + BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => ctx + .emit_span_lint( + lint, + span, + lints::MacroExpandedMacroExportsAccessedByAbsolutePaths { definition: span_def }, + ), BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => { - diag.subdiagnostic( - sess.dcx(), - elided_lifetime_in_path_suggestion( - sess.source_map(), - n, - path_span, - incl_angl_brckt, - insertion_span, - ), + ctx.emit_span_lint( + lint, + span, + lints::ElidedLifetimesInPaths { + subdiag: elided_lifetime_in_path_suggestion( + ctx.sess().source_map(), + n, + path_span, + incl_angl_brckt, + insertion_span, + ), + }, ); } BuiltinLintDiag::UnknownCrateTypes { span, candidate } => { - if let Some(candidate) = candidate { - diag.span_suggestion( - span, - "did you mean", - format!(r#""{candidate}""#), - Applicability::MaybeIncorrect, - ); - } - } - BuiltinLintDiag::UnusedImports { fix_msg, fixes, test_module_span, .. } => { - if !fixes.is_empty() { - diag.tool_only_multipart_suggestion( - fix_msg, - fixes, - Applicability::MachineApplicable, - ); - } + let sugg = candidate.map(|candidate| lints::UnknownCrateTypesSub { span, candidate }); + ctx.emit_span_lint(lint, span, lints::UnknownCrateTypes { sugg }); + } + BuiltinLintDiag::UnusedImports { + remove_whole_use, + num_to_remove, + remove_spans, + test_module_span, + span_snippets, + } => { + let sugg = if remove_whole_use { + lints::UnusedImportsSugg::RemoveWholeUse { span: remove_spans[0] } + } else { + lints::UnusedImportsSugg::RemoveImports { remove_spans, num_to_remove } + }; + let test_module_span = + test_module_span.map(|span| ctx.sess().source_map().guess_head_span(span)); - if let Some(span) = test_module_span { - diag.span_help( - sess.source_map().guess_head_span(span), - "if this is a test module, consider adding a `#[cfg(test)]` to the containing module", - ); - } + ctx.emit_span_lint( + lint, + span, + lints::UnusedImports { + sugg, + test_module_span, + num_snippets: span_snippets.len(), + span_snippets: DiagArgValue::StrListSepByAnd( + span_snippets.into_iter().map(Cow::Owned).collect(), + ), + }, + ); } BuiltinLintDiag::RedundantImport(spans, ident) => { - for (span, is_imported) in spans { - let introduced = if is_imported { "imported" } else { "defined" }; - let span_msg = if span.is_dummy() { "by the extern prelude" } else { "here" }; - diag.span_label( - span, - format!("the item `{ident}` is already {introduced} {span_msg}"), - ); - } + let subs = spans + .into_iter() + .map(|(span, is_imported)| { + (match (span.is_dummy(), is_imported) { + (false, true) => lints::RedundantImportSub::ImportedHere, + (false, false) => lints::RedundantImportSub::DefinedHere, + (true, true) => lints::RedundantImportSub::ImportedPrelude, + (true, false) => lints::RedundantImportSub::DefinedPrelude, + })(span) + }) + .collect(); + ctx.emit_span_lint(lint, span, lints::RedundantImport { subs, ident }); } BuiltinLintDiag::DeprecatedMacro { suggestion, @@ -139,108 +158,116 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di kind: "macro".to_owned(), suggestion, }); - let deprecated = - stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind }; - deprecated.decorate_lint(diag); + ctx.emit_span_lint( + lint, + span, + stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind }, + ); } - BuiltinLintDiag::UnusedDocComment(span) => { - diag.span_label(span, "rustdoc does not generate documentation for macro invocations"); - diag.help("to document an item produced by a macro, \ - the macro must produce the documentation as part of its expansion"); + BuiltinLintDiag::UnusedDocComment(attr_span) => { + ctx.emit_span_lint(lint, span, lints::UnusedDocComment { span: attr_span }); } - BuiltinLintDiag::PatternsInFnsWithoutBody { span, ident, .. } => { - diag.span_suggestion( + BuiltinLintDiag::PatternsInFnsWithoutBody { span: remove_span, ident, is_foreign } => { + let sub = lints::PatternsInFnsWithoutBodySub { ident, span: remove_span }; + + ctx.emit_span_lint( + lint, span, - "remove `mut` from the parameter", - ident, - Applicability::MachineApplicable, + if is_foreign { + lints::PatternsInFnsWithoutBody::Foreign { sub } + } else { + lints::PatternsInFnsWithoutBody::Bodiless { sub } + }, ); } - BuiltinLintDiag::MissingAbi(span, default_abi) => { - diag.span_label(span, "ABI should be specified here"); - diag.help(format!("the default ABI is {}", default_abi.name())); + BuiltinLintDiag::MissingAbi(label_span, default_abi) => { + ctx.emit_span_lint( + lint, + span, + lints::MissingAbi { span: label_span, default_abi: default_abi.name() }, + ); } - BuiltinLintDiag::LegacyDeriveHelpers(span) => { - diag.span_label(span, "the attribute is introduced here"); + BuiltinLintDiag::LegacyDeriveHelpers(label_span) => { + ctx.emit_span_lint(lint, span, lints::LegacyDeriveHelpers { span: label_span }); } - BuiltinLintDiag::ProcMacroBackCompat(note) => { - diag.note(note); + BuiltinLintDiag::ProcMacroBackCompat { crate_name, fixed_version } => { + ctx.emit_span_lint( + lint, + span, + lints::ProcMacroBackCompat { crate_name, fixed_version }, + ); } - BuiltinLintDiag::OrPatternsBackCompat(span, suggestion) => { - diag.span_suggestion( + BuiltinLintDiag::OrPatternsBackCompat(suggestion_span, suggestion) => { + ctx.emit_span_lint( + lint, span, - "use pat_param to preserve semantics", - suggestion, - Applicability::MachineApplicable, + lints::OrPatternsBackCompat { span: suggestion_span, suggestion }, ); } - BuiltinLintDiag::ReservedPrefix(span, _) => { - diag.span_label(span, "unknown prefix"); - diag.span_suggestion_verbose( - span.shrink_to_hi(), - "insert whitespace here to avoid this being parsed as a prefix in Rust 2021", - " ", - Applicability::MachineApplicable, + BuiltinLintDiag::ReservedPrefix(label_span, prefix) => { + ctx.emit_span_lint( + lint, + span, + lints::ReservedPrefix { + label: label_span, + suggestion: label_span.shrink_to_hi(), + prefix, + }, ); } BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => { - diag.span_note( - invoc_span, - format!("the built-in attribute `{attr_name}` will be ignored, since it's applied to the macro invocation `{macro_name}`") - ); + ctx.emit_span_lint( + lint, + span, + lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name }, + ); } BuiltinLintDiag::TrailingMacro(is_trailing, name) => { - if is_trailing { - diag.note("macro invocations at the end of a block are treated as expressions"); - diag.note(format!("to ignore the value produced by the macro, add a semicolon after the invocation of `{name}`")); - } - } - BuiltinLintDiag::BreakWithLabelAndLoop(span) => { - diag.multipart_suggestion( - "wrap this expression in parentheses", - vec![ - (span.shrink_to_lo(), "(".to_string()), - (span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MachineApplicable, + ctx.emit_span_lint(lint, span, lints::TrailingMacro { is_trailing, name }); + } + BuiltinLintDiag::BreakWithLabelAndLoop(sugg_span) => { + ctx.emit_span_lint( + lint, + span, + lints::BreakWithLabelAndLoop { + sub: lints::BreakWithLabelAndLoopSub { + left: sugg_span.shrink_to_lo(), + right: sugg_span.shrink_to_hi(), + }, + }, ); } BuiltinLintDiag::UnexpectedCfgName(name, value) => { - check_cfg::unexpected_cfg_name(sess, diag, name, value) + ctx.emit_span_lint(lint, span, check_cfg::unexpected_cfg_name(ctx.sess(), name, value)); } BuiltinLintDiag::UnexpectedCfgValue(name, value) => { - check_cfg::unexpected_cfg_value(sess, diag, name, value) - } - BuiltinLintDiag::DeprecatedWhereclauseLocation(sugg) => { - let left_sp = diag.span.primary_span().unwrap(); - match sugg { - Some((right_sp, sugg)) => diag.multipart_suggestion( - "move it to the end of the type declaration", - vec![(left_sp, String::new()), (right_sp, sugg)], - Applicability::MachineApplicable, - ), - None => diag.span_suggestion( - left_sp, - "remove this `where`", - "", - Applicability::MachineApplicable, - ), + ctx.emit_span_lint( + lint, + span, + check_cfg::unexpected_cfg_value(ctx.sess(), name, value), + ); + } + BuiltinLintDiag::DeprecatedWhereclauseLocation(left_sp, sugg) => { + let suggestion = match sugg { + Some((right_sp, sugg)) => lints::DeprecatedWhereClauseLocationSugg::MoveToEnd { + left: left_sp, + right: right_sp, + sugg, + }, + None => lints::DeprecatedWhereClauseLocationSugg::RemoveWhere { span: left_sp }, }; - diag.note("see issue #89122 for more information"); + ctx.emit_span_lint(lint, span, lints::DeprecatedWhereClauseLocation { suggestion }); } BuiltinLintDiag::SingleUseLifetime { param_span, use_span: Some((use_span, elide)), deletion_span, - .. + ident, } => { debug!(?param_span, ?use_span, ?deletion_span); - diag.span_label(param_span, "this lifetime..."); - diag.span_label(use_span, "...is used only here"); - if let Some(deletion_span) = deletion_span { - let msg = "elide the single-use lifetime"; + let suggestion = if let Some(deletion_span) = deletion_span { let (use_span, replace_lt) = if elide { - let use_span = sess.source_map().span_extend_while_whitespace(use_span); + let use_span = ctx.sess().source_map().span_extend_while_whitespace(use_span); (use_span, String::new()) } else { (use_span, "'_".to_owned()) @@ -249,26 +276,22 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di // issue 107998 for the case such as a wrong function pointer type // `deletion_span` is empty and there is no need to report lifetime uses here - let suggestions = if deletion_span.is_empty() { - vec![(use_span, replace_lt)] - } else { - vec![(deletion_span, String::new()), (use_span, replace_lt)] - }; - diag.multipart_suggestion(msg, suggestions, Applicability::MachineApplicable); - } + let deletion_span = + if deletion_span.is_empty() { None } else { Some(deletion_span) }; + Some(lints::SingleUseLifetimeSugg { deletion_span, use_span, replace_lt }) + } else { + None + }; + + ctx.emit_span_lint( + lint, + span, + lints::SingleUseLifetime { suggestion, param_span, use_span, ident }, + ); } - BuiltinLintDiag::SingleUseLifetime { - param_span: _, use_span: None, deletion_span, .. - } => { + BuiltinLintDiag::SingleUseLifetime { use_span: None, deletion_span, ident, .. } => { debug!(?deletion_span); - if let Some(deletion_span) = deletion_span { - diag.span_suggestion( - deletion_span, - "elide the unused lifetime", - "", - Applicability::MachineApplicable, - ); - } + ctx.emit_span_lint(lint, span, lints::UnusedLifetime { deletion_span, ident }); } BuiltinLintDiag::NamedArgumentUsedPositionally { position_sp_to_replace, @@ -277,52 +300,54 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di named_arg_name, is_formatting_arg, } => { - diag.span_label( - named_arg_sp, - "this named argument is referred to by position in formatting string", - ); - if let Some(positional_arg_for_msg) = position_sp_for_msg { - let msg = format!( - "this formatting argument uses named argument `{named_arg_name}` by position" - ); - diag.span_label(positional_arg_for_msg, msg); - } - - if let Some(positional_arg_to_replace) = position_sp_to_replace { - let name = if is_formatting_arg { named_arg_name + "$" } else { named_arg_name }; + let (suggestion, name) = if let Some(positional_arg_to_replace) = position_sp_to_replace + { + let mut name = named_arg_name.clone(); + if is_formatting_arg { + name.push('$') + }; let span_to_replace = if let Ok(positional_arg_content) = - sess.source_map().span_to_snippet(positional_arg_to_replace) + ctx.sess().source_map().span_to_snippet(positional_arg_to_replace) && positional_arg_content.starts_with(':') { positional_arg_to_replace.shrink_to_lo() } else { positional_arg_to_replace }; - diag.span_suggestion_verbose( - span_to_replace, - "use the named argument by name to avoid ambiguity", + (Some(span_to_replace), name) + } else { + (None, String::new()) + }; + + ctx.emit_span_lint( + lint, + span, + lints::NamedArgumentUsedPositionally { + named_arg_sp, + position_label_sp: position_sp_for_msg, + suggestion, name, - Applicability::MaybeIncorrect, - ); - } + named_arg_name, + }, + ) } - BuiltinLintDiag::ByteSliceInPackedStructWithDerive { .. } => { - diag.help("consider implementing the trait by hand, or remove the `packed` attribute"); + BuiltinLintDiag::ByteSliceInPackedStructWithDerive { ty } => { + ctx.emit_span_lint(lint, span, lints::ByteSliceInPackedStructWithDerive { ty }) } BuiltinLintDiag::UnusedExternCrate { removal_span } => { - diag.span_suggestion(removal_span, "remove it", "", Applicability::MachineApplicable); + ctx.emit_span_lint(lint, span, lints::UnusedExternCrate { removal_span }) } BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span } => { let suggestion_span = vis_span.between(ident_span); - diag.span_suggestion_verbose( - suggestion_span, - "convert it to a `use`", - if vis_span.is_empty() { "use " } else { " use " }, - Applicability::MachineApplicable, + let code = if vis_span.is_empty() { "use " } else { " use " }; + ctx.emit_span_lint( + lint, + span, + lints::ExternCrateNotIdiomatic { span: suggestion_span, code }, ); } BuiltinLintDiag::AmbiguousGlobImports { diag: ambiguity } => { - rustc_errors::report_ambiguity_error(diag, ambiguity); + ctx.emit_span_lint(lint, span, lints::AmbiguousGlobImports { ambiguity }); } BuiltinLintDiag::AmbiguousGlobReexports { name, @@ -330,15 +355,15 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di first_reexport_span, duplicate_reexport_span, } => { - diag.span_label( - first_reexport_span, - format!("the name `{name}` in the {namespace} namespace is first re-exported here"), - ); - diag.span_label( - duplicate_reexport_span, - format!( - "but the name `{name}` in the {namespace} namespace is also re-exported here" - ), + ctx.emit_span_lint( + lint, + span, + lints::AmbiguousGlobReexports { + first_reexport: first_reexport_span, + duplicate_reexport: duplicate_reexport_span, + name, + namespace, + }, ); } BuiltinLintDiag::HiddenGlobReexports { @@ -347,263 +372,123 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di glob_reexport_span, private_item_span, } => { - diag.span_note(glob_reexport_span, format!("the name `{name}` in the {namespace} namespace is supposed to be publicly re-exported here")); - diag.span_note(private_item_span, "but the private item here shadows it".to_owned()); + ctx.emit_span_lint( + lint, + span, + lints::HiddenGlobReexports { + glob_reexport: glob_reexport_span, + private_item: private_item_span, + + name, + namespace, + }, + ); } BuiltinLintDiag::UnusedQualifications { removal_span } => { - diag.span_suggestion_verbose( - removal_span, - "remove the unnecessary path segments", - "", - Applicability::MachineApplicable, - ); + ctx.emit_span_lint(lint, span, lints::UnusedQualifications { removal_span }); } - BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span } => { - diag.span_suggestion_verbose( - if elided { span.shrink_to_hi() } else { span }, - "use the `'static` lifetime", - if elided { "'static " } else { "'static" }, - Applicability::MachineApplicable, + BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span: lt_span } => { + let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span }; + let code = if elided { "'static " } else { "'static" }; + ctx.emit_span_lint( + lint, + span, + lints::AssociatedConstElidedLifetime { span: lt_span, code, elided }, ); } - BuiltinLintDiag::RedundantImportVisibility { max_vis, span, .. } => { - diag.span_note(span, format!("the most public imported item is `{max_vis}`")); - diag.help( - "reduce the glob import's visibility or increase visibility of imported items", + BuiltinLintDiag::RedundantImportVisibility { max_vis, span: vis_span, import_vis } => { + ctx.emit_span_lint( + lint, + span, + lints::RedundantImportVisibility { span: vis_span, max_vis, import_vis }, ); } - BuiltinLintDiag::MacroUseDeprecated - | BuiltinLintDiag::UnusedMacroUse - | BuiltinLintDiag::PrivateExternCrateReexport(_) - | BuiltinLintDiag::UnusedLabel - | BuiltinLintDiag::MacroIsPrivate(_) - | BuiltinLintDiag::UnusedMacroDefinition(_) - | BuiltinLintDiag::MacroRuleNeverUsed(_, _) - | BuiltinLintDiag::UnstableFeature(_) - | BuiltinLintDiag::AvoidUsingIntelSyntax - | BuiltinLintDiag::AvoidUsingAttSyntax - | BuiltinLintDiag::IncompleteInclude - | BuiltinLintDiag::UnnameableTestItems - | BuiltinLintDiag::DuplicateMacroAttribute - | BuiltinLintDiag::CfgAttrNoAttributes - | BuiltinLintDiag::CrateTypeInCfgAttr - | BuiltinLintDiag::CrateNameInCfgAttr - | BuiltinLintDiag::MissingFragmentSpecifier - | BuiltinLintDiag::MetaVariableStillRepeating(_) - | BuiltinLintDiag::MetaVariableWrongOperator - | BuiltinLintDiag::DuplicateMatcherBinding - | BuiltinLintDiag::UnknownMacroVariable(_) - | BuiltinLintDiag::UnusedExternCrate2 { .. } - | BuiltinLintDiag::WasmCAbi - | BuiltinLintDiag::IllFormedAttributeInput { .. } - | BuiltinLintDiag::InnerAttributeUnstable { .. } - | BuiltinLintDiag::UnknownDiagnosticAttribute => {} - } -} - -pub(super) fn builtin_message(diagnostic: &BuiltinLintDiag) -> DiagMessage { - match diagnostic { - BuiltinLintDiag::AbsPathWithModule(_) => { - "absolute paths must start with `self`, `super`, `crate`, or an \ - external crate name in the 2018 edition" - .into() - } - BuiltinLintDiag::ProcMacroDeriveResolutionFallback { ns, ident, .. } => { - format!("cannot find {} `{}` in this scope", ns.descr(), ident).into() - } - BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(_) => { - "macro-expanded `macro_export` macros from the current crate cannot \ - be referred to by absolute paths" - .into() - } - BuiltinLintDiag::ElidedLifetimesInPaths(_, _, _, _) => { - "hidden lifetime parameters in types are deprecated".into() - } - BuiltinLintDiag::UnknownCrateTypes { .. } => "invalid `crate_type` value".into(), - BuiltinLintDiag::UnusedImports { span_snippets, .. } => format!( - "unused import{}{}", - pluralize!(span_snippets.len()), - if !span_snippets.is_empty() { - format!(": {}", span_snippets.join(", ")) - } else { - String::new() - } - ) - .into(), - BuiltinLintDiag::RedundantImport(_, source) => { - format!("the item `{source}` is imported redundantly").into() - } - BuiltinLintDiag::DeprecatedMacro { since_kind, .. } => { - stability::Deprecated::msg_for_since_kind(since_kind) - } - BuiltinLintDiag::MissingAbi(_, _) => crate::fluent_generated::lint_extern_without_abi, - BuiltinLintDiag::UnusedDocComment(_) => "unused doc comment".into(), - BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, .. } => { - format!("unused attribute `{attr_name}`").into() - } - BuiltinLintDiag::PatternsInFnsWithoutBody { is_foreign, .. } => { - if *is_foreign { - crate::fluent_generated::lint_pattern_in_foreign - } else { - crate::fluent_generated::lint_pattern_in_bodiless - } - } - BuiltinLintDiag::LegacyDeriveHelpers(_) => { - "derive helper attribute is used before it is introduced".into() - } - BuiltinLintDiag::ProcMacroBackCompat(_) => "using an old version of `rental`".into(), - BuiltinLintDiag::OrPatternsBackCompat(_, _) => { - "the meaning of the `pat` fragment specifier is changing in Rust 2021, \ - which may affect this macro" - .into() - } - BuiltinLintDiag::ReservedPrefix(_, prefix) => { - format!("prefix `{prefix}` is unknown").into() - } - BuiltinLintDiag::TrailingMacro(_, _) => { - "trailing semicolon in macro used in expression position".into() - } - BuiltinLintDiag::BreakWithLabelAndLoop(_) => { - "this labeled break expression is easy to confuse with an unlabeled break with a \ - labeled value expression" - .into() - } - BuiltinLintDiag::UnicodeTextFlow(_, _) => { - "unicode codepoint changing visible direction of text present in comment".into() - } - BuiltinLintDiag::UnexpectedCfgName((name, _), _) => { - format!("unexpected `cfg` condition name: `{}`", name).into() - } - BuiltinLintDiag::UnexpectedCfgValue(_, v) => if let Some((value, _)) = v { - format!("unexpected `cfg` condition value: `{value}`") - } else { - format!("unexpected `cfg` condition value: (none)") - } - .into(), - BuiltinLintDiag::DeprecatedWhereclauseLocation(_) => { - crate::fluent_generated::lint_deprecated_where_clause_location + BuiltinLintDiag::MacroUseDeprecated => { + ctx.emit_span_lint(lint, span, lints::MacroUseDeprecated) } - BuiltinLintDiag::SingleUseLifetime { use_span, ident, .. } => { - if use_span.is_some() { - format!("lifetime parameter `{}` only used once", ident).into() - } else { - format!("lifetime parameter `{}` never used", ident).into() - } + BuiltinLintDiag::UnusedMacroUse => ctx.emit_span_lint(lint, span, lints::UnusedMacroUse), + BuiltinLintDiag::PrivateExternCrateReexport(ident) => { + ctx.emit_span_lint(lint, span, lints::PrivateExternCrateReexport { ident }) } - BuiltinLintDiag::NamedArgumentUsedPositionally { named_arg_name, .. } => { - format!("named argument `{}` is not used by name", named_arg_name).into() + BuiltinLintDiag::UnusedLabel => ctx.emit_span_lint(lint, span, lints::UnusedLabel), + BuiltinLintDiag::MacroIsPrivate(ident) => { + ctx.emit_span_lint(lint, span, lints::MacroIsPrivate { ident }) } - BuiltinLintDiag::ByteSliceInPackedStructWithDerive { ty } => { - format!("{ty} slice in a packed struct that derives a built-in trait").into() - } - BuiltinLintDiag::UnusedExternCrate { .. } => "unused extern crate".into(), - BuiltinLintDiag::ExternCrateNotIdiomatic { .. } => { - "`extern crate` is not idiomatic in the new edition".into() - } - BuiltinLintDiag::AmbiguousGlobImports { diag } => diag.msg.clone().into(), - BuiltinLintDiag::AmbiguousGlobReexports { .. } => "ambiguous glob re-exports".into(), - BuiltinLintDiag::HiddenGlobReexports { .. } => { - "private item shadows public glob re-export".into() - } - BuiltinLintDiag::UnusedQualifications { .. } => "unnecessary qualification".into(), - BuiltinLintDiag::AssociatedConstElidedLifetime { elided, .. } => if *elided { - "`&` without an explicit lifetime name cannot be used here" - } else { - "`'_` cannot be used here" - } - .into(), - BuiltinLintDiag::RedundantImportVisibility { import_vis, .. } => format!( - "glob import doesn't reexport anything with visibility `{}` \ - because no imported item is public enough", - import_vis - ) - .into(), - BuiltinLintDiag::MacroUseDeprecated => "deprecated `#[macro_use]` attribute used to \ - import macros should be replaced at use sites \ - with a `use` item to import the macro \ - instead" - .into(), - BuiltinLintDiag::UnusedMacroUse => "unused `#[macro_use]` import".into(), - BuiltinLintDiag::PrivateExternCrateReexport(ident) => format!( - "extern crate `{ident}` is private, and cannot be \ - re-exported (error E0365), consider declaring with \ - `pub`" - ) - .into(), - BuiltinLintDiag::UnusedLabel => "unused label".into(), - BuiltinLintDiag::MacroIsPrivate(ident) => format!("macro `{ident}` is private").into(), BuiltinLintDiag::UnusedMacroDefinition(name) => { - format!("unused macro definition: `{}`", name).into() + ctx.emit_span_lint(lint, span, lints::UnusedMacroDefinition { name }) } BuiltinLintDiag::MacroRuleNeverUsed(n, name) => { - format!("{} rule of macro `{}` is never used", ordinalize(n + 1), name).into() + ctx.emit_span_lint(lint, span, lints::MacroRuleNeverUsed { n: n + 1, name }) + } + BuiltinLintDiag::UnstableFeature(msg) => { + ctx.emit_span_lint(lint, span, lints::UnstableFeature { msg }) } - BuiltinLintDiag::UnstableFeature(msg) => msg.clone().into(), BuiltinLintDiag::AvoidUsingIntelSyntax => { - "avoid using `.intel_syntax`, Intel syntax is the default".into() + ctx.emit_span_lint(lint, span, lints::AvoidIntelSyntax) } BuiltinLintDiag::AvoidUsingAttSyntax => { - "avoid using `.att_syntax`, prefer using `options(att_syntax)` instead".into() + ctx.emit_span_lint(lint, span, lints::AvoidAttSyntax) } BuiltinLintDiag::IncompleteInclude => { - "include macro expected single expression in source".into() + ctx.emit_span_lint(lint, span, lints::IncompleteInclude) + } + BuiltinLintDiag::UnnameableTestItems => { + ctx.emit_span_lint(lint, span, lints::UnnameableTestItems) + } + BuiltinLintDiag::DuplicateMacroAttribute => { + ctx.emit_span_lint(lint, span, lints::DuplicateMacroAttribute) } - BuiltinLintDiag::UnnameableTestItems => crate::fluent_generated::lint_unnameable_test_items, - BuiltinLintDiag::DuplicateMacroAttribute => "duplicated attribute".into(), BuiltinLintDiag::CfgAttrNoAttributes => { - crate::fluent_generated::lint_cfg_attr_no_attributes + ctx.emit_span_lint(lint, span, lints::CfgAttrNoAttributes) } BuiltinLintDiag::CrateTypeInCfgAttr => { - crate::fluent_generated::lint_crate_type_in_cfg_attr_deprecated + ctx.emit_span_lint(lint, span, lints::CrateTypeInCfgAttr) } BuiltinLintDiag::CrateNameInCfgAttr => { - crate::fluent_generated::lint_crate_name_in_cfg_attr_deprecated + ctx.emit_span_lint(lint, span, lints::CrateNameInCfgAttr) + } + BuiltinLintDiag::MissingFragmentSpecifier => { + ctx.emit_span_lint(lint, span, lints::MissingFragmentSpecifier) } - BuiltinLintDiag::MissingFragmentSpecifier => "missing fragment specifier".into(), BuiltinLintDiag::MetaVariableStillRepeating(name) => { - format!("variable '{name}' is still repeating at this depth").into() + ctx.emit_span_lint(lint, span, lints::MetaVariableStillRepeating { name }) } BuiltinLintDiag::MetaVariableWrongOperator => { - "meta-variable repeats with different Kleene operator".into() + ctx.emit_span_lint(lint, span, lints::MetaVariableWrongOperator) + } + BuiltinLintDiag::DuplicateMatcherBinding => { + ctx.emit_span_lint(lint, span, lints::DuplicateMatcherBinding) } - BuiltinLintDiag::DuplicateMatcherBinding => "duplicate matcher binding".into(), BuiltinLintDiag::UnknownMacroVariable(name) => { - format!("unknown macro variable `{name}`").into() - } - BuiltinLintDiag::UnusedExternCrate2 { extern_crate, local_crate } => format!( - "external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`", - extern_crate, local_crate, extern_crate - ) - .into(), - BuiltinLintDiag::WasmCAbi => crate::fluent_generated::lint_wasm_c_abi, - BuiltinLintDiag::IllFormedAttributeInput { suggestions } => suggestions - .iter() - .enumerate() - .fold("attribute must be of the form ".to_string(), |mut acc, (i, sugg)| { - if i != 0 { - write!(acc, " or ").unwrap(); - } - write!(acc, "`{sugg}`").unwrap(); - acc - }) - .into(), - BuiltinLintDiag::InnerAttributeUnstable { is_macro } => if *is_macro { - "inner macro attributes are unstable" - } else { - "custom inner attributes are unstable" - } - .into(), - BuiltinLintDiag::UnknownDiagnosticAttribute => "unknown diagnostic attribute".into(), + ctx.emit_span_lint(lint, span, lints::UnknownMacroVariable { name }) + } + BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => ctx.emit_span_lint( + lint, + span, + lints::UnusedCrateDependency { extern_crate, local_crate }, + ), + BuiltinLintDiag::WasmCAbi => ctx.emit_span_lint(lint, span, lints::WasmCAbi), + BuiltinLintDiag::IllFormedAttributeInput { suggestions } => ctx.emit_span_lint( + lint, + span, + lints::IllFormedAttributeInput { + num_suggestions: suggestions.len(), + suggestions: DiagArgValue::StrListSepByAnd( + suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(), + ), + }, + ), + BuiltinLintDiag::InnerAttributeUnstable { is_macro } => ctx.emit_span_lint( + lint, + span, + if is_macro { + lints::InnerAttributeUnstable::InnerMacroAttribute + } else { + lints::InnerAttributeUnstable::CustomInnerAttribute + }, + ), + BuiltinLintDiag::UnknownDiagnosticAttribute => { + ctx.emit_span_lint(lint, span, lints::UnknownDiagnosticAttribute) + } } } - -/// Convert the given number into the corresponding ordinal -pub(crate) fn ordinalize(v: usize) -> String { - let suffix = match ((11..=13).contains(&(v % 100)), v % 10) { - (false, 1) => "st", - (false, 2) => "nd", - (false, 3) => "rd", - _ => "th", - }; - format!("{v}{suffix}") -} diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs index 7b19aefc93d5e..c7c312b84a71c 100644 --- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs +++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs @@ -1,4 +1,3 @@ -use rustc_errors::Diag; use rustc_middle::bug; use rustc_session::{config::ExpectedValues, Session}; use rustc_span::edit_distance::find_best_match_for_name; @@ -27,10 +26,9 @@ fn sort_and_truncate_possibilities( pub(super) fn unexpected_cfg_name( sess: &Session, - diag: &mut Diag<'_, ()>, (name, name_span): (Symbol, Span), value: Option<(Symbol, Span)>, -) { +) -> lints::UnexpectedCfgName { #[allow(rustc::potential_query_instability)] let possibilities: Vec = sess.psess.check_config.expecteds.keys().copied().collect(); @@ -165,18 +163,14 @@ pub(super) fn unexpected_cfg_name( } }; - diag.subdiagnostic( - diag.dcx, - lints::UnexpectedCfgNameSub { code_sugg, invocation_sugg: meta_sugg }, - ); + lints::UnexpectedCfgName { code_sugg, invocation_sugg: meta_sugg, name } } pub(super) fn unexpected_cfg_value( sess: &Session, - diag: &mut Diag<'_, ()>, (name, name_span): (Symbol, Span), value: Option<(Symbol, Span)>, -) { +) -> lints::UnexpectedCfgValue { let Some(ExpectedValues::Some(values)) = &sess.psess.check_config.expecteds.get(&name) else { bug!( "it shouldn't be possible to have a diagnostic on a value whose name is not in values" @@ -282,5 +276,10 @@ pub(super) fn unexpected_cfg_value( lints::unexpected_cfg_value::InvocationSuggestion::Rustc(help) }; - diag.subdiagnostic(diag.dcx, lints::UnexpectedCfgValueSub { code_sugg, invocation_sugg }); + lints::UnexpectedCfgValue { + code_sugg, + invocation_sugg, + has_value: value.is_some(), + value: value.map_or_else(String::new, |(v, _span)| v.to_string()), + } } diff --git a/compiler/rustc_lint/src/context/diagnostics/tests.rs b/compiler/rustc_lint/src/context/diagnostics/tests.rs deleted file mode 100644 index 2aa6cc61e460a..0000000000000 --- a/compiler/rustc_lint/src/context/diagnostics/tests.rs +++ /dev/null @@ -1,40 +0,0 @@ -use super::ordinalize; - -#[test] -fn test_ordinalize() { - assert_eq!(ordinalize(1), "1st"); - assert_eq!(ordinalize(2), "2nd"); - assert_eq!(ordinalize(3), "3rd"); - assert_eq!(ordinalize(4), "4th"); - assert_eq!(ordinalize(5), "5th"); - // ... - assert_eq!(ordinalize(10), "10th"); - assert_eq!(ordinalize(11), "11th"); - assert_eq!(ordinalize(12), "12th"); - assert_eq!(ordinalize(13), "13th"); - assert_eq!(ordinalize(14), "14th"); - // ... - assert_eq!(ordinalize(20), "20th"); - assert_eq!(ordinalize(21), "21st"); - assert_eq!(ordinalize(22), "22nd"); - assert_eq!(ordinalize(23), "23rd"); - assert_eq!(ordinalize(24), "24th"); - // ... - assert_eq!(ordinalize(30), "30th"); - assert_eq!(ordinalize(31), "31st"); - assert_eq!(ordinalize(32), "32nd"); - assert_eq!(ordinalize(33), "33rd"); - assert_eq!(ordinalize(34), "34th"); - // ... - assert_eq!(ordinalize(7010), "7010th"); - assert_eq!(ordinalize(7011), "7011th"); - assert_eq!(ordinalize(7012), "7012th"); - assert_eq!(ordinalize(7013), "7013th"); - assert_eq!(ordinalize(7014), "7014th"); - // ... - assert_eq!(ordinalize(7020), "7020th"); - assert_eq!(ordinalize(7021), "7021st"); - assert_eq!(ordinalize(7022), "7022nd"); - assert_eq!(ordinalize(7023), "7023rd"); - assert_eq!(ordinalize(7024), "7024th"); -} diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 80cb70ba277c8..736c7a1106932 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -14,7 +14,7 @@ //! upon. As the ast is traversed, this keeps track of the current lint level //! for all lint attributes. -use crate::context::{EarlyContext, LintContext, LintStore}; +use crate::context::{EarlyContext, LintStore}; use crate::passes::{EarlyLintPass, EarlyLintPassObject}; use rustc_ast::ptr::P; use rustc_ast::visit::{self as ast_visit, walk_list, Visitor}; @@ -45,7 +45,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { fn inlined_check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint; - self.context.span_lint_with_diagnostics(lint_id.lint, Some(span), |_| {}, diagnostic); + self.context.span_lint_with_diagnostics(lint_id.lint, span, diagnostic); } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 1b2189b661aa5..dcc3888dea09e 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -5,16 +5,22 @@ use std::num::NonZero; use crate::errors::RequestedLevel; use crate::fluent_generated as fluent; use rustc_errors::{ - codes::*, Applicability, Diag, DiagMessage, DiagStyledString, EmissionGuarantee, - LintDiagnostic, SubdiagMessageOp, Subdiagnostic, SuggestionStyle, + codes::*, Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, + ElidedLifetimeInPathSubdiag, EmissionGuarantee, LintDiagnostic, SubdiagMessageOp, + Subdiagnostic, SuggestionStyle, }; -use rustc_hir::def_id::DefId; +use rustc_hir::{def::Namespace, def_id::DefId}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{ inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt, }; -use rustc_session::Session; -use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol}; +use rustc_session::{lint::AmbiguityErrorDiag, Session}; +use rustc_span::{ + edition::Edition, + sym, + symbol::{Ident, MacroRulesNormalizedIdent}, + Span, Symbol, +}; use crate::{ builtin::InitError, builtin::TypeAliasBounds, errors::OverruledAttributeSub, LateContext, @@ -1953,12 +1959,15 @@ pub struct UnitBindingsDiag { #[note] pub struct BuiltinNamedAsmLabel; -#[derive(Subdiagnostic)] -pub struct UnexpectedCfgNameSub { +#[derive(LintDiagnostic)] +#[diag(lint_unexpected_cfg_name)] +pub struct UnexpectedCfgName { #[subdiagnostic] pub code_sugg: unexpected_cfg_name::CodeSuggestion, #[subdiagnostic] pub invocation_sugg: unexpected_cfg_name::InvocationSuggestion, + + pub name: Symbol, } pub mod unexpected_cfg_name { @@ -2067,12 +2076,16 @@ pub mod unexpected_cfg_name { } } -#[derive(Subdiagnostic)] -pub struct UnexpectedCfgValueSub { +#[derive(LintDiagnostic)] +#[diag(lint_unexpected_cfg_value)] +pub struct UnexpectedCfgValue { #[subdiagnostic] pub code_sugg: unexpected_cfg_value::CodeSuggestion, #[subdiagnostic] pub invocation_sugg: unexpected_cfg_value::InvocationSuggestion, + + pub has_value: bool, + pub value: String, } pub mod unexpected_cfg_value { @@ -2183,3 +2196,556 @@ pub mod unexpected_cfg_value { pub cmdline_arg: String, } } + +#[derive(LintDiagnostic)] +#[diag(lint_macro_use_deprecated)] +pub struct MacroUseDeprecated; + +#[derive(LintDiagnostic)] +#[diag(lint_unused_macro_use)] +pub struct UnusedMacroUse; + +#[derive(LintDiagnostic)] +#[diag(lint_private_extern_crate_reexport)] +pub struct PrivateExternCrateReexport { + pub ident: Ident, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_label)] +pub struct UnusedLabel; + +#[derive(LintDiagnostic)] +#[diag(lint_macro_is_private)] +pub struct MacroIsPrivate { + pub ident: Ident, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_macro_definition)] +pub struct UnusedMacroDefinition { + pub name: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(lint_macro_rule_never_used)] +pub struct MacroRuleNeverUsed { + pub n: usize, + pub name: Symbol, +} + +pub struct UnstableFeature { + pub msg: DiagMessage, +} + +impl<'a> LintDiagnostic<'a, ()> for UnstableFeature { + fn decorate_lint<'b>(self, _diag: &'b mut Diag<'a, ()>) {} + + fn msg(&self) -> DiagMessage { + self.msg.clone() + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_avoid_intel_syntax)] +pub struct AvoidIntelSyntax; + +#[derive(LintDiagnostic)] +#[diag(lint_avoid_att_syntax)] +pub struct AvoidAttSyntax; + +#[derive(LintDiagnostic)] +#[diag(lint_incomplete_include)] +pub struct IncompleteInclude; + +#[derive(LintDiagnostic)] +#[diag(lint_unnameable_test_items)] +pub struct UnnameableTestItems; + +#[derive(LintDiagnostic)] +#[diag(lint_duplicate_macro_attribute)] +pub struct DuplicateMacroAttribute; + +#[derive(LintDiagnostic)] +#[diag(lint_cfg_attr_no_attributes)] +pub struct CfgAttrNoAttributes; + +#[derive(LintDiagnostic)] +#[diag(lint_crate_type_in_cfg_attr_deprecated)] +pub struct CrateTypeInCfgAttr; + +#[derive(LintDiagnostic)] +#[diag(lint_crate_name_in_cfg_attr_deprecated)] +pub struct CrateNameInCfgAttr; + +#[derive(LintDiagnostic)] +#[diag(lint_missing_fragment_specifier)] +pub struct MissingFragmentSpecifier; + +#[derive(LintDiagnostic)] +#[diag(lint_metavariable_still_repeating)] +pub struct MetaVariableStillRepeating { + pub name: MacroRulesNormalizedIdent, +} + +#[derive(LintDiagnostic)] +#[diag(lint_metavariable_wrong_operator)] +pub struct MetaVariableWrongOperator; + +#[derive(LintDiagnostic)] +#[diag(lint_duplicate_matcher_binding)] +pub struct DuplicateMatcherBinding; + +#[derive(LintDiagnostic)] +#[diag(lint_unknown_macro_variable)] +pub struct UnknownMacroVariable { + pub name: MacroRulesNormalizedIdent, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_crate_dependency)] +pub struct UnusedCrateDependency { + pub extern_crate: Symbol, + pub local_crate: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(lint_wasm_c_abi)] +pub struct WasmCAbi; + +#[derive(LintDiagnostic)] +#[diag(lint_ill_formed_attribute_input)] +pub struct IllFormedAttributeInput { + pub num_suggestions: usize, + pub suggestions: DiagArgValue, +} + +#[derive(LintDiagnostic)] +pub enum InnerAttributeUnstable { + #[diag(lint_inner_macro_attribute_unstable)] + InnerMacroAttribute, + #[diag(lint_custom_inner_attribute_unstable)] + CustomInnerAttribute, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unknown_diagnostic_attribute)] +pub struct UnknownDiagnosticAttribute; + +#[derive(LintDiagnostic)] +#[diag(lint_unicode_text_flow)] +#[note] +pub struct UnicodeTextFlow { + #[label] + pub comment_span: Span, + #[subdiagnostic] + pub characters: Vec, + #[subdiagnostic] + pub suggestions: Option, + + pub num_codepoints: usize, +} + +#[derive(Subdiagnostic)] +#[label(lint_label_comment_char)] +pub struct UnicodeCharNoteSub { + #[primary_span] + pub span: Span, + pub c_debug: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable", style = "hidden")] +pub struct UnicodeTextFlowSuggestion { + #[suggestion_part(code = "")] + pub spans: Vec, +} + +#[derive(LintDiagnostic)] +#[diag(lint_abs_path_with_module)] +pub struct AbsPathWithModule { + #[subdiagnostic] + pub sugg: AbsPathWithModuleSugg, +} + +#[derive(Subdiagnostic)] +#[suggestion(lint_suggestion, code = "{replacement}")] +pub struct AbsPathWithModuleSugg { + #[primary_span] + pub span: Span, + #[applicability] + pub applicability: Applicability, + pub replacement: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_proc_macro_derive_resolution_fallback)] +pub struct ProcMacroDeriveResolutionFallback { + #[label] + pub span: Span, + pub ns: Namespace, + pub ident: Ident, +} + +#[derive(LintDiagnostic)] +#[diag(lint_macro_expanded_macro_exports_accessed_by_absolute_paths)] +pub struct MacroExpandedMacroExportsAccessedByAbsolutePaths { + #[note] + pub definition: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_hidden_lifetime_parameters)] +pub struct ElidedLifetimesInPaths { + #[subdiagnostic] + pub subdiag: ElidedLifetimeInPathSubdiag, +} + +#[derive(LintDiagnostic)] +#[diag(lint_invalid_crate_type_value)] +pub struct UnknownCrateTypes { + #[subdiagnostic] + pub sugg: Option, +} + +#[derive(Subdiagnostic)] +#[suggestion(lint_suggestion, code = r#""{candidate}""#, applicability = "maybe-incorrect")] +pub struct UnknownCrateTypesSub { + #[primary_span] + pub span: Span, + pub candidate: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_imports)] +pub struct UnusedImports { + #[subdiagnostic] + pub sugg: UnusedImportsSugg, + #[help] + pub test_module_span: Option, + + pub span_snippets: DiagArgValue, + pub num_snippets: usize, +} + +#[derive(Subdiagnostic)] +pub enum UnusedImportsSugg { + #[suggestion( + lint_suggestion_remove_whole_use, + applicability = "machine-applicable", + code = "", + style = "tool-only" + )] + RemoveWholeUse { + #[primary_span] + span: Span, + }, + #[multipart_suggestion( + lint_suggestion_remove_imports, + applicability = "machine-applicable", + style = "tool-only" + )] + RemoveImports { + #[suggestion_part(code = "")] + remove_spans: Vec, + num_to_remove: usize, + }, +} + +#[derive(LintDiagnostic)] +#[diag(lint_redundant_import)] +pub struct RedundantImport { + #[subdiagnostic] + pub subs: Vec, + + pub ident: Ident, +} + +#[derive(Subdiagnostic)] +pub enum RedundantImportSub { + #[label(lint_label_imported_here)] + ImportedHere(#[primary_span] Span), + #[label(lint_label_defined_here)] + DefinedHere(#[primary_span] Span), + #[label(lint_label_imported_prelude)] + ImportedPrelude(#[primary_span] Span), + #[label(lint_label_defined_prelude)] + DefinedPrelude(#[primary_span] Span), +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_doc_comment)] +#[help] +pub struct UnusedDocComment { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +pub enum PatternsInFnsWithoutBody { + #[diag(lint_pattern_in_foreign)] + Foreign { + #[subdiagnostic] + sub: PatternsInFnsWithoutBodySub, + }, + #[diag(lint_pattern_in_bodiless)] + Bodiless { + #[subdiagnostic] + sub: PatternsInFnsWithoutBodySub, + }, +} + +#[derive(Subdiagnostic)] +#[suggestion(lint_remove_mut_from_pattern, code = "{ident}", applicability = "machine-applicable")] +pub struct PatternsInFnsWithoutBodySub { + #[primary_span] + pub span: Span, + + pub ident: Ident, +} + +#[derive(LintDiagnostic)] +#[diag(lint_extern_without_abi)] +#[help] +pub struct MissingAbi { + #[label] + pub span: Span, + + pub default_abi: &'static str, +} + +#[derive(LintDiagnostic)] +#[diag(lint_legacy_derive_helpers)] +pub struct LegacyDeriveHelpers { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_proc_macro_back_compat)] +#[note] +pub struct ProcMacroBackCompat { + pub crate_name: String, + pub fixed_version: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_or_patterns_back_compat)] +pub struct OrPatternsBackCompat { + #[suggestion(code = "{suggestion}", applicability = "machine-applicable")] + pub span: Span, + pub suggestion: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_reserved_prefix)] +pub struct ReservedPrefix { + #[label] + pub label: Span, + #[suggestion(code = " ", applicability = "machine-applicable")] + pub suggestion: Span, + + pub prefix: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_builtin_attribute)] +pub struct UnusedBuiltinAttribute { + #[note] + pub invoc_span: Span, + + pub attr_name: Symbol, + pub macro_name: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_trailing_semi_macro)] +pub struct TrailingMacro { + #[note(lint_note1)] + #[note(lint_note2)] + pub is_trailing: bool, + + pub name: Ident, +} + +#[derive(LintDiagnostic)] +#[diag(lint_break_with_label_and_loop)] +pub struct BreakWithLabelAndLoop { + #[subdiagnostic] + pub sub: BreakWithLabelAndLoopSub, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +pub struct BreakWithLabelAndLoopSub { + #[suggestion_part(code = "(")] + pub left: Span, + #[suggestion_part(code = ")")] + pub right: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_deprecated_where_clause_location)] +#[note] +pub struct DeprecatedWhereClauseLocation { + #[subdiagnostic] + pub suggestion: DeprecatedWhereClauseLocationSugg, +} + +#[derive(Subdiagnostic)] +pub enum DeprecatedWhereClauseLocationSugg { + #[multipart_suggestion(lint_suggestion_move_to_end, applicability = "machine-applicable")] + MoveToEnd { + #[suggestion_part(code = "")] + left: Span, + #[suggestion_part(code = "{sugg}")] + right: Span, + + sugg: String, + }, + #[suggestion(lint_suggestion_remove_where, code = "", applicability = "machine-applicable")] + RemoveWhere { + #[primary_span] + span: Span, + }, +} + +#[derive(LintDiagnostic)] +#[diag(lint_single_use_lifetime)] +pub struct SingleUseLifetime { + #[label(lint_label_param)] + pub param_span: Span, + #[label(lint_label_use)] + pub use_span: Span, + #[subdiagnostic] + pub suggestion: Option, + + pub ident: Ident, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +pub struct SingleUseLifetimeSugg { + #[suggestion_part(code = "")] + pub deletion_span: Option, + #[suggestion_part(code = "{replace_lt}")] + pub use_span: Span, + + pub replace_lt: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_lifetime)] +pub struct UnusedLifetime { + #[suggestion(code = "", applicability = "machine-applicable")] + pub deletion_span: Option, + + pub ident: Ident, +} + +#[derive(LintDiagnostic)] +#[diag(lint_named_argument_used_positionally)] +pub struct NamedArgumentUsedPositionally { + #[label(lint_label_named_arg)] + pub named_arg_sp: Span, + #[label(lint_label_position_arg)] + pub position_label_sp: Option, + #[suggestion(style = "verbose", code = "{name}", applicability = "maybe-incorrect")] + pub suggestion: Option, + + pub name: String, + pub named_arg_name: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_byte_slice_in_packed_struct_with_derive)] +#[help] +pub struct ByteSliceInPackedStructWithDerive { + // FIXME: make this translatable + pub ty: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_extern_crate)] +pub struct UnusedExternCrate { + #[suggestion(code = "", applicability = "machine-applicable")] + pub removal_span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_extern_crate_not_idiomatic)] +pub struct ExternCrateNotIdiomatic { + #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")] + pub span: Span, + + pub code: &'static str, +} + +// FIXME: make this translatable +pub struct AmbiguousGlobImports { + pub ambiguity: AmbiguityErrorDiag, +} + +impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for AmbiguousGlobImports { + fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) { + rustc_errors::report_ambiguity_error(diag, self.ambiguity); + } + + fn msg(&self) -> DiagMessage { + DiagMessage::Str(self.ambiguity.msg.clone().into()) + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_ambiguous_glob_reexport)] +pub struct AmbiguousGlobReexports { + #[label(lint_label_first_reexport)] + pub first_reexport: Span, + #[label(lint_label_duplicate_reexport)] + pub duplicate_reexport: Span, + + pub name: String, + // FIXME: make this translatable + pub namespace: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_hidden_glob_reexport)] +pub struct HiddenGlobReexports { + #[note(lint_note_glob_reexport)] + pub glob_reexport: Span, + #[note(lint_note_private_item)] + pub private_item: Span, + + pub name: String, + // FIXME: make this translatable + pub namespace: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unnecessary_qualification)] +pub struct UnusedQualifications { + #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] + pub removal_span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_associated_const_elided_lifetime)] +pub struct AssociatedConstElidedLifetime { + #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")] + pub span: Span, + + pub code: &'static str, + pub elided: bool, +} + +#[derive(LintDiagnostic)] +#[diag(lint_redundant_import_visibility)] +#[help] +pub struct RedundantImportVisibility { + #[note] + pub span: Span, + + pub import_vis: String, + pub max_vis: String, +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 281ae38ef09b7..ba6db31e6aedf 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -5,7 +5,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::stable_hasher::{ HashStable, StableCompare, StableHasher, ToStableHashKey, }; -use rustc_error_messages::MultiSpan; +use rustc_error_messages::{DiagMessage, MultiSpan}; use rustc_hir::def::Namespace; use rustc_hir::HashStableContext; use rustc_hir::HirId; @@ -591,8 +591,9 @@ pub enum BuiltinLintDiag { candidate: Option, }, UnusedImports { - fix_msg: String, - fixes: Vec<(Span, String)>, + remove_whole_use: bool, + num_to_remove: usize, + remove_spans: Vec, test_module_span: Option, span_snippets: Vec, }, @@ -617,7 +618,10 @@ pub enum BuiltinLintDiag { is_foreign: bool, }, LegacyDeriveHelpers(Span), - ProcMacroBackCompat(String), + ProcMacroBackCompat { + crate_name: String, + fixed_version: String, + }, OrPatternsBackCompat(Span, String), ReservedPrefix(Span, String), TrailingMacro(bool, Ident), @@ -625,7 +629,7 @@ pub enum BuiltinLintDiag { UnicodeTextFlow(Span, String), UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>), UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>), - DeprecatedWhereclauseLocation(Option<(Span, String)>), + DeprecatedWhereclauseLocation(Span, Option<(Span, String)>), SingleUseLifetime { /// Span of the parameter which declares this lifetime. param_span: Span, @@ -704,7 +708,7 @@ pub enum BuiltinLintDiag { MacroIsPrivate(Ident), UnusedMacroDefinition(Symbol), MacroRuleNeverUsed(usize, Symbol), - UnstableFeature(String), + UnstableFeature(DiagMessage), AvoidUsingIntelSyntax, AvoidUsingAttSyntax, IncompleteInclude, @@ -718,8 +722,7 @@ pub enum BuiltinLintDiag { MetaVariableWrongOperator, DuplicateMatcherBinding, UnknownMacroVariable(MacroRulesNormalizedIdent), - // FIXME: combine with UnusedExternCrate? - UnusedExternCrate2 { + UnusedCrateDependency { extern_crate: Symbol, local_crate: Symbol, }, diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index fd671d91e3bdf..92628db98bbdb 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -977,7 +977,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { lint::builtin::UNUSED_CRATE_DEPENDENCIES, span, ast::CRATE_NODE_ID, - BuiltinLintDiag::UnusedExternCrate2 { + BuiltinLintDiag::UnusedCrateDependency { extern_crate: name_interned, local_crate: self.tcx.crate_name(LOCAL_CRATE), }, diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 37d2c6a707854..0451ab4a06b29 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -154,19 +154,6 @@ pub struct Deprecated { pub since_kind: DeprecatedSinceKind, } -impl Deprecated { - // FIXME: remove - pub fn msg_for_since_kind(since_kind: &DeprecatedSinceKind) -> rustc_errors::DiagMessage { - match since_kind { - DeprecatedSinceKind::InEffect => crate::fluent_generated::middle_deprecated, - DeprecatedSinceKind::InFuture => crate::fluent_generated::middle_deprecated_in_future, - DeprecatedSinceKind::InVersion(_) => { - crate::fluent_generated::middle_deprecated_in_version - } - } - } -} - impl<'a, G: EmissionGuarantee> rustc_errors::LintDiagnostic<'a, G> for Deprecated { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) { diag.arg("kind", self.kind); @@ -186,7 +173,13 @@ impl<'a, G: EmissionGuarantee> rustc_errors::LintDiagnostic<'a, G> for Deprecate } fn msg(&self) -> rustc_errors::DiagMessage { - Self::msg_for_since_kind(&self.since_kind) + match &self.since_kind { + DeprecatedSinceKind::InEffect => crate::fluent_generated::middle_deprecated, + DeprecatedSinceKind::InFuture => crate::fluent_generated::middle_deprecated_in_future, + DeprecatedSinceKind::InVersion(_) => { + crate::fluent_generated::middle_deprecated_in_version + } + } } } diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index c95b8f2a81651..d972bb05cff8f 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -433,20 +433,12 @@ impl Resolver<'_, '_> { visitor.report_unused_extern_crate_items(maybe_unused_extern_crates); for unused in visitor.unused_imports.values() { - let mut fixes = Vec::new(); - let spans = match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) { - UnusedSpanResult::Used => continue, - UnusedSpanResult::Unused { spans, remove } => { - fixes.push((remove, String::new())); - spans - } - UnusedSpanResult::PartialUnused { spans, remove } => { - for fix in &remove { - fixes.push((*fix, String::new())); - } - spans - } - }; + let (spans, remove_spans) = + match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) { + UnusedSpanResult::Used => continue, + UnusedSpanResult::Unused { spans, remove } => (spans, vec![remove]), + UnusedSpanResult::PartialUnused { spans, remove } => (spans, remove), + }; let ms = MultiSpan::from_spans(spans); @@ -458,13 +450,8 @@ impl Resolver<'_, '_> { .collect::>(); span_snippets.sort(); - let fix_msg = if fixes.len() == 1 && fixes[0].0 == unused.item_span { - "remove the whole `use` item" - } else if ms.primary_spans().len() > 1 { - "remove the unused imports" - } else { - "remove the unused import" - }; + let remove_whole_use = remove_spans.len() == 1 && remove_spans[0] == unused.item_span; + let num_to_remove = ms.primary_spans().len(); // If we are in the `--test` mode, suppress a help that adds the `#[cfg(test)]` // attribute; however, if not, suggest adding the attribute. There is no way to @@ -495,8 +482,9 @@ impl Resolver<'_, '_> { unused.use_tree_id, ms, BuiltinLintDiag::UnusedImports { - fix_msg: fix_msg.into(), - fixes, + remove_whole_use, + num_to_remove, + remove_spans, test_module_span, span_snippets, }, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 91b0d4a5192bc..5810abbeeee5d 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -841,7 +841,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { lint, node_id, span, - BuiltinLintDiag::UnstableFeature(msg), + BuiltinLintDiag::UnstableFeature( + // FIXME make this translatable + msg.into(), + ), ) }; stability::report_unstable( diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs index bd3b69c2b4a6a..ca60bc62b5183 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs @@ -45,7 +45,7 @@ mod inline { //~| NOTE not a function or closure #[inline = "2100"] fn f() { } - //~^ ERROR attribute must be of the form + //~^ ERROR valid forms for the attribute are //~| WARN this was previously accepted //~| NOTE #[deny(ill_formed_attribute_input)]` on by default //~| NOTE for more information, see issue #57571 diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index 89fa2abffc2fc..ac2bf78157d27 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -7,7 +7,7 @@ LL | #![rustc_main] = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: attribute must be of the form `#[inline]` or `#[inline(always|never)]` +error: valid forms for the attribute are `#[inline]` and `#[inline(always|never)]` --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:47:5 | LL | #[inline = "2100"] fn f() { } diff --git a/tests/ui/imports/no-pub-reexports-but-used.stderr b/tests/ui/imports/no-pub-reexports-but-used.stderr index b693dea193579..8d79e429a42a3 100644 --- a/tests/ui/imports/no-pub-reexports-but-used.stderr +++ b/tests/ui/imports/no-pub-reexports-but-used.stderr @@ -4,12 +4,12 @@ warning: glob import doesn't reexport anything with visibility `pub` because no LL | pub use m::*; | ^^^^ | + = help: reduce the glob import's visibility or increase visibility of imported items note: the most public imported item is `pub(crate)` --> $DIR/no-pub-reexports-but-used.rs:9:9 | LL | pub use m::*; | ^^^^ - = help: reduce the glob import's visibility or increase visibility of imported items note: the lint level is defined here --> $DIR/no-pub-reexports-but-used.rs:8:8 | diff --git a/tests/ui/imports/reexports.stderr b/tests/ui/imports/reexports.stderr index bf4ba474875bf..2bbdf2a476b5a 100644 --- a/tests/ui/imports/reexports.stderr +++ b/tests/ui/imports/reexports.stderr @@ -62,12 +62,12 @@ warning: glob import doesn't reexport anything with visibility `pub` because no LL | pub use super::*; | ^^^^^^^^ | + = help: reduce the glob import's visibility or increase visibility of imported items note: the most public imported item is `pub(a)` --> $DIR/reexports.rs:11:17 | LL | pub use super::*; | ^^^^^^^^ - = help: reduce the glob import's visibility or increase visibility of imported items warning: unused import: `super::*` --> $DIR/reexports.rs:11:17 diff --git a/tests/ui/lint/anonymous-reexport.stderr b/tests/ui/lint/anonymous-reexport.stderr index e3854a5459ec0..c4ee18fe8da2a 100644 --- a/tests/ui/lint/anonymous-reexport.stderr +++ b/tests/ui/lint/anonymous-reexport.stderr @@ -34,7 +34,7 @@ error: unused import: `Bar as _` LL | pub use self::my_mod::{Bar as _, Foo as _}; | ^^^^^^^^ -error: unused imports: `Bar as _`, `TyBar as _` +error: unused imports: `Bar as _` and `TyBar as _` --> $DIR/anonymous-reexport.rs:17:24 | LL | pub use self::my_mod::{Bar as _, TyBar as _}; diff --git a/tests/ui/lint/unused/import_remove_line.stderr b/tests/ui/lint/unused/import_remove_line.stderr index 0e8c5de3558e5..b2a16669a9398 100644 --- a/tests/ui/lint/unused/import_remove_line.stderr +++ b/tests/ui/lint/unused/import_remove_line.stderr @@ -1,4 +1,4 @@ -warning: unused imports: `Duration`, `Instant` +warning: unused imports: `Duration` and `Instant` --> $DIR/import_remove_line.rs:7:17 | LL | use std::time::{Duration, Instant}; diff --git a/tests/ui/lint/unused/lint-unused-imports.rs b/tests/ui/lint/unused/lint-unused-imports.rs index 88f2baa5da9b3..710fb7a5ed12a 100644 --- a/tests/ui/lint/unused/lint-unused-imports.rs +++ b/tests/ui/lint/unused/lint-unused-imports.rs @@ -10,7 +10,7 @@ use std::fmt::{}; // Should get errors for both 'Some' and 'None' use std::option::Option::{Some, None}; -//~^ ERROR unused imports: `None`, `Some` +//~^ ERROR unused imports: `None` and `Some` use test::A; //~ ERROR unused import: `test::A` // Be sure that if we just bring some methods into scope that they're also diff --git a/tests/ui/lint/unused/lint-unused-imports.stderr b/tests/ui/lint/unused/lint-unused-imports.stderr index 07684a84a64ff..a848fb31ebaba 100644 --- a/tests/ui/lint/unused/lint-unused-imports.stderr +++ b/tests/ui/lint/unused/lint-unused-imports.stderr @@ -10,7 +10,7 @@ note: the lint level is defined here LL | #![deny(unused_imports)] | ^^^^^^^^^^^^^^ -error: unused imports: `None`, `Some` +error: unused imports: `None` and `Some` --> $DIR/lint-unused-imports.rs:12:27 | LL | use std::option::Option::{Some, None}; diff --git a/tests/ui/malformed/malformed-regressions.rs b/tests/ui/malformed/malformed-regressions.rs index ac1444bbaef4e..f0a7aac59c1cc 100644 --- a/tests/ui/malformed/malformed-regressions.rs +++ b/tests/ui/malformed/malformed-regressions.rs @@ -1,8 +1,8 @@ -#[doc] //~ ERROR attribute must be of the form +#[doc] //~ ERROR valid forms for the attribute are //~^ WARN this was previously accepted -#[ignore()] //~ ERROR attribute must be of the form +#[ignore()] //~ ERROR valid forms for the attribute are //~^ WARN this was previously accepted -#[inline = ""] //~ ERROR attribute must be of the form +#[inline = ""] //~ ERROR valid forms for the attribute are //~^ WARN this was previously accepted #[link] //~ ERROR attribute must be of the form //~^ WARN this was previously accepted diff --git a/tests/ui/malformed/malformed-regressions.stderr b/tests/ui/malformed/malformed-regressions.stderr index 9bfbe7ebafd76..e1dbdb9ab3c66 100644 --- a/tests/ui/malformed/malformed-regressions.stderr +++ b/tests/ui/malformed/malformed-regressions.stderr @@ -1,4 +1,4 @@ -error: attribute must be of the form `#[doc(hidden|inline|...)]` or `#[doc = "string"]` +error: valid forms for the attribute are `#[doc(hidden|inline|...)]` and `#[doc = "string"]` --> $DIR/malformed-regressions.rs:1:1 | LL | #[doc] @@ -8,7 +8,7 @@ LL | #[doc] = note: for more information, see issue #57571 = note: `#[deny(ill_formed_attribute_input)]` on by default -error: attribute must be of the form `#[ignore]` or `#[ignore = "reason"]` +error: valid forms for the attribute are `#[ignore]` and `#[ignore = "reason"]` --> $DIR/malformed-regressions.rs:3:1 | LL | #[ignore()] @@ -17,7 +17,7 @@ LL | #[ignore()] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #57571 -error: attribute must be of the form `#[inline]` or `#[inline(always|never)]` +error: valid forms for the attribute are `#[inline]` and `#[inline(always|never)]` --> $DIR/malformed-regressions.rs:5:1 | LL | #[inline = ""] diff --git a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs index 653dcab577148..796ba4d233201 100644 --- a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs +++ b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs @@ -6,7 +6,7 @@ mod rank { pub use self::Lieutenant::{JuniorGrade, Full}; //~^ ERROR `JuniorGrade` is private, and cannot be re-exported //~| ERROR `Full` is private, and cannot be re-exported - //~| ERROR unused imports: `Full`, `JuniorGrade` + //~| ERROR unused imports: `Full` and `JuniorGrade` pub use self::PettyOfficer::*; //~^ ERROR glob import doesn't reexport anything //~| ERROR unused import: `self::PettyOfficer::*` diff --git a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr index 93a39edbb8232..f213e56f1e551 100644 --- a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr +++ b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr @@ -28,12 +28,12 @@ error: glob import doesn't reexport anything with visibility `pub` because no im LL | pub use self::Professor::*; | ^^^^^^^^^^^^^^^^^^ | + = help: reduce the glob import's visibility or increase visibility of imported items note: the most public imported item is `pub(self)` --> $DIR/issue-46209-private-enum-variant-reexport.rs:3:13 | LL | pub use self::Professor::*; | ^^^^^^^^^^^^^^^^^^ - = help: reduce the glob import's visibility or increase visibility of imported items note: the lint level is defined here --> $DIR/issue-46209-private-enum-variant-reexport.rs:1:8 | @@ -46,7 +46,7 @@ error: unused import: `self::Professor::*` LL | pub use self::Professor::*; | ^^^^^^^^^^^^^^^^^^ -error: unused imports: `Full`, `JuniorGrade` +error: unused imports: `Full` and `JuniorGrade` --> $DIR/issue-46209-private-enum-variant-reexport.rs:6:32 | LL | pub use self::Lieutenant::{JuniorGrade, Full}; @@ -58,12 +58,12 @@ error: glob import doesn't reexport anything with visibility `pub` because no im LL | pub use self::PettyOfficer::*; | ^^^^^^^^^^^^^^^^^^^^^ | + = help: reduce the glob import's visibility or increase visibility of imported items note: the most public imported item is `pub(self)` --> $DIR/issue-46209-private-enum-variant-reexport.rs:10:13 | LL | pub use self::PettyOfficer::*; | ^^^^^^^^^^^^^^^^^^^^^ - = help: reduce the glob import's visibility or increase visibility of imported items error: unused import: `self::PettyOfficer::*` --> $DIR/issue-46209-private-enum-variant-reexport.rs:10:13 @@ -77,12 +77,12 @@ error: glob import doesn't reexport anything with visibility `pub` because no im LL | pub use self::Crewman::*; | ^^^^^^^^^^^^^^^^ | + = help: reduce the glob import's visibility or increase visibility of imported items note: the most public imported item is `pub(crate)` --> $DIR/issue-46209-private-enum-variant-reexport.rs:13:13 | LL | pub use self::Crewman::*; | ^^^^^^^^^^^^^^^^ - = help: reduce the glob import's visibility or increase visibility of imported items error: unused import: `self::Crewman::*` --> $DIR/issue-46209-private-enum-variant-reexport.rs:13:13 diff --git a/tests/ui/privacy/private-variant-reexport.stderr b/tests/ui/privacy/private-variant-reexport.stderr index d73bd1a8cc29f..109c1078c33a6 100644 --- a/tests/ui/privacy/private-variant-reexport.stderr +++ b/tests/ui/privacy/private-variant-reexport.stderr @@ -36,12 +36,12 @@ error: glob import doesn't reexport anything with visibility `pub` because no im LL | pub use ::E::*; | ^^^^^^ | + = help: reduce the glob import's visibility or increase visibility of imported items note: the most public imported item is `pub(crate)` --> $DIR/private-variant-reexport.rs:15:13 | LL | pub use ::E::*; | ^^^^^^ - = help: reduce the glob import's visibility or increase visibility of imported items note: the lint level is defined here --> $DIR/private-variant-reexport.rs:13:8 | diff --git a/tests/ui/span/multispan-import-lint.stderr b/tests/ui/span/multispan-import-lint.stderr index 4a955d1b31f58..a4ea1af237bdd 100644 --- a/tests/ui/span/multispan-import-lint.stderr +++ b/tests/ui/span/multispan-import-lint.stderr @@ -1,4 +1,4 @@ -warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd` +warning: unused imports: `Eq`, `Ord`, `PartialEq`, and `PartialOrd` --> $DIR/multispan-import-lint.rs:5:16 | LL | use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd}; diff --git a/tests/ui/suggestions/unused-imports.stderr b/tests/ui/suggestions/unused-imports.stderr index bf112608da7ed..31edb4e5ec20d 100644 --- a/tests/ui/suggestions/unused-imports.stderr +++ b/tests/ui/suggestions/unused-imports.stderr @@ -1,4 +1,4 @@ -warning: unused imports: `A`, `C` +warning: unused imports: `A` and `C` --> $DIR/unused-imports.rs:22:14 | LL | use nested::{A, B, C}; @@ -10,7 +10,7 @@ note: the lint level is defined here LL | #![warn(unused_imports)] | ^^^^^^^^^^^^^^ -warning: unused imports: `D`, `E`, `G` +warning: unused imports: `D`, `E`, and `G` --> $DIR/unused-imports.rs:26:5 | LL | D, diff --git a/tests/ui/use/use-nested-groups-unused-imports.rs b/tests/ui/use/use-nested-groups-unused-imports.rs index ca6b8ba94d1ca..0c8ae558a5971 100644 --- a/tests/ui/use/use-nested-groups-unused-imports.rs +++ b/tests/ui/use/use-nested-groups-unused-imports.rs @@ -13,7 +13,7 @@ mod foo { } use foo::{Foo, bar::{baz::{}, foobar::*}, *}; - //~^ ERROR unused imports: `*`, `Foo`, `baz::{}`, `foobar::*` + //~^ ERROR unused imports: `*`, `Foo`, `baz::{}`, and `foobar::*` use foo::bar::baz::{*, *}; //~^ ERROR unused import: `*` use foo::{}; diff --git a/tests/ui/use/use-nested-groups-unused-imports.stderr b/tests/ui/use/use-nested-groups-unused-imports.stderr index 6610f8ecd4a28..dd39a852772c0 100644 --- a/tests/ui/use/use-nested-groups-unused-imports.stderr +++ b/tests/ui/use/use-nested-groups-unused-imports.stderr @@ -1,4 +1,4 @@ -error: unused imports: `*`, `Foo`, `baz::{}`, `foobar::*` +error: unused imports: `*`, `Foo`, `baz::{}`, and `foobar::*` --> $DIR/use-nested-groups-unused-imports.rs:15:11 | LL | use foo::{Foo, bar::{baz::{}, foobar::*}, *};