diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index f1f734b855c14..d0c6504796d8f 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -107,6 +107,9 @@ ast_passes_coroutine_and_c_variadic = functions cannot be both `{$coroutine_kind .const = `{$coroutine_kind}` because of this .variadic = C-variadic because of this +ast_passes_deprecated_where_clause_location = where clause not allowed here + .note = see issue #89122 for more information + ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses .label = not supported .suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax @@ -237,6 +240,8 @@ ast_passes_missing_unsafe_on_extern_lint = extern blocks should be unsafe ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name .help = consider using the `#[path]` attribute to specify filesystem path +ast_passes_move_leading_ty_alias_where_clause = move it to the end of the type declaration + ast_passes_negative_bound_not_supported = negative bounds are not supported @@ -259,6 +264,7 @@ ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior ast_passes_pattern_in_bodiless = patterns aren't allowed in functions without bodies .label = pattern not allowed in function without body + .remove_mut_sugg = remove `mut` from the parameter ast_passes_pattern_in_fn_pointer = patterns aren't allowed in function pointer types @@ -270,6 +276,8 @@ ast_passes_precise_capturing_duplicated = duplicate `use<...>` precise capturing ast_passes_precise_capturing_not_allowed_here = `use<...>` precise capturing syntax not allowed in {$loc} +ast_passes_remove_leading_ty_alias_where_clause = remove this `where` + ast_passes_static_without_body = free static item without body .suggestion = provide a definition for the static @@ -322,6 +330,10 @@ ast_passes_unsafe_negative_impl = negative impls cannot be unsafe ast_passes_unsafe_static = static items cannot be declared with `unsafe` safety qualifier outside of `extern` block +ast_passes_unused_visibilities = visibility qualifiers have no effect on `const _` declarations + .note = `const _` does not declare a name, so there is nothing for the qualifier to apply to + .suggestion = remove the qualifier + ast_passes_visibility_not_permitted = visibility qualifiers are not permitted here .enum_variant = enum variants and their fields always share the visibility of the enum they are in @@ -336,5 +348,3 @@ ast_passes_where_clause_after_type_alias = where clauses are not allowed after t ast_passes_where_clause_before_type_alias = where clauses are not allowed before the type for type aliases .note = see issue #89122 for more information - .remove_suggestion = remove this `where` - .move_suggestion = move it to the end of the type declaration diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 0d34ba6c2ca87..4539f5f611695 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -30,7 +30,6 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::{DiagCtxtHandle, LintBuffer}; use rustc_feature::Features; use rustc_session::Session; -use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{ DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, MISSING_UNSAFE_ON_EXTERN, PATTERNS_IN_FNS_WITHOUT_BODY, UNUSED_VISIBILITIES, @@ -166,13 +165,13 @@ impl<'a> AstValidator<'a> { state.print_where_predicate(p); } - errors::WhereClauseBeforeTypeAliasSugg::Move { + errors::ModifyLeadingTyAliasWhereClause::Move { left: span, snippet: state.s.eof(), right: ty_alias.after_where_clause.span.shrink_to_hi(), } } else { - errors::WhereClauseBeforeTypeAliasSugg::Remove { span } + errors::ModifyLeadingTyAliasWhereClause::Remove { span } }; Err(errors::WhereClauseBeforeTypeAlias { span, sugg }) @@ -230,14 +229,12 @@ impl<'a> AstValidator<'a> { }); } - fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option, bool)) { + fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option)) { for Param { pat, .. } in &decl.inputs { match pat.kind { PatKind::Missing | PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {} - PatKind::Ident(BindingMode::MUT, ident, None) => { - report_err(pat.span, Some(ident), true) - } - _ => report_err(pat.span, None, false), + PatKind::Ident(BindingMode::MUT, ident, None) => report_err(pat.span, Some(ident)), + _ => report_err(pat.span, None), } } } @@ -929,7 +926,7 @@ impl<'a> AstValidator<'a> { TyKind::FnPtr(bfty) => { self.check_fn_ptr_safety(bfty.decl_span, bfty.safety); self.check_fn_decl(&bfty.decl, SelfSemantic::No); - Self::check_decl_no_pat(&bfty.decl, |span, _, _| { + Self::check_decl_no_pat(&bfty.decl, |span, _| { self.dcx().emit_err(errors::PatternFnPointer { span }); }); if let Extern::Implicit(extern_span) = bfty.ext { @@ -1360,7 +1357,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { UNUSED_VISIBILITIES, item.id, item.vis.span, - BuiltinLintDiag::UnusedVisibility(item.vis.span), + errors::UnusedVisibility { span: item.vis.span }, ) } @@ -1646,25 +1643,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // Functions without bodies cannot have patterns. if let FnKind::Fn(ctxt, _, Fn { body: None, sig, .. }) = fk { - Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| { - if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) { - if let Some(ident) = ident { - self.lint_buffer.buffer_lint( - PATTERNS_IN_FNS_WITHOUT_BODY, - id, - span, - BuiltinLintDiag::PatternsInFnsWithoutBody { - span, - ident, - is_foreign: matches!(ctxt, FnCtxt::Foreign), - }, - ) - } - } else { - match ctxt { - FnCtxt::Foreign => self.dcx().emit_err(errors::PatternInForeign { span }), - _ => self.dcx().emit_err(errors::PatternInBodiless { span }), - }; + Self::check_decl_no_pat(&sig.decl, |span, mut_ident| match ctxt { + FnCtxt::Assoc(_) if let Some(mut_ident) = mut_ident => { + self.lint_buffer.buffer_lint( + PATTERNS_IN_FNS_WITHOUT_BODY, + id, + span, + errors::PatternInBodilessLint { removal: span.until(mut_ident.span) }, + ); + } + FnCtxt::Foreign => { + self.dcx().emit_err(errors::PatternInForeign { span }); + } + _ => { + self.dcx().emit_err(errors::PatternInBodiless { span }); } }); } @@ -1728,17 +1720,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let AssocItemKind::Type(ty_alias) = &item.kind && let Err(err) = self.check_type_alias_where_clause_location(ty_alias) { - let sugg = match err.sugg { - errors::WhereClauseBeforeTypeAliasSugg::Remove { .. } => None, - errors::WhereClauseBeforeTypeAliasSugg::Move { snippet, right, .. } => { - Some((right, snippet)) - } - }; self.lint_buffer.buffer_lint( DEPRECATED_WHERE_CLAUSE_LOCATION, item.id, err.span, - BuiltinLintDiag::DeprecatedWhereclauseLocation(err.span, sugg), + errors::DeprecatedWhereClauseLocation { sugg: err.sugg }, ); } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index bf9309614fe20..ceba4d507ba95 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -575,18 +575,30 @@ pub(crate) struct WhereClauseBeforeTypeAlias { #[primary_span] pub span: Span, #[subdiagnostic] - pub sugg: WhereClauseBeforeTypeAliasSugg, + pub sugg: ModifyLeadingTyAliasWhereClause, +} + +#[derive(LintDiagnostic)] +#[diag(ast_passes_deprecated_where_clause_location)] +#[note] +pub(crate) struct DeprecatedWhereClauseLocation { + #[subdiagnostic] + pub sugg: ModifyLeadingTyAliasWhereClause, } #[derive(Subdiagnostic)] -pub(crate) enum WhereClauseBeforeTypeAliasSugg { - #[suggestion(ast_passes_remove_suggestion, applicability = "machine-applicable", code = "")] +pub(crate) enum ModifyLeadingTyAliasWhereClause { + #[suggestion( + ast_passes_remove_leading_ty_alias_where_clause, + applicability = "machine-applicable", + code = "" + )] Remove { #[primary_span] span: Span, }, #[multipart_suggestion( - ast_passes_move_suggestion, + ast_passes_move_leading_ty_alias_where_clause, applicability = "machine-applicable", style = "verbose" )] @@ -743,7 +755,6 @@ pub(crate) struct CVariadicNotSupported<'a> { #[derive(Diagnostic)] #[diag(ast_passes_pattern_in_foreign, code = E0130)] -// FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`) pub(crate) struct PatternInForeign { #[primary_span] #[label] @@ -752,13 +763,19 @@ pub(crate) struct PatternInForeign { #[derive(Diagnostic)] #[diag(ast_passes_pattern_in_bodiless, code = E0642)] -// FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`) pub(crate) struct PatternInBodiless { #[primary_span] #[label] pub span: Span, } +#[derive(LintDiagnostic)] +#[diag(ast_passes_pattern_in_bodiless)] +pub(crate) struct PatternInBodilessLint { + #[suggestion(ast_passes_remove_mut_sugg, code = "", applicability = "machine-applicable")] + pub removal: Span, +} + #[derive(Diagnostic)] #[diag(ast_passes_equality_in_where)] #[note] @@ -990,3 +1007,11 @@ pub(crate) struct AbiX86Interrupt { pub spans: Vec, pub param_count: usize, } + +#[derive(LintDiagnostic)] +#[diag(ast_passes_unused_visibilities)] +#[note] +pub(crate) struct UnusedVisibility { + #[suggestion(style = "short", code = "", applicability = "machine-applicable")] + pub span: Span, +} diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 542f34d9d831f..863b2a5af05f0 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -270,6 +270,11 @@ builtin_macros_naked_functions_testing_attribute = .label = function marked with testing attribute here .naked_attribute = `#[unsafe(naked)]` is incompatible with testing attributes +builtin_macros_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 + builtin_macros_no_default_variant = `#[derive(Default)]` on enum with no `#[default]` .label = this enum needs a unit variant marked with `#[default]` .suggestion = make this unit variant default by placing `#[default]` on it diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 2a4c499349ad1..dee3f61f3ad06 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1,11 +1,13 @@ use rustc_errors::codes::*; use rustc_errors::{ - Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan, SingleLabelManySpans, - Subdiagnostic, + Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, LintDiagnostic, + MultiSpan, SingleLabelManySpans, Subdiagnostic, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; +use crate::fluent_generated as fluent; + #[derive(LintDiagnostic)] #[diag(builtin_macros_avoid_intel_syntax)] pub(crate) struct AvoidIntelSyntax; @@ -1058,3 +1060,35 @@ pub(crate) struct EiiMacroExpectedMaxOneArgument { pub span: Span, pub name: String, } + +pub(crate) struct NamedArgumentUsedPositionally { + pub position_sp_to_replace: Option, + pub position_sp_for_msg: Option, + pub named_arg_sp: Span, + pub named_arg_name: Symbol, + pub is_formatting_arg: bool, +} + +impl<'a> LintDiagnostic<'a, ()> for NamedArgumentUsedPositionally { + fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { + diag.primary_message(fluent::builtin_macros_named_argument_used_positionally); + diag.span_label(self.named_arg_sp, fluent::builtin_macros_label_named_arg); + if let Some(span) = self.position_sp_for_msg { + diag.span_label(span, fluent::builtin_macros_label_position_arg); + } + diag.arg("named_arg_name", self.named_arg_name); + + if let Some(positional_arg_to_replace) = self.position_sp_to_replace { + let mut name = self.named_arg_name.to_string(); + if self.is_formatting_arg { + name.push('$') + }; + diag.span_suggestion_verbose( + positional_arg_to_replace, + fluent::builtin_macros_suggestion, + name, + Applicability::MaybeIncorrect, + ); + } + } +} diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index a0ee7ac19899b..fd42d0aa88dac 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -14,8 +14,8 @@ use rustc_errors::{ pluralize, }; use rustc_expand::base::*; +use rustc_lint_defs::LintId; use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY; -use rustc_lint_defs::{BuiltinLintDiag, LintId}; use rustc_parse::exp; use rustc_parse_format as parse; use rustc_span::{BytePos, ErrorGuaranteed, Ident, InnerSpan, Span, Symbol}; @@ -589,11 +589,11 @@ fn make_format_args( span: Some(arg_name.span.into()), node_id: rustc_ast::CRATE_NODE_ID, lint_id: LintId::of(NAMED_ARGUMENTS_USED_POSITIONALLY), - diagnostic: BuiltinLintDiag::NamedArgumentUsedPositionally { + diagnostic: errors::NamedArgumentUsedPositionally { position_sp_to_replace, position_sp_for_msg, named_arg_sp: arg_name.span, - named_arg_name: arg_name.name.to_string(), + named_arg_name: arg_name.name, is_formatting_arg: matches!(used_as, Width | Precision), } .into(), diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 56a0a3ceebf5a..aef5d77b35c2a 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -1,10 +1,6 @@ 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_negative_literals = `-` has lower precedence than method calls, which might be unexpected .example = e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4` .negative_literal = add parentheses around the `-` and the literal to call the method on a negative literal @@ -16,13 +12,6 @@ lint_ambiguous_wide_pointer_comparisons = ambiguous wide pointer comparison, the .cast_suggestion = use untyped pointers to only compare their addresses .expect_suggestion = or expect the lint to compare the pointers metadata and addresses -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 - .note = cannot automatically infer `'static` because of other lifetimes in scope - 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 @@ -44,9 +33,6 @@ 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 @@ -225,11 +211,6 @@ lint_deprecated_lint_name = .suggestion = change it to .help = change it to {$replace} -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 @@ -338,10 +319,6 @@ lint_forgetting_references = calls to `std::mem::forget` with a reference instea lint_function_casts_as_integer = direct cast of function item into an integer .cast_as_fn = first cast to a pointer `as *const ()` -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_identifier_non_ascii_char = identifier contains non-ASCII characters @@ -604,11 +581,6 @@ lint_mixed_script_confusables = lint_multiple_supertrait_upcastable = `{$ident}` is dyn-compatible 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} @@ -749,12 +721,6 @@ lint_path_statement_drop = path statement drops value lint_path_statement_no_effect = path statement with no effect -lint_pattern_in_bodiless = patterns aren't allowed in functions without bodies - .label = pattern not allowed in function without body - -lint_pattern_in_foreign = patterns aren't allowed in foreign function declarations - .label = pattern not allowed in foreign function - lint_query_instability = using `{$query}` can result in unstable query results .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale @@ -765,11 +731,6 @@ lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}` lint_range_use_inclusive_range = use an inclusive range instead - -lint_raw_prefix = prefix `'r` is reserved - .label = reserved prefix - .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021 - lint_reason_must_be_string_literal = reason must be a string literal lint_reason_must_come_last = reason in lint attribute must come last @@ -791,8 +752,6 @@ lint_redundant_semicolons_suggestion = remove {$multiple_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}` @@ -801,16 +760,6 @@ lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}` lint_requested_level = requested on the command line with `{$level} {$lint_name}` -lint_reserved_multihash = reserved token in Rust 2024 - .suggestion = insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 - -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_reserved_string = will be parsed as a guarded string in Rust 2024 - .suggestion = insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 - lint_shadowed_into_iter = this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<{$target} as IntoIterator>::into_iter` in Rust {$edition} .use_iter_suggestion = use `.iter()` instead of `.into_iter()` to avoid ambiguity @@ -927,16 +876,6 @@ lint_unexpected_cfg_value_specify_value = specify a config value 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 `()` @@ -958,9 +897,6 @@ lint_unknown_lint = 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_unnecessary_qualification = unnecessary qualification - .suggestion = remove the unnecessary path segments - lint_unpredictable_fn_pointer_comparisons = function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique .note_duplicated_fn = the address of the same function can vary between different codegen units .note_deduplicated_fn = furthermore, different functions could have the same address after being merged together @@ -996,9 +932,6 @@ lint_unused_coroutine = }{$post} that must be used .note = coroutines are lazy and do nothing unless resumed -lint_unused_crate_dependency = extern crate `{$extern_crate}` is unused in crate `{$local_crate}` - .help = remove the dependency or add `use {$extern_crate} as _;` to the crate root - lint_unused_def = unused {$pre}`{$def}`{$post} that must be used .suggestion = use `let _ = ...` to ignore the resulting value @@ -1033,10 +966,6 @@ lint_unused_op = unused {$op} that must be used lint_unused_result = unused result of type `{$ty}` -lint_unused_visibilities = visibility qualifiers have no effect on `const _` declarations - .note = `const _` does not declare a name, so there is nothing for the qualifier to apply to - .suggestion = remove the qualifier - lint_use_let_underscore_ignore_suggestion = use `let _ = ...` to ignore the expression or result lint_useless_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index f622de7f84d93..949d83c327948 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -1,6 +1,5 @@ use std::borrow::Cow; -use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; use rustc_errors::{ Applicability, Diag, DiagArgValue, LintDiagnostic, elided_lifetime_in_path_suggestion, }; @@ -9,7 +8,6 @@ use rustc_middle::middle::stability; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::lint::BuiltinLintDiag; -use rustc_span::BytePos; use tracing::debug; use crate::lints; @@ -23,32 +21,6 @@ pub fn decorate_builtin_lint( diag: &mut Diag<'_, ()>, ) { match diagnostic { - BuiltinLintDiag::UnicodeTextFlow(comment_span, content) => { - let spans: Vec<_> = content - .char_indices() - .filter_map(|(i, c)| { - TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| { - 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 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(), - }); - - lints::UnicodeTextFlow { - comment_span, - characters, - suggestions, - num_codepoints: spans.len(), - } - .decorate_lint(diag); - } BuiltinLintDiag::AbsPathWithModule(mod_span) => { let (replacement, applicability) = match sess.source_map().span_to_snippet(mod_span) { Ok(ref s) => { @@ -132,54 +104,6 @@ pub fn decorate_builtin_lint( stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind } .decorate_lint(diag); } - BuiltinLintDiag::PatternsInFnsWithoutBody { span: remove_span, ident, is_foreign } => { - let sub = lints::PatternsInFnsWithoutBodySub { ident, span: remove_span }; - if is_foreign { - lints::PatternsInFnsWithoutBody::Foreign { sub } - } else { - lints::PatternsInFnsWithoutBody::Bodiless { sub } - } - .decorate_lint(diag); - } - BuiltinLintDiag::ReservedPrefix(label_span, prefix) => { - lints::ReservedPrefix { - label: label_span, - suggestion: label_span.shrink_to_hi(), - prefix, - } - .decorate_lint(diag); - } - BuiltinLintDiag::RawPrefix(label_span) => { - lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() } - .decorate_lint(diag); - } - BuiltinLintDiag::ReservedString { is_string, suggestion } => { - if is_string { - lints::ReservedString { suggestion }.decorate_lint(diag); - } else { - lints::ReservedMultihash { suggestion }.decorate_lint(diag); - } - } - BuiltinLintDiag::BreakWithLabelAndLoop(sugg_span) => { - lints::BreakWithLabelAndLoop { - sub: lints::BreakWithLabelAndLoopSub { - left: sugg_span.shrink_to_lo(), - right: sugg_span.shrink_to_hi(), - }, - } - .decorate_lint(diag); - } - 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 }, - }; - lints::DeprecatedWhereClauseLocation { suggestion }.decorate_lint(diag); - } BuiltinLintDiag::SingleUseLifetime { param_span, use_span: Some((use_span, elide)), @@ -211,94 +135,6 @@ pub fn decorate_builtin_lint( BuiltinLintDiag::SingleUseLifetime { use_span: None, deletion_span, ident, .. } => { lints::UnusedLifetime { deletion_span, ident }.decorate_lint(diag); } - BuiltinLintDiag::NamedArgumentUsedPositionally { - position_sp_to_replace, - position_sp_for_msg, - named_arg_sp, - named_arg_name, - is_formatting_arg, - } => { - 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) - && positional_arg_content.starts_with(':') - { - positional_arg_to_replace.shrink_to_lo() - } else { - positional_arg_to_replace - }; - (Some(span_to_replace), name) - } else { - (None, String::new()) - }; - - lints::NamedArgumentUsedPositionally { - named_arg_sp, - position_label_sp: position_sp_for_msg, - suggestion, - name, - named_arg_name, - } - .decorate_lint(diag); - } - BuiltinLintDiag::AmbiguousGlobReexports { - name, - namespace, - first_reexport_span, - duplicate_reexport_span, - } => { - lints::AmbiguousGlobReexports { - first_reexport: first_reexport_span, - duplicate_reexport: duplicate_reexport_span, - name, - namespace, - } - .decorate_lint(diag); - } - BuiltinLintDiag::HiddenGlobReexports { - name, - namespace, - glob_reexport_span, - private_item_span, - } => { - lints::HiddenGlobReexports { - glob_reexport: glob_reexport_span, - private_item: private_item_span, - - name, - namespace, - } - .decorate_lint(diag); - } - BuiltinLintDiag::UnusedQualifications { removal_span } => { - lints::UnusedQualifications { removal_span }.decorate_lint(diag); - } - BuiltinLintDiag::AssociatedConstElidedLifetime { - elided, - span: lt_span, - lifetimes_in_scope, - } => { - let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span }; - let code = if elided { "'static " } else { "'static" }; - lints::AssociatedConstElidedLifetime { - span: lt_span, - code, - elided, - lifetimes_in_scope, - } - .decorate_lint(diag); - } - BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => { - lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag) - } - BuiltinLintDiag::UnusedVisibility(span) => { - lints::UnusedVisibility { span }.decorate_lint(diag) - } BuiltinLintDiag::AttributeLint(kind) => decorate_attribute_lint(sess, tcx, &kind, diag), } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 5017ce7caa525..851599138c9b9 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -6,7 +6,7 @@ use std::num::NonZero; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, ElidedLifetimeInPathSubdiag, - EmissionGuarantee, LintDiagnostic, MultiSpan, Subdiagnostic, SuggestionStyle, + EmissionGuarantee, LintDiagnostic, Subdiagnostic, SuggestionStyle, }; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -2585,14 +2585,6 @@ pub(crate) mod unexpected_cfg_value { } } -#[derive(LintDiagnostic)] -#[diag(lint_unused_crate_dependency)] -#[help] -pub(crate) struct UnusedCrateDependency { - pub extern_crate: Symbol, - pub local_crate: Symbol, -} - // FIXME(jdonszelmann): duplicated in rustc_attr_parsing, should be moved there completely. #[derive(LintDiagnostic)] #[diag(lint_ill_formed_attribute_input)] @@ -2604,35 +2596,6 @@ pub(crate) struct IllFormedAttributeInput { pub docs: &'static str, } -#[derive(LintDiagnostic)] -#[diag(lint_unicode_text_flow)] -#[note] -pub(crate) 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(crate) struct UnicodeCharNoteSub { - #[primary_span] - pub span: Span, - pub c_debug: String, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable", style = "hidden")] -pub(crate) struct UnicodeTextFlowSuggestion { - #[suggestion_part(code = "")] - pub spans: Vec, -} - #[derive(LintDiagnostic)] #[diag(lint_abs_path_with_module)] pub(crate) struct AbsPathWithModule { @@ -2714,91 +2677,6 @@ pub(crate) enum RedundantImportSub { DefinedPrelude(#[primary_span] Span), } -#[derive(LintDiagnostic)] -pub(crate) 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(crate) struct PatternsInFnsWithoutBodySub { - #[primary_span] - pub span: Span, - - pub ident: Ident, -} - -#[derive(LintDiagnostic)] -#[diag(lint_reserved_prefix)] -pub(crate) struct ReservedPrefix { - #[label] - pub label: Span, - #[suggestion(code = " ", applicability = "machine-applicable")] - pub suggestion: Span, - - pub prefix: String, -} - -#[derive(LintDiagnostic)] -#[diag(lint_raw_prefix)] -pub(crate) struct RawPrefix { - #[label] - pub label: Span, - #[suggestion(code = " ", applicability = "machine-applicable")] - pub suggestion: Span, -} - -#[derive(LintDiagnostic)] -#[diag(lint_break_with_label_and_loop)] -pub(crate) struct BreakWithLabelAndLoop { - #[subdiagnostic] - pub sub: BreakWithLabelAndLoopSub, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] -pub(crate) struct BreakWithLabelAndLoopSub { - #[suggestion_part(code = "(")] - pub left: Span, - #[suggestion_part(code = ")")] - pub right: Span, -} - -#[derive(LintDiagnostic)] -#[diag(lint_deprecated_where_clause_location)] -#[note] -pub(crate) struct DeprecatedWhereClauseLocation { - #[subdiagnostic] - pub suggestion: DeprecatedWhereClauseLocationSugg, -} - -#[derive(Subdiagnostic)] -pub(crate) 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(crate) struct SingleUseLifetime { @@ -2832,65 +2710,6 @@ pub(crate) struct UnusedLifetime { pub ident: Ident, } -#[derive(LintDiagnostic)] -#[diag(lint_named_argument_used_positionally)] -pub(crate) 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_ambiguous_glob_reexport)] -pub(crate) 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(crate) 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(crate) struct UnusedQualifications { - #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] - pub removal_span: Span, -} - -#[derive(LintDiagnostic)] -#[diag(lint_associated_const_elided_lifetime)] -pub(crate) struct AssociatedConstElidedLifetime { - #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")] - pub span: Span, - - pub code: &'static str, - pub elided: bool, - #[note] - pub lifetimes_in_scope: MultiSpan, -} - #[derive(LintDiagnostic)] #[diag(lint_static_mut_refs_lint)] pub(crate) struct RefOfMutStatic<'a> { @@ -2927,20 +2746,6 @@ pub(crate) enum MutRefSugg { #[diag(lint_unqualified_local_imports)] pub(crate) struct UnqualifiedLocalImportsDiag {} -#[derive(LintDiagnostic)] -#[diag(lint_reserved_string)] -pub(crate) struct ReservedString { - #[suggestion(code = " ", applicability = "machine-applicable")] - pub suggestion: Span, -} - -#[derive(LintDiagnostic)] -#[diag(lint_reserved_multihash)] -pub(crate) struct ReservedMultihash { - #[suggestion(code = " ", applicability = "machine-applicable")] - pub suggestion: Span, -} - #[derive(LintDiagnostic)] #[diag(lint_function_casts_as_integer)] pub(crate) struct FunctionCastsAsIntegerDiag<'tcx> { @@ -3203,14 +3008,6 @@ pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { pub right: Span, } -#[derive(LintDiagnostic)] -#[diag(lint_unused_visibilities)] -#[note] -pub(crate) struct UnusedVisibility { - #[suggestion(style = "short", code = "", applicability = "machine-applicable")] - pub span: Span, -} - #[derive(LintDiagnostic)] #[diag(lint_doc_alias_duplicated)] pub(crate) struct DocAliasDuplicated { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 7b41cfbb43ef0..4f21a04b1aef1 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::stable_hasher::{ HashStable, StableCompare, StableHasher, ToStableHashKey, }; -use rustc_error_messages::{DiagArgValue, IntoDiagArg, MultiSpan}; +use rustc_error_messages::{DiagArgValue, IntoDiagArg}; use rustc_hir_id::{HashStableContext, HirId, ItemLocalId}; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::def_id::DefPathHash; @@ -673,22 +673,6 @@ pub enum BuiltinLintDiag { path: String, since_kind: DeprecatedSinceKind, }, - PatternsInFnsWithoutBody { - span: Span, - ident: Ident, - is_foreign: bool, - }, - ReservedPrefix(Span, String), - /// `'r#` in edition < 2021. - RawPrefix(Span), - /// `##` or `#"` in edition < 2024. - ReservedString { - is_string: bool, - suggestion: Span, - }, - BreakWithLabelAndLoop(Span), - UnicodeTextFlow(Span, String), - DeprecatedWhereclauseLocation(Span, Option<(Span, String)>), SingleUseLifetime { /// Span of the parameter which declares this lifetime. param_span: Span, @@ -700,53 +684,6 @@ pub enum BuiltinLintDiag { use_span: Option<(Span, bool)>, ident: Ident, }, - NamedArgumentUsedPositionally { - /// Span where the named argument is used by position and will be replaced with the named - /// argument name - position_sp_to_replace: Option, - /// Span where the named argument is used by position and is used for lint messages - position_sp_for_msg: Option, - /// Span where the named argument's name is (so we know where to put the warning message) - named_arg_sp: Span, - /// String containing the named arguments name - named_arg_name: String, - /// Indicates if the named argument is used as a width/precision for formatting - is_formatting_arg: bool, - }, - AmbiguousGlobReexports { - /// The name for which collision(s) have occurred. - name: String, - /// The name space for which the collision(s) occurred in. - namespace: String, - /// Span where the name is first re-exported. - first_reexport_span: Span, - /// Span where the same name is also re-exported. - duplicate_reexport_span: Span, - }, - HiddenGlobReexports { - /// The name of the local binding which shadows the glob re-export. - name: String, - /// The namespace for which the shadowing occurred in. - namespace: String, - /// The glob reexport that is shadowed by the local binding. - glob_reexport_span: Span, - /// The local binding that shadows the glob reexport. - private_item_span: Span, - }, - UnusedQualifications { - /// The span of the unnecessarily-qualified path to remove. - removal_span: Span, - }, - AssociatedConstElidedLifetime { - elided: bool, - span: Span, - lifetimes_in_scope: MultiSpan, - }, - UnusedCrateDependency { - extern_crate: Symbol, - local_crate: Symbol, - }, - UnusedVisibility(Span), AttributeLint(AttributeLintKind), } diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index fac7b6c21f60c..72f2e1819513f 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -236,5 +236,8 @@ metadata_two_panic_runtimes = metadata_unknown_target_modifier_unsafe_allowed = unknown target modifier `{$flag_name}`, requested by `-Cunsafe-allow-abi-mismatch={$flag_name}` +metadata_unused_crate_dependency = extern crate `{$extern_crate}` is unused in crate `{$local_crate}` + .help = remove the dependency or add `use {$extern_crate} as _;` to the crate root + metadata_wasm_c_abi = older versions of the `wasm-bindgen` crate are incompatible with current versions of Rust; please update to `wasm-bindgen` v0.2.88 diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index b02029cd9a19b..920e7c156cf65 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -23,15 +23,14 @@ use rustc_middle::bug; use rustc_middle::ty::data_structures::IndexSet; use rustc_middle::ty::{TyCtxt, TyCtxtFeed}; use rustc_proc_macro::bridge::client::ProcMacro; -use rustc_session::Session; use rustc_session::config::{ CrateType, ExtendedTargetModifierInfo, ExternLocation, Externs, OptionsTargetModifiers, TargetModifier, }; use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource}; -use rustc_session::lint::{self, BuiltinLintDiag}; use rustc_session::output::validate_crate_name; use rustc_session::search_paths::PathKind; +use rustc_session::{Session, lint}; use rustc_span::def_id::DefId; use rustc_span::edition::Edition; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym}; @@ -1205,7 +1204,7 @@ impl CStore { lint::builtin::UNUSED_CRATE_DEPENDENCIES, span, ast::CRATE_NODE_ID, - BuiltinLintDiag::UnusedCrateDependency { + errors::UnusedCrateDependency { extern_crate: name_interned, local_crate: tcx.crate_name(LOCAL_CRATE), }, diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index abfd078f7462d..1d967d2052785 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -3,7 +3,7 @@ use std::path::{Path, PathBuf}; use rustc_errors::codes::*; use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level}; -use rustc_macros::{Diagnostic, Subdiagnostic}; +use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol, sym}; use rustc_target::spec::{PanicStrategy, TargetTuple}; @@ -615,3 +615,11 @@ pub struct RawDylibMalformed { #[primary_span] pub span: Span, } + +#[derive(LintDiagnostic)] +#[diag(metadata_unused_crate_dependency)] +#[help] +pub(crate) struct UnusedCrateDependency { + pub extern_crate: Symbol, + pub local_crate: Symbol, +} diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 87d1173c0d486..1e12948804f25 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -115,6 +115,9 @@ parse_box_not_pat = expected pattern, found {$descr} parse_box_syntax_removed = `box_syntax` has been removed parse_box_syntax_removed_suggestion = use `Box::new()` instead +parse_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 + parse_cannot_be_raw_ident = `{$ident}` cannot be a raw identifier parse_cannot_be_raw_lifetime = `{$ident}` cannot be a raw lifetime @@ -773,6 +776,10 @@ parse_question_mark_in_type = invalid `?` in type .label = `?` is only allowed on expressions, not types .suggestion = if you meant to express that the type might not contain a value, use the `Option` wrapper type +parse_raw_prefix = prefix `'r` is reserved + .label = reserved prefix + .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021 + parse_recover_import_as_use = expected item, found {$token_name} .suggestion = items are imported using the `use` keyword @@ -787,13 +794,23 @@ parse_require_colon_after_labeled_expression = labeled expression must be follow .label = the label .suggestion = add `:` after the label +parse_reserved_guarded_string = invalid string literal + .note = unprefixed guarded string literals are reserved for future use since Rust 2024 + .suggestion = consider inserting whitespace here + +parse_reserved_guarded_string_lint = will be parsed as a guarded string in Rust 2024 + .suggestion = insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + parse_reserved_multihash = reserved multi-hash token is forbidden .note = sequences of two or more # are reserved for future use since Rust 2024 - .suggestion_whitespace = consider inserting whitespace here + .suggestion = consider inserting whitespace here -parse_reserved_string = invalid string literal - .note = unprefixed guarded string literals are reserved for future use since Rust 2024 - .suggestion_whitespace = consider inserting whitespace here +parse_reserved_multihash_lint = reserved token in Rust 2024 + .suggestion = insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 + +parse_reserved_prefix = prefix `{$prefix}` is unknown + .label = unknown prefix + .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021 parse_return_types_use_thin_arrow = return types are denoted using `->` .suggestion = use `->` instead @@ -951,6 +968,14 @@ parse_unicode_escape_in_byte = unicode escape in byte string .label = {parse_unicode_escape_in_byte} .help = unicode escape sequences cannot be used as a byte or in a byte string +parse_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 + parse_unknown_builtin_construct = unknown `builtin #` construct `{$name}` parse_unknown_prefix = prefix `{$prefix}` is unknown diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 698d8f76aaa64..8ce3385c02313 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -5,16 +5,17 @@ use std::path::PathBuf; use rustc_ast::token::Token; use rustc_ast::util::parser::ExprPrecedence; +use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; use rustc_ast::{Path, Visibility}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, - Level, Subdiagnostic, SuggestionStyle, + Level, LintDiagnostic, Subdiagnostic, SuggestionStyle, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; -use rustc_span::{Ident, Span, Symbol}; +use rustc_span::{BytePos, Ident, Span, Symbol}; use crate::fluent_generated as fluent; use crate::parser::{ForbiddenLetReason, TokenDescription}; @@ -2323,31 +2324,36 @@ pub(crate) enum UnknownPrefixSugg { } #[derive(Diagnostic)] -#[diag(parse_reserved_multihash)] -#[note] -pub(crate) struct ReservedMultihash { - #[primary_span] - pub span: Span, - #[subdiagnostic] - pub sugg: Option, +pub(crate) enum ReservedHashPrefixedToken { + #[diag(parse_reserved_guarded_string)] + String { + #[primary_span] + span: Span, + #[suggestion(code = " ", applicability = "maybe-incorrect", style = "verbose")] + sugg: Option, + }, + #[diag(parse_reserved_multihash)] + Hash { + #[primary_span] + span: Span, + #[suggestion(code = " ", applicability = "maybe-incorrect", style = "verbose")] + sugg: Option, + }, } -#[derive(Diagnostic)] -#[diag(parse_reserved_string)] -#[note] -pub(crate) struct ReservedString { - #[primary_span] - pub span: Span, - #[subdiagnostic] - pub sugg: Option, + +#[derive(LintDiagnostic)] +pub(crate) enum ReservedHashPrefixedTokenLint { + #[diag(parse_reserved_guarded_string_lint)] + String { + #[suggestion(code = " ", applicability = "machine-applicable")] + sugg: Span, + }, + #[diag(parse_reserved_multihash_lint)] + Hash { + #[suggestion(code = " ", applicability = "machine-applicable")] + sugg: Span, + }, } -#[derive(Subdiagnostic)] -#[suggestion( - parse_suggestion_whitespace, - code = " ", - applicability = "maybe-incorrect", - style = "verbose" -)] -pub(crate) struct GuardedStringSugg(#[primary_span] pub Span); #[derive(Diagnostic)] #[diag(parse_too_many_hashes)] @@ -3671,3 +3677,76 @@ pub(crate) struct VarargsWithoutPattern { #[suggestion(code = "_: ...", applicability = "machine-applicable")] pub span: Span, } + +#[derive(LintDiagnostic)] +#[diag(parse_raw_prefix)] +pub(crate) struct RawPrefix { + #[label] + pub label: Span, + #[suggestion(code = " ", applicability = "machine-applicable")] + pub suggestion: Span, +} + +#[derive(LintDiagnostic)] +#[diag(parse_reserved_prefix)] +pub(crate) struct ReservedPrefix { + #[label] + pub label: Span, + #[suggestion(code = " ", applicability = "machine-applicable")] + pub suggestion: Span, + pub prefix: String, +} + +#[derive(LintDiagnostic)] +#[diag(parse_break_with_label_and_loop)] +pub(crate) struct BreakWithLabelAndLoop { + #[subdiagnostic] + pub sub: BreakWithLabelAndLoopSub, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +pub(crate) struct BreakWithLabelAndLoopSub { + #[suggestion_part(code = "(")] + pub left: Span, + #[suggestion_part(code = ")")] + pub right: Span, +} + +pub(crate) struct UnicodeTextFlow { + pub comment_span: Span, + pub content: String, +} + +impl<'a> LintDiagnostic<'a, ()> for UnicodeTextFlow { + fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { + diag.primary_message(fluent::parse_unicode_text_flow); + diag.note(fluent::parse_note); + diag.span_label(self.comment_span, fluent::parse_label); + + let spans: Vec<_> = self + .content + .char_indices() + .filter(|(_, c)| TEXT_FLOW_CONTROL_CHARS.contains(c)) + .map(|(i, c)| { + let lo = self.comment_span.lo() + BytePos(2 + i as u32); + (c, self.comment_span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32))) + }) + .collect(); + + for &(c, span) in &spans { + diag.span_label(span, format!("{c:?}")); + } + + if !spans.is_empty() { + diag.multipart_suggestion_with_style( + fluent::parse_suggestion, + spans.iter().map(|&(_, span)| (span, String::new())).collect(), + Applicability::MachineApplicable, + SuggestionStyle::HideCodeAlways, + ); + } + + diag.arg("num_codepoints", spans.len()); + } +} diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 94ae35c195821..71437a66096da 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -9,7 +9,6 @@ use rustc_lexer::{ Base, Cursor, DocStyle, FrontmatterAllowed, LiteralKind, RawStrError, is_horizontal_whitespace, }; use rustc_literal_escaper::{EscapeError, Mode, check_for_errors}; -use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{ RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX, TEXT_DIRECTION_CODEPOINT_IN_COMMENT, TEXT_DIRECTION_CODEPOINT_IN_LITERAL, @@ -384,7 +383,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, prefix_span, ast::CRATE_NODE_ID, - BuiltinLintDiag::RawPrefix(prefix_span), + errors::RawPrefix { label: prefix_span, suggestion: prefix_span.shrink_to_hi() }, ); // Reset the state so we just lex the `'r`. @@ -497,7 +496,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { TEXT_DIRECTION_CODEPOINT_IN_COMMENT, span, ast::CRATE_NODE_ID, - BuiltinLintDiag::UnicodeTextFlow(span, content.to_string()), + errors::UnicodeTextFlow { comment_span: span, content: content.to_string() }, ); } } @@ -1025,7 +1024,11 @@ impl<'psess, 'src> Lexer<'psess, 'src> { RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, prefix_span, ast::CRATE_NODE_ID, - BuiltinLintDiag::ReservedPrefix(prefix_span, prefix.to_string()), + errors::ReservedPrefix { + label: prefix_span, + suggestion: prefix_span.shrink_to_hi(), + prefix: prefix.to_owned(), + }, ); } } @@ -1079,21 +1082,17 @@ impl<'psess, 'src> Lexer<'psess, 'src> { .emit() } - let sugg = if span.from_expansion() { - None - } else { - Some(errors::GuardedStringSugg(space_span)) - }; + let sugg = if span.from_expansion() { None } else { Some(space_span) }; // In Edition 2024 and later, emit a hard error. - let err = if is_string { - self.dcx().emit_err(errors::ReservedString { span, sugg }) + let guar = self.dcx().emit_err(if is_string { + errors::ReservedHashPrefixedToken::String { span, sugg } } else { - self.dcx().emit_err(errors::ReservedMultihash { span, sugg }) - }; + errors::ReservedHashPrefixedToken::Hash { span, sugg } + }); token::Literal(token::Lit { - kind: token::Err(err), + kind: token::Err(guar), symbol: self.symbol_from_to(start, self.pos), suffix: None, }) @@ -1103,7 +1102,11 @@ impl<'psess, 'src> Lexer<'psess, 'src> { RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX, span, ast::CRATE_NODE_ID, - BuiltinLintDiag::ReservedString { is_string, suggestion: space_span }, + if is_string { + errors::ReservedHashPrefixedTokenLint::String { sugg: space_span } + } else { + errors::ReservedHashPrefixedTokenLint::Hash { sugg: space_span } + }, ); // For backwards compatibility, roll back to after just the first `#` diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 3f0853a3c54df..9b6fdf69b0df9 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -23,7 +23,6 @@ use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic}; use rustc_literal_escaper::unescape_char; use rustc_macros::Subdiagnostic; use rustc_session::errors::{ExprParenthesesNeeded, report_lit_error}; -use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; use rustc_span::edition::Edition; use rustc_span::source_map::{self, Spanned}; @@ -1930,7 +1929,12 @@ impl<'a> Parser<'a> { BREAK_WITH_LABEL_AND_LOOP, lo.to(expr.span), ast::CRATE_NODE_ID, - BuiltinLintDiag::BreakWithLabelAndLoop(expr.span), + errors::BreakWithLabelAndLoop { + sub: errors::BreakWithLabelAndLoopSub { + left: expr.span.shrink_to_lo(), + right: expr.span.shrink_to_hi(), + }, + }, ); } diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 4a980b2bd747d..10f73f8f80f60 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -8,6 +8,10 @@ resolve_add_as_non_derive = resolve_added_macro_use = have you added the `#[macro_use]` on the module/import? +resolve_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 + resolve_ancestor_only = visibilities can only be restricted to ancestor modules @@ -17,6 +21,13 @@ resolve_anonymous_lifetime_non_gat_report_error = missing lifetime in associated resolve_arguments_macro_use_not_allowed = arguments to `macro_use` are not allowed here +resolve_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 + .note = cannot automatically infer `'static` because of other lifetimes in scope + resolve_associated_const_with_similar_name_exists = there is an associated constant with a similar name @@ -197,6 +208,10 @@ resolve_generic_params_from_outer_item_static = a `static` is a separate item fr resolve_generic_params_from_outer_item_ty_param = type parameter from outer item +resolve_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 + resolve_ident_bound_more_than_once_in_parameter_list = identifier `{$identifier}` is bound more than once in this parameter list .label = used as parameter more than once @@ -490,6 +505,9 @@ resolve_unknown_diagnostic_attribute_typo_sugg = an attribute with a similar nam resolve_unnamed_crate_root_import = crate root imports need to be explicitly named: `use crate as name;` +resolve_unnecessary_qualification = unnecessary qualification + .suggestion = remove the unnecessary path segments + resolve_unreachable_label = use of unreachable label `{$name}` .label = unreachable label `{$name}` diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 5349cf6d7dbe7..ed838e91f7e8b 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -554,7 +554,7 @@ impl Resolver<'_, '_> { UNUSED_QUALIFICATIONS, unn_qua.node_id, unn_qua.path_span, - BuiltinLintDiag::UnusedQualifications { removal_span: unn_qua.removal_span }, + crate::errors::UnusedQualifications { removal_span: unn_qua.removal_span }, ); } diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index af58d88ec35f2..6649c636b1298 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1486,3 +1486,45 @@ impl<'a> LintDiagnostic<'a, ()> for Ambiguity { self.decorate(diag); } } + +#[derive(LintDiagnostic)] +#[diag(resolve_unnecessary_qualification)] +pub(crate) struct UnusedQualifications { + #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] + pub removal_span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(resolve_associated_const_elided_lifetime)] +pub(crate) struct AssociatedConstElidedLifetime { + #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")] + pub span: Span, + pub code: &'static str, + pub elided: bool, + #[note] + pub lifetimes_in_scope: MultiSpan, +} + +#[derive(LintDiagnostic)] +#[diag(resolve_ambiguous_glob_reexport)] +pub(crate) struct AmbiguousGlobReexports { + #[label(resolve_label_first_reexport)] + pub first_reexport: Span, + #[label(resolve_label_duplicate_reexport)] + pub duplicate_reexport: Span, + pub name: String, + // FIXME: make this translatable + pub namespace: &'static str, +} + +#[derive(LintDiagnostic)] +#[diag(resolve_hidden_glob_reexport)] +pub(crate) struct HiddenGlobReexports { + #[note(resolve_note_glob_reexport)] + pub glob_reexport: Span, + #[note(resolve_note_private_item)] + pub private_item: Span, + pub name: Symbol, + // FIXME: make this translatable + pub namespace: &'static str, +} diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 4e0f3db59821f..250104076c07d 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -666,11 +666,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { AMBIGUOUS_GLOB_REEXPORTS, import.root_id, import.root_span, - BuiltinLintDiag::AmbiguousGlobReexports { + crate::errors::AmbiguousGlobReexports { + first_reexport: import.root_span, + duplicate_reexport: amb_binding.span, name: key.ident.to_string(), - namespace: key.ns.descr().to_string(), - first_reexport_span: import.root_span, - duplicate_reexport_span: amb_binding.span, + namespace: key.ns.descr(), }, ); } @@ -699,11 +699,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { HIDDEN_GLOB_REEXPORTS, binding_id, binding.span, - BuiltinLintDiag::HiddenGlobReexports { - name: key.ident.name.to_string(), - namespace: key.ns.descr().to_owned(), - glob_reexport_span: glob_binding.span, - private_item_span: binding.span, + crate::errors::HiddenGlobReexports { + glob_reexport: glob_binding.span, + private_item: binding.span, + name: key.ident.name, + namespace: key.ns.descr(), }, ); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5a4fbad6aaf88..9a0222f6651c5 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1852,13 +1852,15 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); return; } else if emit_lint { + let span = lifetime.ident.span; self.r.lint_buffer.buffer_lint( lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, node_id, - lifetime.ident.span, - lint::BuiltinLintDiag::AssociatedConstElidedLifetime { + span, + errors::AssociatedConstElidedLifetime { + span: if elided { span.shrink_to_hi() } else { span }, elided, - span: lifetime.ident.span, + code: if elided { "'static " } else { "'static" }, lifetimes_in_scope: lifetimes_in_scope.into(), }, ); diff --git a/tests/ui/pattern/no-patterns-in-args-2.stderr b/tests/ui/pattern/no-patterns-in-args-2.stderr index 3990f23038714..9a74936295b89 100644 --- a/tests/ui/pattern/no-patterns-in-args-2.stderr +++ b/tests/ui/pattern/no-patterns-in-args-2.stderr @@ -8,7 +8,9 @@ error: patterns aren't allowed in functions without bodies --> $DIR/no-patterns-in-args-2.rs:5:11 | LL | fn f1(mut arg: u8); - | ^^^^^^^ help: remove `mut` from the parameter: `arg` + | ----^^^ + | | + | help: remove `mut` from the parameter | = 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 #35203