From 5a90537b62573721c42a83c024d3d7ad031b758b Mon Sep 17 00:00:00 2001 From: Rejyr Date: Sun, 28 Aug 2022 13:37:00 -0400 Subject: [PATCH 01/33] add: `lints.rs` add: `lints.rs` refactor: move `InvalidAtomicOrderingDiag` to `lints.rs` --- compiler/rustc_lint/src/lib.rs | 3 +++ compiler/rustc_lint/src/lints.rs | 11 +++++++++++ compiler/rustc_lint/src/types.rs | 11 +---------- 3 files changed, 15 insertions(+), 10 deletions(-) create mode 100644 compiler/rustc_lint/src/lints.rs diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 1275d6f223c7a..afcf8b54322f6 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -38,6 +38,8 @@ #![feature(never_type)] #![feature(rustc_attrs)] #![recursion_limit = "256"] +// #![deny(rustc::untranslatable_diagnostic)] +// #![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; @@ -60,6 +62,7 @@ mod internal; mod late; mod let_underscore; mod levels; +mod lints; mod methods; mod non_ascii_idents; mod non_fmt_panic; diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs new file mode 100644 index 0000000000000..1dc23ad9e921b --- /dev/null +++ b/compiler/rustc_lint/src/lints.rs @@ -0,0 +1,11 @@ +use rustc_macros::LintDiagnostic; +use rustc_span::{Symbol, Span}; + +#[derive(LintDiagnostic)] +#[diag(lint_atomic_ordering_invalid)] +#[help] +pub struct InvalidAtomicOrderingDiag { + pub method: Symbol, + #[label] + pub fail_order_arg_span: Span, +} diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index fa415243ba066..7f3a501aeb0d1 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1,3 +1,4 @@ +use crate::lints::InvalidAtomicOrderingDiag; use crate::{LateContext, LateLintPass, LintContext}; use rustc_ast as ast; use rustc_attr as attr; @@ -5,7 +6,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::{fluent, Applicability, DiagnosticMessage}; use rustc_hir as hir; use rustc_hir::{is_range_literal, Expr, ExprKind, Node}; -use rustc_macros::LintDiagnostic; use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable}; @@ -1550,15 +1550,6 @@ impl InvalidAtomicOrdering { let Some(fail_ordering) = Self::match_ordering(cx, fail_order_arg) else { return }; if matches!(fail_ordering, sym::Release | sym::AcqRel) { - #[derive(LintDiagnostic)] - #[diag(lint_atomic_ordering_invalid)] - #[help] - struct InvalidAtomicOrderingDiag { - method: Symbol, - #[label] - fail_order_arg_span: Span, - } - cx.emit_spanned_lint( INVALID_ATOMIC_ORDERING, fail_order_arg.span, From d44ccaa56f2ddebfe5794330876325d3b6b83869 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Sun, 28 Aug 2022 19:07:58 -0400 Subject: [PATCH 02/33] migrate: `types.rs` --- compiler/rustc_lint/src/lints.rs | 141 ++++++++++++++++- compiler/rustc_lint/src/types.rs | 261 +++++++++++++------------------ 2 files changed, 248 insertions(+), 154 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 1dc23ad9e921b..ce93616da131e 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1,5 +1,142 @@ -use rustc_macros::LintDiagnostic; -use rustc_span::{Symbol, Span}; +use rustc_errors::{fluent, AddSubdiagnostic, DecorateLint, EmissionGuarantee}; +use rustc_macros::{LintDiagnostic, SessionSubdiagnostic}; +use rustc_span::{Span, Symbol}; + +#[derive(LintDiagnostic)] +#[diag(lint_range_endpoint_out_of_range)] +pub struct RangeEndpointOutOfRange<'a> { + pub ty: &'a str, + #[suggestion(code = "{start}..={literal}{suffix}", applicability = "machine-applicable")] + pub suggestion: Span, + pub start: String, + pub literal: u128, + pub suffix: &'a str, +} + +#[derive(LintDiagnostic)] +#[diag(lint_overflowing_bin_hex)] +pub struct OverflowingBinHex<'a> { + pub ty: &'a str, + pub lit: String, + pub dec: u128, + pub actually: String, + #[subdiagnostic] + pub sign: OverflowingBinHexSign, + #[subdiagnostic] + pub sub: Option>, +} + +pub enum OverflowingBinHexSign { + Positive, + Negative, +} + +impl AddSubdiagnostic for OverflowingBinHexSign { + fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + match self { + OverflowingBinHexSign::Positive => { + diag.note(fluent::positive_note); + } + OverflowingBinHexSign::Negative => { + diag.note(fluent::negative_note); + diag.note(fluent::negative_becomes_note); + } + } + } +} + +#[derive(SessionSubdiagnostic)] +pub enum OverflowingBinHexSub<'a> { + #[suggestion( + suggestion, + code = "{sans_suffix}{suggestion_ty}", + applicability = "machine-applicable" + )] + Suggestion { + #[primary_span] + span: Span, + suggestion_ty: &'a str, + sans_suffix: &'a str, + }, + #[help(help)] + Help { suggestion_ty: &'a str }, +} + +pub struct OverflowingInt<'a> { + pub ty: &'a str, + pub lit: String, + pub min: i128, + pub max: u128, + pub suggestion_ty: Option<&'a str>, +} + +// FIXME: refactor with `Option<&'a str>` in macro +impl<'a, G: EmissionGuarantee> DecorateLint<'_, G> for OverflowingInt<'a> { + fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) { + let mut diag = diag.build(fluent::lint_overflowing_int); + diag.set_arg("ty", self.ty); + diag.set_arg("lit", self.lit); + diag.set_arg("min", self.min); + diag.set_arg("max", self.max); + diag.note(fluent::note); + if let Some(suggestion_ty) = self.suggestion_ty { + diag.set_arg("suggestion_ty", suggestion_ty); + diag.help(fluent::help); + } + diag.emit(); + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_only_cast_u8_to_char)] +pub struct OnlyCastu8ToChar { + #[suggestion(code = "'\\u{{{literal:X}}}'", applicability = "machine-applicable")] + pub span: Span, + pub literal: u128, +} + +#[derive(LintDiagnostic)] +#[diag(lint_overflowing_uint)] +#[note] +pub struct OverflowingUInt<'a> { + pub ty: &'a str, + pub lit: String, + pub min: u128, + pub max: u128, +} + +#[derive(LintDiagnostic)] +#[diag(lint_overflowing_literal)] +#[note] +pub struct OverflowingLiteral<'a> { + pub ty: &'a str, + pub lit: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_comparisons)] +pub struct UnusedComparisons; + +#[derive(LintDiagnostic)] +#[diag(lint_variant_size_differences)] +pub struct VariantSizeDifferencesDiag { + pub largest: u64, +} + +#[derive(LintDiagnostic)] +#[diag(lint_atomic_ordering_load)] +#[help] +pub struct AtomicOrderingLoad; + +#[derive(LintDiagnostic)] +#[diag(lint_atomic_ordering_store)] +#[help] +pub struct AtomicOrderingStore; + +#[derive(LintDiagnostic)] +#[diag(lint_atomic_ordering_fence)] +#[help] +pub struct AtomicOrderingFence; #[derive(LintDiagnostic)] #[diag(lint_atomic_ordering_invalid)] diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 7f3a501aeb0d1..46e957d15931a 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1,9 +1,16 @@ -use crate::lints::InvalidAtomicOrderingDiag; +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +use crate::lints::{ + AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, InvalidAtomicOrderingDiag, + OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSub, + OverflowingInt, OverflowingLiteral, OverflowingUInt, RangeEndpointOutOfRange, + UnusedComparisons, VariantSizeDifferencesDiag, +}; use crate::{LateContext, LateLintPass, LintContext}; use rustc_ast as ast; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{fluent, Applicability, DiagnosticMessage}; +use rustc_errors::{fluent, DiagnosticMessage}; use rustc_hir as hir; use rustc_hir::{is_range_literal, Expr, ExprKind, Node}; use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton}; @@ -146,32 +153,22 @@ fn lint_overflowing_range_endpoint<'tcx>( }; let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) else { return false }; - cx.struct_span_lint( + use rustc_ast::{LitIntType, LitKind}; + let suffix = match lit.node { + LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(), + LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(), + LitKind::Int(_, LitIntType::Unsuffixed) => "", + _ => bug!(), + }; + cx.emit_spanned_lint( OVERFLOWING_LITERALS, struct_expr.span, - fluent::lint_range_endpoint_out_of_range, - |lint| { - use ast::{LitIntType, LitKind}; - - lint.set_arg("ty", ty); - - // We need to preserve the literal's suffix, - // as it may determine typing information. - let suffix = match lit.node { - LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(), - LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(), - LitKind::Int(_, LitIntType::Unsuffixed) => "", - _ => bug!(), - }; - let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix); - lint.span_suggestion( - struct_expr.span, - fluent::suggestion, - suggestion, - Applicability::MachineApplicable, - ); - - lint + RangeEndpointOutOfRange { + ty, + suggestion: struct_expr.span, + start, + literal: lit_val - 1, + suffix, }, ); @@ -228,58 +225,37 @@ fn report_bin_hex_error( val: u128, negative: bool, ) { - cx.struct_span_lint( - OVERFLOWING_LITERALS, - expr.span, - fluent::lint_overflowing_bin_hex, - |lint| { - let (t, actually) = match ty { - attr::IntType::SignedInt(t) => { - let actually = if negative { - -(size.sign_extend(val) as i128) - } else { - size.sign_extend(val) as i128 - }; - (t.name_str(), actually.to_string()) - } - attr::IntType::UnsignedInt(t) => { - let actually = size.truncate(val); - (t.name_str(), actually.to_string()) - } + let (t, actually) = match ty { + attr::IntType::SignedInt(t) => { + let actually = if negative { + -(size.sign_extend(val) as i128) + } else { + size.sign_extend(val) as i128 }; - - if negative { - // If the value is negative, - // emits a note about the value itself, apart from the literal. - lint.note(fluent::negative_note); - lint.note(fluent::negative_becomes_note); + (t.name_str(), actually.to_string()) + } + attr::IntType::UnsignedInt(t) => { + let actually = size.truncate(val); + (t.name_str(), actually.to_string()) + } + }; + let sign = + if negative { OverflowingBinHexSign::Negative } else { OverflowingBinHexSign::Positive }; + let sub = get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative).map( + |suggestion_ty| { + if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') { + let (sans_suffix, _) = repr_str.split_at(pos); + OverflowingBinHexSub::Suggestion { span: expr.span, suggestion_ty, sans_suffix } } else { - lint.note(fluent::positive_note); + OverflowingBinHexSub::Help { suggestion_ty } } - if let Some(sugg_ty) = - get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative) - { - lint.set_arg("suggestion_ty", sugg_ty); - if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') { - let (sans_suffix, _) = repr_str.split_at(pos); - lint.span_suggestion( - expr.span, - fluent::suggestion, - format!("{}{}", sans_suffix, sugg_ty), - Applicability::MachineApplicable, - ); - } else { - lint.help(fluent::help); - } - } - lint.set_arg("ty", t) - .set_arg("lit", repr_str) - .set_arg("dec", val) - .set_arg("actually", actually); - - lint }, ); + cx.emit_spanned_lint( + OVERFLOWING_LITERALS, + expr.span, + OverflowingBinHex { ty: t, lit: repr_str.clone(), dec: val, actually, sign, sub }, + ) } // This function finds the next fitting type and generates a suggestion string. @@ -363,28 +339,25 @@ fn lint_int_literal<'tcx>( return; } - cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, fluent::lint_overflowing_int, |lint| { - lint.set_arg("ty", t.name_str()) - .set_arg( - "lit", - cx.sess() - .source_map() - .span_to_snippet(lit.span) - .expect("must get snippet from literal"), - ) - .set_arg("min", min) - .set_arg("max", max) - .note(fluent::note); - - if let Some(sugg_ty) = - get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative) - { - lint.set_arg("suggestion_ty", sugg_ty); - lint.help(fluent::help); - } - - lint - }); + cx.emit_spanned_lint( + OVERFLOWING_LITERALS, + e.span, + OverflowingInt { + ty: t.name_str(), + lit: cx + .sess() + .source_map() + .span_to_snippet(lit.span) + .expect("must get snippet from literal"), + min, + max, + suggestion_ty: get_type_suggestion( + cx.typeck_results().node_type(e.hir_id), + v, + negative, + ), + }, + ); } } @@ -408,18 +381,10 @@ fn lint_uint_literal<'tcx>( match par_e.kind { hir::ExprKind::Cast(..) => { if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() { - cx.struct_span_lint( + cx.emit_spanned_lint( OVERFLOWING_LITERALS, par_e.span, - fluent::lint_only_cast_u8_to_char, - |lint| { - lint.span_suggestion( - par_e.span, - fluent::suggestion, - format!("'\\u{{{:X}}}'", lit_val), - Applicability::MachineApplicable, - ) - }, + OnlyCastu8ToChar { span: par_e.span, literal: lit_val }, ); return; } @@ -443,19 +408,20 @@ fn lint_uint_literal<'tcx>( ); return; } - cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, fluent::lint_overflowing_uint, |lint| { - lint.set_arg("ty", t.name_str()) - .set_arg( - "lit", - cx.sess() - .source_map() - .span_to_snippet(lit.span) - .expect("must get snippet from literal"), - ) - .set_arg("min", min) - .set_arg("max", max) - .note(fluent::note) - }); + cx.emit_spanned_lint( + OVERFLOWING_LITERALS, + e.span, + OverflowingUInt { + ty: t.name_str(), + lit: cx + .sess() + .source_map() + .span_to_snippet(lit.span) + .expect("must get snippet from literal"), + min, + max, + }, + ); } } @@ -484,20 +450,16 @@ fn lint_literal<'tcx>( _ => bug!(), }; if is_infinite == Ok(true) { - cx.struct_span_lint( + cx.emit_spanned_lint( OVERFLOWING_LITERALS, e.span, - fluent::lint_overflowing_literal, - |lint| { - lint.set_arg("ty", t.name_str()) - .set_arg( - "lit", - cx.sess() - .source_map() - .span_to_snippet(lit.span) - .expect("must get snippet from literal"), - ) - .note(fluent::note) + OverflowingLiteral { + ty: t.name_str(), + lit: cx + .sess() + .source_map() + .span_to_snippet(lit.span) + .expect("must get snippet from literal"), }, ); } @@ -517,12 +479,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { } hir::ExprKind::Binary(binop, ref l, ref r) => { if is_comparison(binop) && !check_limits(cx, binop, &l, &r) { - cx.struct_span_lint( - UNUSED_COMPARISONS, - e.span, - fluent::lint_unused_comparisons, - |lint| lint, - ); + cx.emit_spanned_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons); } } hir::ExprKind::Lit(ref lit) => lint_literal(cx, self, e, lit), @@ -1180,9 +1137,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { CItemKind::Declaration => "block", CItemKind::Definition => "fn", }; - lint.set_arg("ty", ty); - lint.set_arg("desc", item_description); - lint.span_label(sp, fluent::label); + #[allow(rustc::diagnostic_outside_of_impl)] + let mut diag = lint.build(fluent::lint_improper_ctypes); + diag.set_arg("ty", ty); + diag.set_arg("desc", item_description); + diag.span_label(sp, fluent::label); if let Some(help) = help { lint.help(help); } @@ -1397,11 +1356,10 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences { // We only warn if the largest variant is at least thrice as large as // the second-largest. if largest > slargest * 3 && slargest > 0 { - cx.struct_span_lint( + cx.emit_spanned_lint( VARIANT_SIZE_DIFFERENCES, enum_definition.variants[largest_index].span, - fluent::lint_variant_size_differences, - |lint| lint.set_arg("largest", largest), + VariantSizeDifferencesDiag { largest }, ); } } @@ -1509,17 +1467,19 @@ impl InvalidAtomicOrdering { fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) { if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::load, sym::store]) - && let Some((ordering_arg, invalid_ordering, msg)) = match method { - sym::load => Some((&args[0], sym::Release, fluent::lint_atomic_ordering_load)), - sym::store => Some((&args[1], sym::Acquire, fluent::lint_atomic_ordering_store)), + && let Some((ordering_arg, invalid_ordering)) = match method { + sym::load => Some((&args[0], sym::Release)), + sym::store => Some((&args[1], sym::Acquire)), _ => None, } && let Some(ordering) = Self::match_ordering(cx, ordering_arg) && (ordering == invalid_ordering || ordering == sym::AcqRel) { - cx.struct_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, msg, |lint| { - lint.help(fluent::help) - }); + if method == sym::load { + cx.emit_spanned_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, AtomicOrderingLoad); + } else { + cx.emit_spanned_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, AtomicOrderingStore); + }; } } @@ -1530,10 +1490,7 @@ impl InvalidAtomicOrdering { && matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::fence | sym::compiler_fence)) && Self::match_ordering(cx, &args[0]) == Some(sym::Relaxed) { - cx.struct_span_lint(INVALID_ATOMIC_ORDERING, args[0].span, fluent::lint_atomic_ordering_fence, |lint| { - lint - .help(fluent::help) - }); + cx.emit_spanned_lint(INVALID_ATOMIC_ORDERING, args[0].span, AtomicOrderingFence); } } From e5ae9d019c263a37b1d47fab91b057ec9b8d7c45 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Sun, 4 Sep 2022 15:46:35 -0400 Subject: [PATCH 03/33] migrate: `unused.rs` --- compiler/rustc_lint/src/lints.rs | 133 ++++++++++++++++++++++- compiler/rustc_lint/src/unused.rs | 171 ++++++++++++------------------ 2 files changed, 201 insertions(+), 103 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index ce93616da131e..c68bfc98f9351 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1,7 +1,11 @@ -use rustc_errors::{fluent, AddSubdiagnostic, DecorateLint, EmissionGuarantee}; +use rustc_errors::{fluent, AddSubdiagnostic, Applicability, DecorateLint, EmissionGuarantee}; +use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, SessionSubdiagnostic}; +use rustc_middle::ty::Ty; use rustc_span::{Span, Symbol}; +use crate::LateContext; + #[derive(LintDiagnostic)] #[diag(lint_range_endpoint_out_of_range)] pub struct RangeEndpointOutOfRange<'a> { @@ -146,3 +150,130 @@ pub struct InvalidAtomicOrderingDiag { #[label] pub fail_order_arg_span: Span, } + +#[derive(LintDiagnostic)] +#[diag(lint_unused_op)] +pub struct UnusedOp<'a> { + pub op: &'a str, + #[label] + pub label: Span, + #[suggestion(style = "verbose", code = "let _ = ", applicability = "machine-applicable")] + pub suggestion: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_result)] +pub struct UnusedResult<'a> { + pub ty: Ty<'a>, +} + +// FIXME(davidtwco): this isn't properly translatable becauses of the +// pre/post strings +#[derive(LintDiagnostic)] +#[diag(lint_unused_closure)] +#[note] +pub struct UnusedClosure<'a> { + pub count: usize, + pub pre: &'a str, + pub post: &'a str, +} + +// FIXME(davidtwco): this isn't properly translatable becauses of the +// pre/post strings +#[derive(LintDiagnostic)] +#[diag(lint_unused_generator)] +#[note] +pub struct UnusedGenerator<'a> { + pub count: usize, + pub pre: &'a str, + pub post: &'a str, +} + +// FIXME(davidtwco): this isn't properly translatable becauses of the pre/post +// strings +pub struct UnusedDef<'a, 'b> { + pub pre: &'a str, + pub post: &'a str, + pub cx: &'a LateContext<'b>, + pub def_id: DefId, + pub note: Option, +} + +// FIXME: refactor with `Option` in macro +impl<'a, 'b, G: EmissionGuarantee> DecorateLint<'_, G> for UnusedDef<'a, 'b> { + fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) { + let mut diag = diag.build(fluent::lint_unused_def); + diag.set_arg("pre", self.pre); + diag.set_arg("post", self.post); + diag.set_arg("def", self.cx.tcx.def_path_str(self.def_id)); + // check for #[must_use = "..."] + if let Some(note) = self.note { + diag.note(note.as_str()); + } + diag.emit(); + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_path_statement_drop)] +pub struct PathStatementDrop { + #[subdiagnostic] + pub sub: PathStatementDropSub, +} + +#[derive(SessionSubdiagnostic)] +pub enum PathStatementDropSub { + #[suggestion( + suggestion, + code = "drop({snippet});", + applicability = "machine-applicable" + )] + Suggestion { + #[primary_span] + span: Span, + snippet: String, + }, + #[help(help)] + Help { + #[primary_span] + span: Span, + }, +} + +#[derive(LintDiagnostic)] +#[diag(lint_path_statement_no_effect)] +pub struct PathStatementNoEffect; + +#[derive(LintDiagnostic)] +#[diag(lint_unused_delim)] +pub struct UnusedDelim<'a> { + pub delim: &'static str, + pub item: &'a str, + #[subdiagnostic] + pub suggestion: Option, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(suggestion, applicability = "machine-applicable")] +pub struct UnusedDelimSuggestion { + #[suggestion_part(code = "{start_replace}")] + pub start_span: Span, + pub start_replace: &'static str, + #[suggestion_part(code = "{end_replace}")] + pub end_span: Span, + pub end_replace: &'static str, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_import_braces)] +pub struct UnusedImportBracesDiag { + pub node: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_allocation)] +pub struct UnusedAllocationDiag; + +#[derive(LintDiagnostic)] +#[diag(lint_unused_allocation_mut)] +pub struct UnusedAllocationMutDiag; diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 525079681ca5c..8c5f68d614461 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1,9 +1,16 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +use crate::lints::{ + PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag, + UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDelim, UnusedDelimSuggestion, + UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedResult, +}; use crate::Lint; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_ast as ast; use rustc_ast::util::{classify, parser}; use rustc_ast::{ExprKind, StmtKind}; -use rustc_errors::{fluent, pluralize, Applicability, MultiSpan}; +use rustc_errors::{pluralize, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; @@ -163,23 +170,20 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { let mut op_warned = false; if let Some(must_use_op) = must_use_op { - cx.struct_span_lint(UNUSED_MUST_USE, expr.span, fluent::lint_unused_op, |lint| { - lint.set_arg("op", must_use_op) - .span_label(expr.span, fluent::label) - .span_suggestion_verbose( - expr.span.shrink_to_lo(), - fluent::suggestion, - "let _ = ", - Applicability::MachineApplicable, - ) - }); + cx.emit_spanned_lint( + UNUSED_MUST_USE, + expr.span, + UnusedOp { + op: must_use_op, + label: expr.span, + suggestion: expr.span.shrink_to_lo(), + }, + ); op_warned = true; } if !(type_lint_emitted_or_suppressed || fn_warned || op_warned) { - cx.struct_span_lint(UNUSED_RESULTS, s.span, fluent::lint_unused_result, |lint| { - lint.set_arg("ty", ty) - }); + cx.emit_spanned_lint(UNUSED_RESULTS, s.span, UnusedResult { ty }); } fn check_fn_must_use(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { @@ -402,47 +406,31 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { ); } MustUsePath::Closure(span) => { - cx.struct_span_lint( + cx.emit_spanned_lint( UNUSED_MUST_USE, *span, - fluent::lint_unused_closure, - |lint| { - // FIXME(davidtwco): this isn't properly translatable because of the - // pre/post strings - lint.set_arg("count", plural_len) - .set_arg("pre", descr_pre) - .set_arg("post", descr_post) - .note(fluent::note) - }, + UnusedClosure { count: plural_len, pre: descr_pre, post: descr_post }, ); } MustUsePath::Generator(span) => { - cx.struct_span_lint( + cx.emit_spanned_lint( UNUSED_MUST_USE, *span, - fluent::lint_unused_generator, - |lint| { - // FIXME(davidtwco): this isn't properly translatable because of the - // pre/post strings - lint.set_arg("count", plural_len) - .set_arg("pre", descr_pre) - .set_arg("post", descr_post) - .note(fluent::note) - }, + UnusedGenerator { count: plural_len, pre: descr_pre, post: descr_post }, ); } MustUsePath::Def(span, def_id, reason) => { - cx.struct_span_lint(UNUSED_MUST_USE, *span, fluent::lint_unused_def, |lint| { - // FIXME(davidtwco): this isn't properly translatable because of the pre/post - // strings - lint.set_arg("pre", descr_pre); - lint.set_arg("post", descr_post); - lint.set_arg("def", cx.tcx.def_path_str(*def_id)); - if let Some(note) = reason { - lint.note(note.as_str()); - } - lint - }); + cx.emit_spanned_lint( + UNUSED_MUST_USE, + *span, + UnusedDef { + pre: descr_pre, + post: descr_post, + cx, + def_id: *def_id, + note: *reason, + }, + ); } } } @@ -478,31 +466,15 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements { if let hir::ExprKind::Path(_) = expr.kind { let ty = cx.typeck_results().expr_ty(expr); if ty.needs_drop(cx.tcx, cx.param_env) { - cx.struct_span_lint( - PATH_STATEMENTS, - s.span, - fluent::lint_path_statement_drop, - |lint| { - if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) { - lint.span_suggestion( - s.span, - fluent::suggestion, - format!("drop({});", snippet), - Applicability::MachineApplicable, - ); - } else { - lint.span_help(s.span, fluent::suggestion); - } - lint - }, - ); + let sub = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) + { + PathStatementDropSub::Suggestion { span: s.span, snippet } + } else { + PathStatementDropSub::Help { span: s.span } + }; + cx.emit_spanned_lint(PATH_STATEMENTS, s.span, PathStatementDrop { sub }) } else { - cx.struct_span_lint( - PATH_STATEMENTS, - s.span, - fluent::lint_path_statement_no_effect, - |lint| lint, - ); + cx.emit_spanned_lint(PATH_STATEMENTS, s.span, PathStatementNoEffect); } } } @@ -695,36 +667,35 @@ trait UnusedDelimLint { } else { MultiSpan::from(value_span) }; - cx.struct_span_lint(self.lint(), primary_span, fluent::lint_unused_delim, |lint| { - lint.set_arg("delim", Self::DELIM_STR); - lint.set_arg("item", msg); - if let Some((lo, hi)) = spans { - let sm = cx.sess().source_map(); - let lo_replace = + let suggestion = spans.map(|(lo, hi)| { + let sm = cx.sess().source_map(); + let lo_replace = if keep_space.0 && let Ok(snip) = sm.span_to_prev_source(lo) && !snip.ends_with(' ') { - " ".to_string() + " " } else { - "".to_string() + "" }; - let hi_replace = + let hi_replace = if keep_space.1 && let Ok(snip) = sm.span_to_next_source(hi) && !snip.starts_with(' ') { - " ".to_string() + " " } else { - "".to_string() + "" }; - - let replacement = vec![(lo, lo_replace), (hi, hi_replace)]; - lint.multipart_suggestion( - fluent::suggestion, - replacement, - Applicability::MachineApplicable, - ); + UnusedDelimSuggestion { + start_span: lo, + start_replace: lo_replace, + end_span: hi, + end_replace: hi_replace, } - lint }); + cx.emit_spanned_lint( + self.lint(), + primary_span, + UnusedDelim { delim: Self::DELIM_STR, item: msg, suggestion }, + ); } fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { @@ -1297,11 +1268,10 @@ impl UnusedImportBraces { ast::UseTreeKind::Nested(_) => return, }; - cx.struct_span_lint( + cx.emit_spanned_lint( UNUSED_IMPORT_BRACES, item.span, - fluent::lint_unused_import_braces, - |lint| lint.set_arg("node", node_name), + UnusedImportBracesDiag { node: node_name }, ); } } @@ -1351,17 +1321,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation { for adj in cx.typeck_results().expr_adjustments(e) { if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind { - cx.struct_span_lint( - UNUSED_ALLOCATION, - e.span, - match m { - adjustment::AutoBorrowMutability::Not => fluent::lint_unused_allocation, - adjustment::AutoBorrowMutability::Mut { .. } => { - fluent::lint_unused_allocation_mut - } - }, - |lint| lint, - ); + match m { + adjustment::AutoBorrowMutability::Not => { + cx.emit_spanned_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationDiag); + } + adjustment::AutoBorrowMutability::Mut { .. } => { + cx.emit_spanned_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationMutDiag); + } + }; } } } From a42afa0444118ae5549f89e8ea9a15b73702fbcf Mon Sep 17 00:00:00 2001 From: Rejyr Date: Mon, 5 Sep 2022 11:52:08 -0400 Subject: [PATCH 04/33] migrate: `traits.rs` --- compiler/rustc_lint/src/lints.rs | 30 +++++++++++++++++++++++++++++- compiler/rustc_lint/src/traits.rs | 27 ++++++++++++--------------- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index c68bfc98f9351..691cc8667e33a 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1,11 +1,39 @@ use rustc_errors::{fluent, AddSubdiagnostic, Applicability, DecorateLint, EmissionGuarantee}; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, SessionSubdiagnostic}; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{Predicate, Ty, TyCtxt}; use rustc_span::{Span, Symbol}; use crate::LateContext; +pub struct DropTraitConstraintsDiag<'a> { + pub predicate: Predicate<'a>, + pub tcx: TyCtxt<'a>, + pub def_id: DefId, +} + +impl<'a, G: EmissionGuarantee> DecorateLint<'_, G> for DropTraitConstraintsDiag<'a> { + fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) { + let mut diag = diag.build(fluent::lint_drop_trait_constraints); + diag.set_arg("predicate", self.predicate); + diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id)); + diag.emit(); + } +} + +pub struct DropGlue<'a> { + pub tcx: TyCtxt<'a>, + pub def_id: DefId, +} + +impl<'a, G: EmissionGuarantee> DecorateLint<'_, G> for DropGlue<'a> { + fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) { + let mut diag = diag.build(fluent::lint_drop_glue); + diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id)); + diag.emit(); + } +} + #[derive(LintDiagnostic)] #[diag(lint_range_endpoint_out_of_range)] pub struct RangeEndpointOutOfRange<'a> { diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index 1b21c2dac3788..2e778cf0d0fe0 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -1,7 +1,9 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +use crate::lints::{DropGlue, DropTraitConstraintsDiag}; use crate::LateContext; use crate::LateLintPass; use crate::LintContext; -use rustc_errors::fluent; use rustc_hir as hir; use rustc_span::symbol::sym; @@ -101,17 +103,13 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { if trait_predicate.trait_ref.self_ty().is_impl_trait() { continue; } - let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { - continue; + let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { + return }; - cx.struct_span_lint( + cx.emit_spanned_lint( DROP_BOUNDS, span, - fluent::lint_drop_trait_constraints, - |lint| { - lint.set_arg("predicate", predicate) - .set_arg("needs_drop", cx.tcx.def_path_str(needs_drop)) - }, + DropTraitConstraintsDiag { predicate, tcx: cx.tcx, def_id }, ); } } @@ -123,12 +121,11 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { }; for bound in &bounds[..] { let def_id = bound.trait_ref.trait_def_id(); - if cx.tcx.lang_items().drop_trait() == def_id - && let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) - { - cx.struct_span_lint(DYN_DROP, bound.span, fluent::lint_drop_glue, |lint| { - lint.set_arg("needs_drop", cx.tcx.def_path_str(needs_drop)) - }); + if cx.tcx.lang_items().drop_trait() == def_id { + let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { + return + }; + cx.emit_spanned_lint(DYN_DROP, bound.span, DropGlue { tcx: cx.tcx, def_id }); } } } From c3a6801f8e5ce0aee0a62eb022780740ee61535d Mon Sep 17 00:00:00 2001 From: Rejyr Date: Mon, 5 Sep 2022 12:32:01 -0400 Subject: [PATCH 05/33] migrate: `redundant_semicolon.rs` --- compiler/rustc_lint/src/lints.rs | 8 ++++++++ compiler/rustc_lint/src/redundant_semicolon.rs | 17 +++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 691cc8667e33a..077ee3fb67159 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -6,6 +6,14 @@ use rustc_span::{Span, Symbol}; use crate::LateContext; +#[derive(LintDiagnostic)] +#[diag(lint_redundant_semicolons)] +pub struct RedundantSemicolonsDiag { + pub multiple: bool, + #[suggestion(code = "", applicability = "maybe-incorrect")] + pub suggestion: Span, +} + pub struct DropTraitConstraintsDiag<'a> { pub predicate: Predicate<'a>, pub tcx: TyCtxt<'a>, diff --git a/compiler/rustc_lint/src/redundant_semicolon.rs b/compiler/rustc_lint/src/redundant_semicolon.rs index 3521de7fc0848..6c6add34a520c 100644 --- a/compiler/rustc_lint/src/redundant_semicolon.rs +++ b/compiler/rustc_lint/src/redundant_semicolon.rs @@ -1,6 +1,7 @@ -use crate::{EarlyContext, EarlyLintPass, LintContext}; +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +use crate::{lints::RedundantSemicolonsDiag, EarlyContext, EarlyLintPass, LintContext}; use rustc_ast::{Block, StmtKind}; -use rustc_errors::{fluent, Applicability}; use rustc_span::Span; declare_lint! { @@ -48,18 +49,10 @@ fn maybe_lint_redundant_semis(cx: &EarlyContext<'_>, seq: &mut Option<(Span, boo return; } - cx.struct_span_lint( + cx.emit_spanned_lint( REDUNDANT_SEMICOLONS, span, - fluent::lint_redundant_semicolons, - |lint| { - lint.set_arg("multiple", multiple).span_suggestion( - span, - fluent::suggestion, - "", - Applicability::MaybeIncorrect, - ) - }, + RedundantSemicolonsDiag { multiple, suggestion: span }, ); } } From 6fb3a38f9b27b328c6209147793602545d291b85 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Mon, 5 Sep 2022 12:38:55 -0400 Subject: [PATCH 06/33] migrate: `pass_by_value.rs` --- compiler/rustc_lint/src/lints.rs | 8 ++++++++ compiler/rustc_lint/src/pass_by_value.rs | 19 ++++++------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 077ee3fb67159..fd68af572ff99 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -6,6 +6,14 @@ use rustc_span::{Span, Symbol}; use crate::LateContext; +#[derive(LintDiagnostic)] +#[diag(lint_pass_by_value)] +pub struct PassByValueDiag { + pub ty: String, + #[suggestion(code = "{ty}", applicability = "maybe-incorrect")] + pub suggestion: Span, +} + #[derive(LintDiagnostic)] #[diag(lint_redundant_semicolons)] pub struct RedundantSemicolonsDiag { diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index 22caadfab177d..3df0fc385952d 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -1,5 +1,7 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +use crate::lints::PassByValueDiag; use crate::{LateContext, LateLintPass, LintContext}; -use rustc_errors::{fluent, Applicability}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::{GenericArg, PathSegment, QPath, TyKind}; @@ -29,20 +31,11 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue { } } if let Some(t) = path_for_pass_by_value(cx, &inner_ty) { - cx.struct_span_lint( + cx.emit_spanned_lint( PASS_BY_VALUE, ty.span, - fluent::lint_pass_by_value, - |lint| { - lint.set_arg("ty", t.clone()).span_suggestion( - ty.span, - fluent::suggestion, - t, - // Changing type of function argument - Applicability::MaybeIncorrect, - ) - }, - ) + PassByValueDiag { ty: t.clone(), suggestion: ty.span }, + ); } } _ => {} From 56fc66d196378a1af26631cbedabdcd07883bf3f Mon Sep 17 00:00:00 2001 From: Rejyr Date: Mon, 5 Sep 2022 12:42:58 -0400 Subject: [PATCH 07/33] migrate: `noop_method_call.rs` --- compiler/rustc_lint/src/lints.rs | 10 ++++++++++ compiler/rustc_lint/src/noop_method_call.rs | 16 +++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index fd68af572ff99..83d8dce154082 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -6,6 +6,16 @@ use rustc_span::{Span, Symbol}; use crate::LateContext; +#[derive(LintDiagnostic)] +#[diag(lint_noop_method_call)] +#[note] +pub struct NoopMethodCallDiag<'a> { + pub method: Symbol, + pub receiver_ty: Ty<'a>, + #[label] + pub label: Span, +} + #[derive(LintDiagnostic)] #[diag(lint_pass_by_value)] pub struct PassByValueDiag { diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 2ef425a109312..3fba95f0750d8 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -1,7 +1,10 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use crate::context::LintContext; +use crate::lints::NoopMethodCallDiag; +use crate::rustc_middle::ty::TypeVisitable; use crate::LateContext; use crate::LateLintPass; -use rustc_errors::fluent; use rustc_hir::def::DefKind; use rustc_hir::{Expr, ExprKind}; use rustc_middle::ty; @@ -85,11 +88,10 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { } let expr_span = expr.span; let span = expr_span.with_lo(receiver.span.hi()); - cx.struct_span_lint(NOOP_METHOD_CALL, span, fluent::lint_noop_method_call, |lint| { - lint.set_arg("method", call.ident.name) - .set_arg("receiver_ty", receiver_ty) - .span_label(span, fluent::label) - .note(fluent::note) - }); + cx.emit_spanned_lint( + NOOP_METHOD_CALL, + span, + NoopMethodCallDiag { method: call.ident.name, receiver_ty, label: span }, + ); } } From a9bbe31519b250fb331347351b47345fcbfe7932 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Mon, 5 Sep 2022 13:37:57 -0400 Subject: [PATCH 08/33] migrate: `nonstandard_style.rs` --- compiler/rustc_lint/src/lints.rs | 106 ++++++++++++++- compiler/rustc_lint/src/nonstandard_style.rs | 131 ++++++++----------- 2 files changed, 156 insertions(+), 81 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 83d8dce154082..7e92b2d6b3d51 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2,10 +2,114 @@ use rustc_errors::{fluent, AddSubdiagnostic, Applicability, DecorateLint, Emissi use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, SessionSubdiagnostic}; use rustc_middle::ty::{Predicate, Ty, TyCtxt}; -use rustc_span::{Span, Symbol}; +use rustc_span::{symbol::Ident, Span, Symbol}; use crate::LateContext; +#[derive(LintDiagnostic)] +#[diag(lint_non_camel_case_type)] +pub struct NonCamelCaseType<'a> { + pub sort: &'a str, + pub name: &'a str, + #[subdiagnostic] + pub sub: NonCamelCaseTypeSub, +} + +#[derive(SessionSubdiagnostic)] +pub enum NonCamelCaseTypeSub { + #[label(label)] + Label { + #[primary_span] + span: Span, + }, + #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")] + Suggestion { + #[primary_span] + span: Span, + replace: String, + }, +} + +#[derive(LintDiagnostic)] +#[diag(lint_non_snake_case)] +pub struct NonSnakeCaseDiag<'a> { + pub sort: &'a str, + pub name: &'a str, + pub sc: String, + #[subdiagnostic] + pub sub: NonSnakeCaseDiagSub, +} + +pub enum NonSnakeCaseDiagSub { + Label { span: Span }, + Help, + RenameOrConvertSuggestion { span: Span, suggestion: Ident }, + ConvertSuggestion { span: Span, suggestion: String }, + SuggestionAndNote { span: Span }, +} + +impl AddSubdiagnostic for NonSnakeCaseDiagSub { + fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + match self { + NonSnakeCaseDiagSub::Label { span } => { + diag.span_label(span, fluent::label); + } + NonSnakeCaseDiagSub::Help => { + diag.help(fluent::help); + } + NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => { + diag.span_suggestion( + span, + fluent::convert_suggestion, + suggestion, + Applicability::MaybeIncorrect, + ); + } + NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => { + diag.span_suggestion( + span, + fluent::rename_or_convert_suggestion, + suggestion, + Applicability::MaybeIncorrect, + ); + } + NonSnakeCaseDiagSub::SuggestionAndNote { span } => { + diag.note(fluent::cannot_convert_note); + diag.span_suggestion( + span, + fluent::rename_suggestion, + "", + Applicability::MaybeIncorrect, + ); + } + }; + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_non_upper_case_global)] +pub struct NonUpperCaseGlobal<'a> { + pub sort: &'a str, + pub name: &'a str, + #[subdiagnostic] + pub sub: NonUpperCaseGlobalSub, +} + +#[derive(SessionSubdiagnostic)] +pub enum NonUpperCaseGlobalSub { + #[label(label)] + Label { + #[primary_span] + span: Span, + }, + #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")] + Suggestion { + #[primary_span] + span: Span, + replace: String, + }, +} + #[derive(LintDiagnostic)] #[diag(lint_noop_method_call)] #[note] diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index f37d6e9a63d49..34e3751c061f1 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -1,7 +1,12 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +use crate::lints::{ + NonCamelCaseType, NonCamelCaseTypeSub, NonSnakeCaseDiag, NonSnakeCaseDiagSub, + NonUpperCaseGlobal, NonUpperCaseGlobalSub, +}; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_ast as ast; use rustc_attr as attr; -use rustc_errors::{fluent, Applicability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::FnKind; @@ -136,30 +141,17 @@ impl NonCamelCaseTypes { let name = ident.name.as_str(); if !is_camel_case(name) { - cx.struct_span_lint( + let cc = to_camel_case(name); + let sub = if *name != cc { + NonCamelCaseTypeSub::Suggestion { span: ident.span, replace: cc } + } else { + NonCamelCaseTypeSub::Label { span: ident.span } + }; + cx.emit_spanned_lint( NON_CAMEL_CASE_TYPES, ident.span, - fluent::lint_non_camel_case_type, - |lint| { - let cc = to_camel_case(name); - // We cannot provide meaningful suggestions - // if the characters are in the category of "Lowercase Letter". - if *name != cc { - lint.span_suggestion( - ident.span, - fluent::suggestion, - to_camel_case(name), - Applicability::MaybeIncorrect, - ); - } else { - lint.span_label(ident.span, fluent::label); - } - - lint.set_arg("sort", sort); - lint.set_arg("name", name); - lint - }, - ) + NonCamelCaseType { sort, name, sub }, + ); } } } @@ -294,47 +286,37 @@ impl NonSnakeCase { let name = ident.name.as_str(); if !is_snake_case(name) { - cx.struct_span_lint(NON_SNAKE_CASE, ident.span, fluent::lint_non_snake_case, |lint| { - let sc = NonSnakeCase::to_snake_case(name); - // We cannot provide meaningful suggestions - // if the characters are in the category of "Uppercase Letter". - if name != sc { - // We have a valid span in almost all cases, but we don't have one when linting a crate - // name provided via the command line. - if !ident.span.is_dummy() { - let sc_ident = Ident::from_str_and_span(&sc, ident.span); - let (message, suggestion) = if sc_ident.is_reserved() { - // We shouldn't suggest a reserved identifier to fix non-snake-case identifiers. - // Instead, recommend renaming the identifier entirely or, if permitted, - // escaping it to create a raw identifier. - if sc_ident.name.can_be_raw() { - (fluent::rename_or_convert_suggestion, sc_ident.to_string()) - } else { - lint.note(fluent::cannot_convert_note); - (fluent::rename_suggestion, String::new()) + let span = ident.span; + let sc = NonSnakeCase::to_snake_case(name); + // We cannot provide meaningful suggestions + // if the characters are in the category of "Uppercase Letter". + let sub = if name != sc { + // We have a valid span in almost all cases, but we don't have one when linting a crate + // name provided via the command line. + if !span.is_dummy() { + let sc_ident = Ident::from_str_and_span(&sc, span); + if sc_ident.is_reserved() { + // We shouldn't suggest a reserved identifier to fix non-snake-case identifiers. + // Instead, recommend renaming the identifier entirely or, if permitted, + // escaping it to create a raw identifier. + if sc_ident.name.can_be_raw() { + NonSnakeCaseDiagSub::RenameOrConvertSuggestion { + span, + suggestion: sc_ident, } } else { - (fluent::convert_suggestion, sc.clone()) - }; - - lint.span_suggestion( - ident.span, - message, - suggestion, - Applicability::MaybeIncorrect, - ); + NonSnakeCaseDiagSub::SuggestionAndNote { span } + } } else { - lint.help(fluent::help); + NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion: sc.clone() } } } else { - lint.span_label(ident.span, fluent::label); + NonSnakeCaseDiagSub::Help } - - lint.set_arg("sort", sort); - lint.set_arg("name", name); - lint.set_arg("sc", sc); - lint - }); + } else { + NonSnakeCaseDiagSub::Label { span } + }; + cx.emit_spanned_lint(NON_SNAKE_CASE, span, NonSnakeCaseDiag { sort, name, sc, sub }); } } } @@ -490,30 +472,19 @@ impl NonUpperCaseGlobals { fn check_upper_case(cx: &LateContext<'_>, sort: &str, ident: &Ident) { let name = ident.name.as_str(); if name.chars().any(|c| c.is_lowercase()) { - cx.struct_span_lint( + let uc = NonSnakeCase::to_snake_case(&name).to_uppercase(); + // We cannot provide meaningful suggestions + // if the characters are in the category of "Lowercase Letter". + let sub = if *name != uc { + NonUpperCaseGlobalSub::Suggestion { span: ident.span, replace: uc } + } else { + NonUpperCaseGlobalSub::Label { span: ident.span } + }; + cx.emit_spanned_lint( NON_UPPER_CASE_GLOBALS, ident.span, - fluent::lint_non_upper_case_global, - |lint| { - let uc = NonSnakeCase::to_snake_case(&name).to_uppercase(); - // We cannot provide meaningful suggestions - // if the characters are in the category of "Lowercase Letter". - if *name != uc { - lint.span_suggestion( - ident.span, - fluent::suggestion, - uc, - Applicability::MaybeIncorrect, - ); - } else { - lint.span_label(ident.span, fluent::label); - } - - lint.set_arg("sort", sort); - lint.set_arg("name", name); - lint - }, - ) + NonUpperCaseGlobal { sort, name, sub }, + ); } } } From 384010b9f47e6747e6f0b21439666cfe19e2573c Mon Sep 17 00:00:00 2001 From: Rejyr Date: Mon, 5 Sep 2022 14:38:36 -0400 Subject: [PATCH 09/33] migrate: `non_fmt_panic.rs` --- compiler/rustc_lint/src/lints.rs | 37 ++++++++++++++++++ compiler/rustc_lint/src/non_fmt_panic.rs | 49 ++++++++---------------- 2 files changed, 53 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 7e92b2d6b3d51..8a249ebf24d0c 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -6,6 +6,43 @@ use rustc_span::{symbol::Ident, Span, Symbol}; use crate::LateContext; +pub struct NonFmtPanicUnused { + pub count: usize, + pub suggestion: Option, +} + +impl DecorateLint<'_, G> for NonFmtPanicUnused { + fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) { + let mut diag = diag.build(fluent::lint_non_fmt_panic_unused); + diag.set_arg("count", self.count); + diag.note(fluent::note); + if let Some(span) = self.suggestion { + diag.span_suggestion( + span.shrink_to_hi(), + fluent::add_args_suggestion, + ", ...", + Applicability::HasPlaceholders, + ); + diag.span_suggestion( + span.shrink_to_lo(), + fluent::add_fmt_suggestion, + "\"{}\", ", + Applicability::MachineApplicable, + ); + } + diag.emit(); + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_non_fmt_panic_braces)] +#[note] +pub struct NonFmtPanicBraces { + pub count: usize, + #[suggestion(code = "\"{{}}\", ", applicability = "machine-applicable")] + pub suggestion: Option, +} + #[derive(LintDiagnostic)] #[diag(lint_non_camel_case_type)] pub struct NonCamelCaseType<'a> { diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 8dccfe0046c45..b86097a4bfc4a 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -1,3 +1,6 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +use crate::lints::{NonFmtPanicBraces, NonFmtPanicUnused}; use crate::{LateContext, LateLintPass, LintContext}; use rustc_ast as ast; use rustc_errors::{fluent, Applicability}; @@ -118,6 +121,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc arg_span = expn.call_site; } + #[allow(rustc::diagnostic_outside_of_impl)] cx.struct_span_lint(NON_FMT_PANICS, arg_span, fluent::lint_non_fmt_panic, |lint| { lint.set_arg("name", symbol); lint.note(fluent::note); @@ -253,25 +257,14 @@ fn check_panic_str<'tcx>( .map(|span| fmt_span.from_inner(InnerSpan::new(span.start, span.end))) .collect(), }; - cx.struct_span_lint(NON_FMT_PANICS, arg_spans, fluent::lint_non_fmt_panic_unused, |lint| { - lint.set_arg("count", n_arguments); - lint.note(fluent::note); - if is_arg_inside_call(arg.span, span) { - lint.span_suggestion( - arg.span.shrink_to_hi(), - fluent::add_args_suggestion, - ", ...", - Applicability::HasPlaceholders, - ); - lint.span_suggestion( - arg.span.shrink_to_lo(), - fluent::add_fmt_suggestion, - "\"{}\", ", - Applicability::MachineApplicable, - ); - } - lint - }); + cx.emit_spanned_lint( + NON_FMT_PANICS, + arg_spans, + NonFmtPanicUnused { + count: n_arguments, + suggestion: is_arg_inside_call(arg.span, span).then_some(arg.span), + }, + ); } else { let brace_spans: Option> = snippet.filter(|s| s.starts_with('"') || s.starts_with("r#")).map(|s| { @@ -281,22 +274,12 @@ fn check_panic_str<'tcx>( .collect() }); let count = brace_spans.as_ref().map(|v| v.len()).unwrap_or(/* any number >1 */ 2); - cx.struct_span_lint( + cx.emit_spanned_lint( NON_FMT_PANICS, brace_spans.unwrap_or_else(|| vec![span]), - fluent::lint_non_fmt_panic_braces, - |lint| { - lint.set_arg("count", count); - lint.note(fluent::note); - if is_arg_inside_call(arg.span, span) { - lint.span_suggestion( - arg.span.shrink_to_lo(), - fluent::suggestion, - "\"{}\", ", - Applicability::MachineApplicable, - ); - } - lint + NonFmtPanicBraces { + count, + suggestion: is_arg_inside_call(arg.span, span).then_some(arg.span.shrink_to_lo()), }, ); } From 3f69c1b523b4606d09dfdb3c8d9cb7d05e239595 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Mon, 5 Sep 2022 15:05:19 -0400 Subject: [PATCH 10/33] migrate: `non_ascii_idents.rs` --- compiler/rustc_lint/src/lints.rs | 26 +++++++++ compiler/rustc_lint/src/non_ascii_idents.rs | 58 ++++++++------------- 2 files changed, 49 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 8a249ebf24d0c..47582e6a1c68b 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -6,6 +6,32 @@ use rustc_span::{symbol::Ident, Span, Symbol}; use crate::LateContext; +#[derive(LintDiagnostic)] +#[diag(lint_identifier_non_ascii_char)] +pub struct IdentifierNonAsciiChar; + +#[derive(LintDiagnostic)] +#[diag(lint_identifier_uncommon_codepoints)] +pub struct IdentifierUncommonCodepoints; + +#[derive(LintDiagnostic)] +#[diag(lint_confusable_identifier_pair)] +pub struct ConfusableIdentifierPair { + pub existing_sym: Symbol, + pub sym: Symbol, + #[label] + pub label: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_mixed_script_confusables)] +#[note(includes_note)] +#[note] +pub struct MixedScriptConfusables { + pub set: String, + pub includes: String, +} + pub struct NonFmtPanicUnused { pub count: usize, pub suggestion: Option, diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index dea9506acb200..1cac1508bbd6b 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -1,7 +1,12 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +use crate::lints::{ + ConfusableIdentifierPair, IdentifierNonAsciiChar, IdentifierUncommonCodepoints, + MixedScriptConfusables, +}; use crate::{EarlyContext, EarlyLintPass, LintContext}; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::fluent; use rustc_span::symbol::Symbol; declare_lint! { @@ -180,21 +185,11 @@ impl EarlyLintPass for NonAsciiIdents { continue; } has_non_ascii_idents = true; - cx.struct_span_lint( - NON_ASCII_IDENTS, - sp, - fluent::lint_identifier_non_ascii_char, - |lint| lint, - ); + cx.emit_spanned_lint(NON_ASCII_IDENTS, sp, IdentifierNonAsciiChar); if check_uncommon_codepoints && !symbol_str.chars().all(GeneralSecurityProfile::identifier_allowed) { - cx.struct_span_lint( - UNCOMMON_CODEPOINTS, - sp, - fluent::lint_identifier_uncommon_codepoints, - |lint| lint, - ) + cx.emit_spanned_lint(UNCOMMON_CODEPOINTS, sp, IdentifierUncommonCodepoints); } } @@ -222,14 +217,13 @@ impl EarlyLintPass for NonAsciiIdents { .entry(skeleton_sym) .and_modify(|(existing_symbol, existing_span, existing_is_ascii)| { if !*existing_is_ascii || !is_ascii { - cx.struct_span_lint( + cx.emit_spanned_lint( CONFUSABLE_IDENTS, sp, - fluent::lint_confusable_identifier_pair, - |lint| { - lint.set_arg("existing_sym", *existing_symbol) - .set_arg("sym", symbol) - .span_label(*existing_span, fluent::label) + ConfusableIdentifierPair { + existing_sym: *existing_symbol, + sym: symbol, + label: *existing_span, }, ); } @@ -331,24 +325,18 @@ impl EarlyLintPass for NonAsciiIdents { } for ((sp, ch_list), script_set) in lint_reports { - cx.struct_span_lint( + let mut includes = String::new(); + for (idx, ch) in ch_list.into_iter().enumerate() { + if idx != 0 { + includes += ", "; + } + let char_info = format!("'{}' (U+{:04X})", ch, ch as u32); + includes += &char_info; + } + cx.emit_spanned_lint( MIXED_SCRIPT_CONFUSABLES, sp, - fluent::lint_mixed_script_confusables, - |lint| { - let mut includes = String::new(); - for (idx, ch) in ch_list.into_iter().enumerate() { - if idx != 0 { - includes += ", "; - } - let char_info = format!("'{}' (U+{:04X})", ch, ch as u32); - includes += &char_info; - } - lint.set_arg("set", script_set.to_string()) - .set_arg("includes", includes) - .note(fluent::includes_note) - .note(fluent::note) - }, + MixedScriptConfusables { set: script_set.to_string(), includes }, ); } } From 95d3e0cb782016d7e360741a590cb07cc6413d27 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Mon, 5 Sep 2022 15:37:30 -0400 Subject: [PATCH 11/33] migrate: `methods.rs` --- compiler/rustc_lint/src/lints.rs | 10 ++++++++++ compiler/rustc_lint/src/methods.rs | 14 +++++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 47582e6a1c68b..8ad62672f6e63 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -6,6 +6,16 @@ use rustc_span::{symbol::Ident, Span, Symbol}; use crate::LateContext; +#[derive(LintDiagnostic)] +#[diag(lint_cstring_ptr)] +#[note] +#[help] +pub struct CStringPtr { + #[label(as_ptr_label)] + pub as_ptr: Span, + #[label(unwrap_label)] + pub unwrap: Span, +} #[derive(LintDiagnostic)] #[diag(lint_identifier_non_ascii_char)] pub struct IdentifierNonAsciiChar; diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs index e2d7d5b49f693..06d4d2d23403d 100644 --- a/compiler/rustc_lint/src/methods.rs +++ b/compiler/rustc_lint/src/methods.rs @@ -1,7 +1,9 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +use crate::lints::CStringPtr; use crate::LateContext; use crate::LateLintPass; use crate::LintContext; -use rustc_errors::fluent; use rustc_hir::{Expr, ExprKind, PathSegment}; use rustc_middle::ty; use rustc_span::{symbol::sym, ExpnKind, Span}; @@ -90,16 +92,10 @@ fn lint_cstring_as_ptr( if cx.tcx.is_diagnostic_item(sym::Result, def.did()) { if let ty::Adt(adt, _) = substs.type_at(0).kind() { if cx.tcx.is_diagnostic_item(sym::cstring_type, adt.did()) { - cx.struct_span_lint( + cx.emit_spanned_lint( TEMPORARY_CSTRING_AS_PTR, as_ptr_span, - fluent::lint_cstring_ptr, - |diag| { - diag.span_label(as_ptr_span, fluent::as_ptr_label) - .span_label(unwrap.span, fluent::unwrap_label) - .note(fluent::note) - .help(fluent::help) - }, + CStringPtr { as_ptr: as_ptr_span, unwrap: unwrap.span }, ); } } From c63ba52562a0c6c8d19b320c558d437bb8d87bd8 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Sun, 18 Sep 2022 10:03:35 -0400 Subject: [PATCH 12/33] migrate: `array_into_iter.rs` --- compiler/rustc_lint/src/array_into_iter.rs | 52 ++++++++-------------- compiler/rustc_lint/src/lints.rs | 32 ++++++++++--- 2 files changed, 45 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index abebc533cc17b..ea5975ed4f0b3 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -1,5 +1,7 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +use crate::lints::{ArrayIntoIterDiag, ArrayIntoIterDiagSub}; use crate::{LateContext, LateLintPass, LintContext}; -use rustc_errors::{fluent, Applicability}; use rustc_hir as hir; use rustc_middle::ty; use rustc_middle::ty::adjustment::{Adjust, Adjustment}; @@ -118,41 +120,23 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { // to an array or to a slice. _ => bug!("array type coerced to something other than array or slice"), }; - cx.struct_span_lint( + let sub = if self.for_expr_span == expr.span { + Some(ArrayIntoIterDiagSub::RemoveIntoIter { + span: receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()), + }) + } else if receiver_ty.is_array() { + Some(ArrayIntoIterDiagSub::UseExplicitIntoIter { + start_span: expr.span.shrink_to_lo(), + end_span: receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()), + }) + } else { + None + }; + cx.emit_spanned_lint( ARRAY_INTO_ITER, call.ident.span, - fluent::lint_array_into_iter, - |diag| { - diag.set_arg("target", target); - diag.span_suggestion( - call.ident.span, - fluent::use_iter_suggestion, - "iter", - Applicability::MachineApplicable, - ); - if self.for_expr_span == expr.span { - diag.span_suggestion( - receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()), - fluent::remove_into_iter_suggestion, - "", - Applicability::MaybeIncorrect, - ); - } else if receiver_ty.is_array() { - diag.multipart_suggestion( - fluent::use_explicit_into_iter_suggestion, - vec![ - (expr.span.shrink_to_lo(), "IntoIterator::into_iter(".into()), - ( - receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()), - ")".into(), - ), - ], - Applicability::MaybeIncorrect, - ); - } - diag - }, - ) + ArrayIntoIterDiag { target, suggestion: call.ident.span, sub }, + ); } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 8ad62672f6e63..9bfd000351a8c 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -6,6 +6,32 @@ use rustc_span::{symbol::Ident, Span, Symbol}; use crate::LateContext; +#[derive(LintDiagnostic)] +#[diag(lint_array_into_iter)] +pub struct ArrayIntoIterDiag<'a> { + pub target: &'a str, + #[suggestion(use_iter_suggestion, code = "iter", applicability = "machine-applicable")] + pub suggestion: Span, + #[subdiagnostic] + pub sub: Option, +} + +#[derive(SessionSubdiagnostic)] +pub enum ArrayIntoIterDiagSub { + #[suggestion(remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")] + RemoveIntoIter { + #[primary_span] + span: Span, + }, + #[multipart_suggestion(use_explicit_into_iter_suggestion, applicability = "maybe-incorrect")] + UseExplicitIntoIter { + #[suggestion_part(code = "IntoIterator::into_iter(")] + start_span: Span, + #[suggestion_part(code = ")")] + end_span: Span, + }, +} + #[derive(LintDiagnostic)] #[diag(lint_cstring_ptr)] #[note] @@ -454,11 +480,7 @@ pub struct PathStatementDrop { #[derive(SessionSubdiagnostic)] pub enum PathStatementDropSub { - #[suggestion( - suggestion, - code = "drop({snippet});", - applicability = "machine-applicable" - )] + #[suggestion(suggestion, code = "drop({snippet});", applicability = "machine-applicable")] Suggestion { #[primary_span] span: Span, From 8b897bbce6902a646f5de5df6ec4d92b0af98788 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Sun, 18 Sep 2022 10:31:35 -0400 Subject: [PATCH 13/33] migrate: `early.rs` and `enum_intrinsics_non_enums.rs` --- compiler/rustc_lint/src/early.rs | 3 +++ .../src/enum_intrinsics_non_enums.rs | 19 +++++++++++-------- compiler/rustc_lint/src/errors.rs | 1 + compiler/rustc_lint/src/lints.rs | 15 +++++++++++++++ 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index c18abaef8e256..58b1ae6e80010 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] //! Implementation of lint checking. //! //! The lint checking is mostly consolidated into one pass which runs @@ -39,6 +41,7 @@ pub struct EarlyContextAndPass<'a, T: EarlyLintPass> { impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { // This always-inlined function is for the hot call site. #[inline(always)] + #[allow(rustc::diagnostic_outside_of_impl)] fn inlined_check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { let BufferedEarlyLint { span, msg, node_id: _, lint_id, diagnostic } = early_lint; diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs index f9d7466228ad1..6c398cebee770 100644 --- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs +++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs @@ -1,5 +1,10 @@ -use crate::{context::LintContext, LateContext, LateLintPass}; -use rustc_errors::fluent; +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +use crate::{ + context::LintContext, + lints::{EnumIntrinsicsMemDiscriminate, EnumIntrinsicsMemVariant}, + LateContext, LateLintPass, +}; use rustc_hir as hir; use rustc_middle::ty::{visit::TypeVisitable, Ty}; use rustc_span::{symbol::sym, Span}; @@ -50,11 +55,10 @@ fn enforce_mem_discriminant( ) { let ty_param = cx.typeck_results().node_substs(func_expr.hir_id).type_at(0); if is_non_enum(ty_param) { - cx.struct_span_lint( + cx.emit_spanned_lint( ENUM_INTRINSICS_NON_ENUMS, expr_span, - fluent::lint_enum_intrinsics_mem_discriminant, - |lint| lint.set_arg("ty_param", ty_param).span_note(args_span, fluent::note), + EnumIntrinsicsMemDiscriminate { ty_param, note: args_span }, ); } } @@ -62,11 +66,10 @@ fn enforce_mem_discriminant( fn enforce_mem_variant_count(cx: &LateContext<'_>, func_expr: &hir::Expr<'_>, span: Span) { let ty_param = cx.typeck_results().node_substs(func_expr.hir_id).type_at(0); if is_non_enum(ty_param) { - cx.struct_span_lint( + cx.emit_spanned_lint( ENUM_INTRINSICS_NON_ENUMS, span, - fluent::lint_enum_intrinsics_mem_variant, - |lint| lint.set_arg("ty_param", ty_param).note(fluent::note), + EnumIntrinsicsMemVariant { ty_param }, ); } } diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 1a769893f5520..cc34357fa4bc5 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -38,6 +38,7 @@ impl AddToDiagnostic for OverruledAttributeSub { OverruledAttributeSub::NodeSource { span, reason } => { diag.span_label(span, fluent::lint_node_source); if let Some(rationale) = reason { + #[allow(rustc::diagnostic_outside_of_impl)] diag.note(rationale.as_str()); } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 9bfd000351a8c..686aca2d404e4 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -32,6 +32,21 @@ pub enum ArrayIntoIterDiagSub { }, } +#[derive(LintDiagnostic)] +#[diag(lint_enum_intrinsics_mem_discriminant)] +pub struct EnumIntrinsicsMemDiscriminate<'a> { + pub ty_param: Ty<'a>, + #[note] + pub note: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_enum_intrinsics_mem_variant)] +#[note] +pub struct EnumIntrinsicsMemVariant<'a> { + pub ty_param: Ty<'a>, +} + #[derive(LintDiagnostic)] #[diag(lint_cstring_ptr)] #[note] From e3bb2ebfbfba0e928f27d2aea04cc070a1b8ebfe Mon Sep 17 00:00:00 2001 From: Rejyr Date: Wed, 21 Sep 2022 20:42:52 -0400 Subject: [PATCH 14/33] add: `lints` for `errors.rs` --- compiler/rustc_lint/src/errors.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index cc34357fa4bc5..82ec88fbeebd1 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use rustc_errors::{ fluent, AddToDiagnostic, Diagnostic, ErrorGuaranteed, Handler, IntoDiagnostic, SubdiagnosticMessage, @@ -38,7 +40,7 @@ impl AddToDiagnostic for OverruledAttributeSub { OverruledAttributeSub::NodeSource { span, reason } => { diag.span_label(span, fluent::lint_node_source); if let Some(rationale) = reason { - #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] diag.note(rationale.as_str()); } } From dc00aa31142199ac6901fd08e4e4fd2be9b22be3 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Wed, 21 Sep 2022 20:47:24 -0400 Subject: [PATCH 15/33] update: `lints.rs` for renamed traits update: `lints.rs` for renamed `SessionSubdiagnostic` and `AddSubdiagnostic` fix: NonSnakeCaseDiagSub fix: OverflowingBinHexSign --- compiler/rustc_lint/src/lints.rs | 34 +++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 686aca2d404e4..431ded9cd5f2d 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1,6 +1,6 @@ -use rustc_errors::{fluent, AddSubdiagnostic, Applicability, DecorateLint, EmissionGuarantee}; +use rustc_errors::{fluent, AddToDiagnostic, Applicability, DecorateLint, EmissionGuarantee}; use rustc_hir::def_id::DefId; -use rustc_macros::{LintDiagnostic, SessionSubdiagnostic}; +use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{Predicate, Ty, TyCtxt}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -16,7 +16,7 @@ pub struct ArrayIntoIterDiag<'a> { pub sub: Option, } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] pub enum ArrayIntoIterDiagSub { #[suggestion(remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")] RemoveIntoIter { @@ -129,7 +129,7 @@ pub struct NonCamelCaseType<'a> { pub sub: NonCamelCaseTypeSub, } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] pub enum NonCamelCaseTypeSub { #[label(label)] Label { @@ -162,8 +162,14 @@ pub enum NonSnakeCaseDiagSub { SuggestionAndNote { span: Span }, } -impl AddSubdiagnostic for NonSnakeCaseDiagSub { - fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { +impl AddToDiagnostic for NonSnakeCaseDiagSub { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { match self { NonSnakeCaseDiagSub::Label { span } => { diag.span_label(span, fluent::label); @@ -209,7 +215,7 @@ pub struct NonUpperCaseGlobal<'a> { pub sub: NonUpperCaseGlobalSub, } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] pub enum NonUpperCaseGlobalSub { #[label(label)] Label { @@ -307,8 +313,14 @@ pub enum OverflowingBinHexSign { Negative, } -impl AddSubdiagnostic for OverflowingBinHexSign { - fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { +impl AddToDiagnostic for OverflowingBinHexSign { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { match self { OverflowingBinHexSign::Positive => { diag.note(fluent::positive_note); @@ -321,7 +333,7 @@ impl AddSubdiagnostic for OverflowingBinHexSign { } } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] pub enum OverflowingBinHexSub<'a> { #[suggestion( suggestion, @@ -493,7 +505,7 @@ pub struct PathStatementDrop { pub sub: PathStatementDropSub, } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] pub enum PathStatementDropSub { #[suggestion(suggestion, code = "drop({snippet});", applicability = "machine-applicable")] Suggestion { From a0614ec2c3184a025692fc06aacb0df50fba2a19 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Tue, 4 Oct 2022 17:54:47 -0400 Subject: [PATCH 16/33] fix: merge conflict --- compiler/rustc_lint/src/lints.rs | 76 ++++++++++++++------- compiler/rustc_lint/src/noop_method_call.rs | 1 - compiler/rustc_lint/src/types.rs | 7 +- 3 files changed, 55 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 431ded9cd5f2d..391c4cb671d5c 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1,4 +1,4 @@ -use rustc_errors::{fluent, AddToDiagnostic, Applicability, DecorateLint, EmissionGuarantee}; +use rustc_errors::{fluent, AddToDiagnostic, Applicability, DecorateLint}; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{Predicate, Ty, TyCtxt}; @@ -88,9 +88,11 @@ pub struct NonFmtPanicUnused { pub suggestion: Option, } -impl DecorateLint<'_, G> for NonFmtPanicUnused { - fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) { - let mut diag = diag.build(fluent::lint_non_fmt_panic_unused); +impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { diag.set_arg("count", self.count); diag.note(fluent::note); if let Some(span) = self.suggestion { @@ -107,7 +109,11 @@ impl DecorateLint<'_, G> for NonFmtPanicUnused { Applicability::MachineApplicable, ); } - diag.emit(); + diag + } + + fn msg(&self) -> rustc_errors::DiagnosticMessage { + fluent::lint_non_fmt_panic_unused } } @@ -202,7 +208,7 @@ impl AddToDiagnostic for NonSnakeCaseDiagSub { Applicability::MaybeIncorrect, ); } - }; + } } } @@ -262,12 +268,17 @@ pub struct DropTraitConstraintsDiag<'a> { pub def_id: DefId, } -impl<'a, G: EmissionGuarantee> DecorateLint<'_, G> for DropTraitConstraintsDiag<'a> { - fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) { - let mut diag = diag.build(fluent::lint_drop_trait_constraints); +impl<'a> DecorateLint<'a, ()> for DropTraitConstraintsDiag<'_> { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { diag.set_arg("predicate", self.predicate); - diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id)); - diag.emit(); + diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id)) + } + + fn msg(&self) -> rustc_errors::DiagnosticMessage { + fluent::lint_drop_trait_constraints } } @@ -276,11 +287,16 @@ pub struct DropGlue<'a> { pub def_id: DefId, } -impl<'a, G: EmissionGuarantee> DecorateLint<'_, G> for DropGlue<'a> { - fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) { - let mut diag = diag.build(fluent::lint_drop_glue); - diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id)); - diag.emit(); +impl<'a> DecorateLint<'a, ()> for DropGlue<'_> { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { + diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id)) + } + + fn msg(&self) -> rustc_errors::DiagnosticMessage { + fluent::lint_drop_glue } } @@ -359,9 +375,11 @@ pub struct OverflowingInt<'a> { } // FIXME: refactor with `Option<&'a str>` in macro -impl<'a, G: EmissionGuarantee> DecorateLint<'_, G> for OverflowingInt<'a> { - fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) { - let mut diag = diag.build(fluent::lint_overflowing_int); +impl<'a> DecorateLint<'a, ()> for OverflowingInt<'_> { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { diag.set_arg("ty", self.ty); diag.set_arg("lit", self.lit); diag.set_arg("min", self.min); @@ -371,7 +389,11 @@ impl<'a, G: EmissionGuarantee> DecorateLint<'_, G> for OverflowingInt<'a> { diag.set_arg("suggestion_ty", suggestion_ty); diag.help(fluent::help); } - diag.emit(); + diag + } + + fn msg(&self) -> rustc_errors::DiagnosticMessage { + fluent::lint_overflowing_int } } @@ -484,9 +506,11 @@ pub struct UnusedDef<'a, 'b> { } // FIXME: refactor with `Option` in macro -impl<'a, 'b, G: EmissionGuarantee> DecorateLint<'_, G> for UnusedDef<'a, 'b> { - fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) { - let mut diag = diag.build(fluent::lint_unused_def); +impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { diag.set_arg("pre", self.pre); diag.set_arg("post", self.post); diag.set_arg("def", self.cx.tcx.def_path_str(self.def_id)); @@ -494,7 +518,11 @@ impl<'a, 'b, G: EmissionGuarantee> DecorateLint<'_, G> for UnusedDef<'a, 'b> { if let Some(note) = self.note { diag.note(note.as_str()); } - diag.emit(); + diag + } + + fn msg(&self) -> rustc_errors::DiagnosticMessage { + fluent::lint_unused_def } } diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 3fba95f0750d8..ed796940b89df 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -2,7 +2,6 @@ #![deny(rustc::diagnostic_outside_of_impl)] use crate::context::LintContext; use crate::lints::NoopMethodCallDiag; -use crate::rustc_middle::ty::TypeVisitable; use crate::LateContext; use crate::LateLintPass; use rustc_hir::def::DefKind; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 46e957d15931a..3d797d84c04f7 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1138,10 +1138,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { CItemKind::Definition => "fn", }; #[allow(rustc::diagnostic_outside_of_impl)] - let mut diag = lint.build(fluent::lint_improper_ctypes); - diag.set_arg("ty", ty); - diag.set_arg("desc", item_description); - diag.span_label(sp, fluent::label); + lint.set_arg("ty", ty); + lint.set_arg("desc", item_description); + lint.span_label(sp, fluent::label); if let Some(help) = help { lint.help(help); } From f9289c35fb0a6e1ddde9200423cdd7d5dafb0886 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Tue, 4 Oct 2022 19:39:02 -0400 Subject: [PATCH 17/33] refactor: comment about lint location --- compiler/rustc_lint/src/lints.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 391c4cb671d5c..42deb455b0619 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -6,6 +6,7 @@ use rustc_span::{symbol::Ident, Span, Symbol}; use crate::LateContext; +// array_into_iter.rs #[derive(LintDiagnostic)] #[diag(lint_array_into_iter)] pub struct ArrayIntoIterDiag<'a> { @@ -32,6 +33,7 @@ pub enum ArrayIntoIterDiagSub { }, } +// enum_intrinsics_non_enums.rs #[derive(LintDiagnostic)] #[diag(lint_enum_intrinsics_mem_discriminant)] pub struct EnumIntrinsicsMemDiscriminate<'a> { @@ -47,6 +49,7 @@ pub struct EnumIntrinsicsMemVariant<'a> { pub ty_param: Ty<'a>, } +// methods.rs #[derive(LintDiagnostic)] #[diag(lint_cstring_ptr)] #[note] @@ -57,6 +60,8 @@ pub struct CStringPtr { #[label(unwrap_label)] pub unwrap: Span, } + +// non_ascii_idents.rs #[derive(LintDiagnostic)] #[diag(lint_identifier_non_ascii_char)] pub struct IdentifierNonAsciiChar; @@ -83,6 +88,7 @@ pub struct MixedScriptConfusables { pub includes: String, } +// non_fmt_panic.rs pub struct NonFmtPanicUnused { pub count: usize, pub suggestion: Option, @@ -126,6 +132,7 @@ pub struct NonFmtPanicBraces { pub suggestion: Option, } +// nonstandard_style.rs #[derive(LintDiagnostic)] #[diag(lint_non_camel_case_type)] pub struct NonCamelCaseType<'a> { @@ -236,6 +243,7 @@ pub enum NonUpperCaseGlobalSub { }, } +// noop_method_call.rs #[derive(LintDiagnostic)] #[diag(lint_noop_method_call)] #[note] @@ -246,6 +254,7 @@ pub struct NoopMethodCallDiag<'a> { pub label: Span, } +// pass_by_value.rs #[derive(LintDiagnostic)] #[diag(lint_pass_by_value)] pub struct PassByValueDiag { @@ -254,6 +263,7 @@ pub struct PassByValueDiag { pub suggestion: Span, } +// redundant_semicolon.rs #[derive(LintDiagnostic)] #[diag(lint_redundant_semicolons)] pub struct RedundantSemicolonsDiag { @@ -262,6 +272,7 @@ pub struct RedundantSemicolonsDiag { pub suggestion: Span, } +// traits.rs pub struct DropTraitConstraintsDiag<'a> { pub predicate: Predicate<'a>, pub tcx: TyCtxt<'a>, @@ -300,6 +311,7 @@ impl<'a> DecorateLint<'a, ()> for DropGlue<'_> { } } +// types.rs #[derive(LintDiagnostic)] #[diag(lint_range_endpoint_out_of_range)] pub struct RangeEndpointOutOfRange<'a> { @@ -457,6 +469,7 @@ pub struct InvalidAtomicOrderingDiag { pub fail_order_arg_span: Span, } +// unused.rs #[derive(LintDiagnostic)] #[diag(lint_unused_op)] pub struct UnusedOp<'a> { From ab66ea61cf4b6f47109d9c24d5a3ce3ea169c60a Mon Sep 17 00:00:00 2001 From: Rejyr Date: Wed, 5 Oct 2022 08:23:00 -0400 Subject: [PATCH 18/33] add: `emit{,_spanned}_lint` for `LintLevelsBuilder` add: `emit_spanned_lint` and `emit_lint` for `LintLevelsBuilder` migrate: `DeprecatedLintName` --- .../locales/en-US/lint.ftl | 4 ++ compiler/rustc_lint/src/levels.rs | 48 +++++++++++-------- compiler/rustc_lint/src/lints.rs | 10 ++++ 3 files changed, 43 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl index 2eb409a5ddd5e..78b8f6aaae9e2 100644 --- a/compiler/rustc_error_messages/locales/en-US/lint.ftl +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -16,6 +16,10 @@ lint_enum_intrinsics_mem_variant = lint_expectation = this lint expectation is unfulfilled .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message +lint_deprecated_lint_name = + lint name `{$name}` is deprecated and may not have an effect in the future. + .suggestion = change it to + lint_hidden_unicode_codepoints = unicode codepoint changing visible direction of text present in {$label} .label = this {$label} contains {$count -> [one] an invisible diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index e9d3d44a3f9f9..edbf0c6f37a09 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -1,9 +1,12 @@ use crate::context::{CheckLintNameResult, LintStore}; use crate::late::unerased_lint_store; +use crate::lints::DeprecatedLintName; use rustc_ast as ast; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan}; +use rustc_errors::{ + Applicability, DecorateLint, Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan, +}; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::HirId; @@ -858,25 +861,13 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } Err((Some(ids), ref new_lint_name)) => { let lint = builtin::RENAMED_AND_REMOVED_LINTS; - let (lvl, src) = self.provider.get_lint_level(lint, &sess); - struct_lint_level( - self.sess, + self.emit_spanned_lint( lint, - lvl, - src, - Some(sp.into()), - format!( - "lint name `{}` is deprecated \ - and may not have an effect in the future.", - name - ), - |lint| { - lint.span_suggestion( - sp, - "change it to", - new_lint_name, - Applicability::MachineApplicable, - ) + sp.into(), + DeprecatedLintName { + name, + suggestion: sp, + replace: &new_lint_name, }, ); @@ -1086,6 +1077,25 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let (level, src) = self.lint_level(lint); struct_lint_level(self.sess, lint, level, src, span, msg, decorate) } + + pub fn emit_spanned_lint( + &self, + lint: &'static Lint, + span: MultiSpan, + decorate: impl for<'a> DecorateLint<'a, ()>, + ) { + let (level, src) = self.lint_level(lint); + struct_lint_level(self.sess, lint, level, src, Some(span), decorate.msg(), |lint| { + decorate.decorate_lint(lint) + }); + } + + pub fn emit_lint(&self, lint: &'static Lint, decorate: impl for<'a> DecorateLint<'a, ()>) { + let (level, src) = self.lint_level(lint); + struct_lint_level(self.sess, lint, level, src, None, decorate.msg(), |lint| { + decorate.decorate_lint(lint) + }); + } } pub(crate) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 42deb455b0619..942497a1d57a7 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -49,6 +49,16 @@ pub struct EnumIntrinsicsMemVariant<'a> { pub ty_param: Ty<'a>, } +// levels.rs +#[derive(LintDiagnostic)] +#[diag(lint::deprecated_lint_name)] +pub struct DeprecatedLintName<'a> { + pub name: String, + #[suggestion(code = "{replace}", applicability = "machine-applicable")] + pub suggestion: Span, + pub replace: &'a str, +} + // methods.rs #[derive(LintDiagnostic)] #[diag(lint_cstring_ptr)] From 80df25e1601880a2386495b469b19b60034ca382 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Thu, 6 Oct 2022 20:28:51 -0400 Subject: [PATCH 19/33] migrate: `levels.rs` --- .../locales/en-US/lint.ftl | 12 ++ compiler/rustc_lint/src/errors.rs | 4 +- compiler/rustc_lint/src/levels.rs | 142 +++++------------- compiler/rustc_lint/src/lints.rs | 77 +++++++++- 4 files changed, 128 insertions(+), 107 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl index 78b8f6aaae9e2..babdbb1cc1962 100644 --- a/compiler/rustc_error_messages/locales/en-US/lint.ftl +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -20,6 +20,18 @@ lint_deprecated_lint_name = lint name `{$name}` is deprecated and may not have an effect in the future. .suggestion = change it to +lint_renamed_or_removed_lint_suggestion = use the new name + +lint_unknown_lint = + unknown lint: `{$name}` + .suggestion = did you mean + +lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level + +lint_unknown_gated_lint = + unknown lint: `{$name}` + .note = the `{$name}` lint is unstable + lint_hidden_unicode_codepoints = unicode codepoint changing visible direction of text present in {$label} .label = this {$label} contains {$count -> [one] an invisible diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 82ec88fbeebd1..0ea643fd69b68 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -10,12 +10,12 @@ use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] #[diag(lint_overruled_attribute, code = "E0453")] -pub struct OverruledAttribute { +pub struct OverruledAttribute<'a> { #[primary_span] pub span: Span, #[label] pub overruled: Span, - pub lint_level: String, + pub lint_level: &'a str, pub lint_source: Symbol, #[subdiagnostic] pub sub: OverruledAttributeSub, diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index edbf0c6f37a09..b335f330f5d41 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -1,12 +1,15 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use crate::context::{CheckLintNameResult, LintStore}; use crate::late::unerased_lint_store; -use crate::lints::DeprecatedLintName; +use crate::lints::{ + DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAtributeLint, RenamedOrRemovedLint, + UnknownLint, +}; use rustc_ast as ast; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{ - Applicability, DecorateLint, Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan, -}; +use rustc_errors::{fluent, DecorateLint, DiagnosticBuilder, DiagnosticMessage, MultiSpan}; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::HirId; @@ -18,6 +21,7 @@ use rustc_middle::lint::{ }; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{RegisteredTools, TyCtxt}; +use rustc_session::lint::builtin::{RENAMED_AND_REMOVED_LINTS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES}; use rustc_session::lint::{ builtin::{self, FORBIDDEN_LINT_GROUPS, SINGLE_USE_LIFETIMES, UNFULFILLED_LINT_EXPECTATIONS}, Level, Lint, LintExpectationId, LintId, @@ -586,57 +590,32 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { old_src, id_name ); - - let decorate_diag = |diag: &mut Diagnostic| { - diag.span_label(src.span(), "overruled by previous forbid"); - match old_src { - LintLevelSource::Default => { - diag.note(&format!( - "`forbid` lint level is the default for {}", - id.to_string() - )); - } - LintLevelSource::Node { span, reason, .. } => { - diag.span_label(span, "`forbid` level set here"); - if let Some(rationale) = reason { - diag.note(rationale.as_str()); - } - } - LintLevelSource::CommandLine(_, _) => { - diag.note("`forbid` lint level was set on command line"); - } + let sub = match old_src { + LintLevelSource::Default => { + OverruledAttributeSub::DefaultSource { id: id.to_string() } + } + LintLevelSource::Node { span, reason, .. } => { + OverruledAttributeSub::NodeSource { span, reason } } + LintLevelSource::CommandLine(_, _) => OverruledAttributeSub::CommandLineSource, }; if !fcw_warning { self.sess.emit_err(OverruledAttribute { span: src.span(), overruled: src.span(), - lint_level: level.as_str().to_string(), + lint_level: level.as_str(), lint_source: src.name(), - sub: match old_src { - LintLevelSource::Default => { - OverruledAttributeSub::DefaultSource { id: id.to_string() } - } - LintLevelSource::Node { span, reason, .. } => { - OverruledAttributeSub::NodeSource { span, reason } - } - LintLevelSource::CommandLine(_, _) => { - OverruledAttributeSub::CommandLineSource - } - }, + sub, }); } else { - self.struct_lint( + self.emit_spanned_lint( FORBIDDEN_LINT_GROUPS, - Some(src.span().into()), - format!( - "{}({}) incompatible with previous forbid", - level.as_str(), - src.name(), - ), - |lint| { - decorate_diag(lint); - lint + src.span().into(), + OverruledAtributeLint { + overruled: src.span(), + lint_level: level.as_str(), + lint_source: src.name(), + sub, }, ); } @@ -908,54 +887,22 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { _ if !self.warn_about_weird_lints => {} CheckLintNameResult::Warning(msg, renamed) => { - let lint = builtin::RENAMED_AND_REMOVED_LINTS; - let (renamed_lint_level, src) = self.provider.get_lint_level(lint, &sess); - struct_lint_level( - self.sess, - lint, - renamed_lint_level, - src, - Some(sp.into()), - msg, - |lint| { - if let Some(new_name) = &renamed { - lint.span_suggestion( - sp, - "use the new name", - new_name, - Applicability::MachineApplicable, - ); - } - lint - }, + self.emit_spanned_lint( + RENAMED_AND_REMOVED_LINTS, + sp.into(), + RenamedOrRemovedLint { msg, suggestion: sp, renamed }, ); } CheckLintNameResult::NoLint(suggestion) => { - let lint = builtin::UNKNOWN_LINTS; - let (level, src) = self.provider.get_lint_level(lint, self.sess); let name = if let Some(tool_ident) = tool_ident { format!("{}::{}", tool_ident.name, name) } else { name.to_string() }; - struct_lint_level( - self.sess, - lint, - level, - src, - Some(sp.into()), - format!("unknown lint: `{}`", name), - |lint| { - if let Some(suggestion) = suggestion { - lint.span_suggestion( - sp, - "did you mean", - suggestion, - Applicability::MaybeIncorrect, - ); - } - lint - }, + self.emit_spanned_lint( + UNKNOWN_LINTS, + sp.into(), + UnknownLint { name, suggestion: sp, replace: suggestion }, ); } } @@ -1001,20 +948,10 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { continue }; - let lint = builtin::UNUSED_ATTRIBUTES; - let (lint_level, lint_src) = self.provider.get_lint_level(lint, &self.sess); - struct_lint_level( - self.sess, - lint, - lint_level, - lint_src, - Some(lint_attr_span.into()), - format!( - "{}({}) is ignored unless specified at crate level", - level.as_str(), - lint_attr_name - ), - |lint| lint, + self.emit_spanned_lint( + UNUSED_ATTRIBUTES, + lint_attr_span.into(), + IgnoredUnlessCrateSpecified { level: level.as_str(), name: lint_attr_name }, ); // don't set a separate error for every lint in the group break; @@ -1038,11 +975,10 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { level, src, Some(span.into()), - format!("unknown lint: `{}`", lint_id.lint.name_lower()), + fluent::lint_unknown_gated_lint, |lint| { - lint.note( - &format!("the `{}` lint is unstable", lint_id.lint.name_lower(),), - ); + lint.set_arg("name", lint_id.lint.name_lower()); + lint.note(fluent::note); add_feature_diagnostics(lint, &self.sess.parse_sess, feature); lint }, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 942497a1d57a7..eb86bb7b92503 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -4,7 +4,7 @@ use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{Predicate, Ty, TyCtxt}; use rustc_span::{symbol::Ident, Span, Symbol}; -use crate::LateContext; +use crate::{errors::OverruledAttributeSub, LateContext}; // array_into_iter.rs #[derive(LintDiagnostic)] @@ -51,7 +51,18 @@ pub struct EnumIntrinsicsMemVariant<'a> { // levels.rs #[derive(LintDiagnostic)] -#[diag(lint::deprecated_lint_name)] +#[diag(lint_overruled_attribute)] +pub struct OverruledAtributeLint<'a> { + #[label] + pub overruled: Span, + pub lint_level: &'a str, + pub lint_source: Symbol, + #[subdiagnostic] + pub sub: OverruledAttributeSub, +} + +#[derive(LintDiagnostic)] +#[diag(lint_deprecated_lint_name)] pub struct DeprecatedLintName<'a> { pub name: String, #[suggestion(code = "{replace}", applicability = "machine-applicable")] @@ -59,6 +70,68 @@ pub struct DeprecatedLintName<'a> { pub replace: &'a str, } +pub struct RenamedOrRemovedLint<'a> { + pub msg: &'a str, + pub suggestion: Span, + pub renamed: &'a Option, +} + +impl<'a> DecorateLint<'a, ()> for RenamedOrRemovedLint<'_> { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { + if let Some(new_name) = self.renamed { + diag.span_suggestion( + self.suggestion, + fluent::lint_renamed_or_removed_lint_suggestion, + new_name, + Applicability::MachineApplicable, + ); + }; + diag + } + + fn msg(&self) -> rustc_errors::DiagnosticMessage { + rustc_errors::DiagnosticMessage::Str(self.msg.to_string()) + } +} + +pub struct UnknownLint<'a> { + pub name: String, + pub suggestion: Span, + pub replace: &'a Option, +} + +impl<'a> DecorateLint<'a, ()> for UnknownLint<'_> { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { + diag.set_arg("name", self.name); + if let Some(replace) = self.replace { + diag.span_suggestion( + self.suggestion, + fluent::suggestion, + replace, + Applicability::MaybeIncorrect, + ); + }; + diag + } + + fn msg(&self) -> rustc_errors::DiagnosticMessage { + fluent::lint_unknown_lint + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_ignored_unless_crate_specified)] +pub struct IgnoredUnlessCrateSpecified<'a> { + pub level: &'a str, + pub name: Symbol, +} + // methods.rs #[derive(LintDiagnostic)] #[diag(lint_cstring_ptr)] From e6100479404c194a4801f577be2e9f69b4c6fef9 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Fri, 7 Oct 2022 06:14:56 -0400 Subject: [PATCH 20/33] migrate: `let_underscore.rs` fix: NonBindingLetSub --- .../locales/en-US/lint.ftl | 12 +++++ compiler/rustc_lint/src/let_underscore.rs | 49 ++++++------------- compiler/rustc_lint/src/lints.rs | 46 +++++++++++++++++ 3 files changed, 74 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl index babdbb1cc1962..2423d9c0ef998 100644 --- a/compiler/rustc_error_messages/locales/en-US/lint.ftl +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -16,6 +16,18 @@ lint_enum_intrinsics_mem_variant = lint_expectation = this lint expectation is unfulfilled .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message +lint_non_binding_let_on_sync_lock = + non-binding let on a synchronization lock + +lint_non_binding_let_on_drop_type = + non-binding let on a type that implements `Drop` + +lint_non_binding_let_suggestion = + consider binding to an unused variable to avoid immediately dropping the value + +lint_non_binding_let_multi_suggestion = + consider immediately dropping the value + lint_deprecated_lint_name = lint name `{$name}` is deprecated and may not have an effect in the future. .suggestion = change it to diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 04d844d21dc38..991b3e920adbc 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -1,5 +1,10 @@ -use crate::{LateContext, LateLintPass, LintContext}; -use rustc_errors::{Applicability, DiagnosticBuilder, MultiSpan}; +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +use crate::{ + lints::{NonBindingLet, NonBindingLetSub}, + LateContext, LateLintPass, LintContext, +}; +use rustc_errors::MultiSpan; use rustc_hir as hir; use rustc_middle::ty; use rustc_span::Symbol; @@ -119,6 +124,11 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { _ => false, }; + let sub = NonBindingLetSub { + suggestion: local.pat.span, + multi_suggestion_start: local.span.until(init.span), + multi_suggestion_end: init.span.shrink_to_hi(), + }; if is_sync_lock { let mut span = MultiSpan::from_spans(vec![local.pat.span, init.span]); span.push_span_label( @@ -129,41 +139,14 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { init.span, "this binding will immediately drop the value assigned to it".to_string(), ); - cx.struct_span_lint( - LET_UNDERSCORE_LOCK, - span, - "non-binding let on a synchronization lock", - |lint| build_lint(lint, local, init.span), - ) + cx.emit_spanned_lint(LET_UNDERSCORE_LOCK, span, NonBindingLet::SyncLock { sub }); } else { - cx.struct_span_lint( + cx.emit_spanned_lint( LET_UNDERSCORE_DROP, local.span, - "non-binding let on a type that implements `Drop`", - |lint| build_lint(lint, local, init.span), - ) + NonBindingLet::DropType { sub }, + ); } } } } - -fn build_lint<'a, 'b>( - lint: &'a mut DiagnosticBuilder<'b, ()>, - local: &hir::Local<'_>, - init_span: rustc_span::Span, -) -> &'a mut DiagnosticBuilder<'b, ()> { - lint.span_suggestion_verbose( - local.pat.span, - "consider binding to an unused variable to avoid immediately dropping the value", - "_unused", - Applicability::MachineApplicable, - ) - .multipart_suggestion( - "consider immediately dropping the value", - vec![ - (local.span.until(init_span), "drop(".to_string()), - (init_span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MachineApplicable, - ) -} diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index eb86bb7b92503..0f314606a94f5 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -49,6 +49,52 @@ pub struct EnumIntrinsicsMemVariant<'a> { pub ty_param: Ty<'a>, } +// let_underscore.rs +#[derive(LintDiagnostic)] +pub enum NonBindingLet { + #[diag(lint::non_binding_let_on_sync_lock)] + SyncLock { + #[subdiagnostic] + sub: NonBindingLetSub, + }, + #[diag(lint::non_binding_let_on_drop_type)] + DropType { + #[subdiagnostic] + sub: NonBindingLetSub, + }, +} + +pub struct NonBindingLetSub { + pub suggestion: Span, + pub multi_suggestion_start: Span, + pub multi_suggestion_end: Span, +} + +impl AddToDiagnostic for NonBindingLetSub { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { + diag.span_suggestion_verbose( + self.suggestion, + fluent::lint::non_binding_let_suggestion, + "_unused", + Applicability::MachineApplicable, + ); + diag.multipart_suggestion( + fluent::lint::non_binding_let_multi_suggestion, + vec![ + (self.multi_suggestion_start, "drop(".to_string()), + (self.multi_suggestion_end, ")".to_string()), + ], + Applicability::MachineApplicable, + ); + } +} + // levels.rs #[derive(LintDiagnostic)] #[diag(lint_overruled_attribute)] From 5ffaae758e45cc87b435b1a929c8aae9d9ea5a69 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Fri, 7 Oct 2022 06:38:20 -0400 Subject: [PATCH 21/33] migrate: `ImproperCTypes` --- compiler/rustc_lint/src/lints.rs | 42 ++++++++++++++++++++++++++++---- compiler/rustc_lint/src/types.rs | 42 ++++++++++++++------------------ 2 files changed, 55 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 0f314606a94f5..a6e00c3e883f3 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1,4 +1,4 @@ -use rustc_errors::{fluent, AddToDiagnostic, Applicability, DecorateLint}; +use rustc_errors::{fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage}; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{Predicate, Ty, TyCtxt}; @@ -52,12 +52,12 @@ pub struct EnumIntrinsicsMemVariant<'a> { // let_underscore.rs #[derive(LintDiagnostic)] pub enum NonBindingLet { - #[diag(lint::non_binding_let_on_sync_lock)] + #[diag(lint_non_binding_let_on_sync_lock)] SyncLock { #[subdiagnostic] sub: NonBindingLetSub, }, - #[diag(lint::non_binding_let_on_drop_type)] + #[diag(lint_non_binding_let_on_drop_type)] DropType { #[subdiagnostic] sub: NonBindingLetSub, @@ -80,12 +80,12 @@ impl AddToDiagnostic for NonBindingLetSub { { diag.span_suggestion_verbose( self.suggestion, - fluent::lint::non_binding_let_suggestion, + fluent::lint_non_binding_let_suggestion, "_unused", Applicability::MachineApplicable, ); diag.multipart_suggestion( - fluent::lint::non_binding_let_multi_suggestion, + fluent::lint_non_binding_let_multi_suggestion, vec![ (self.multi_suggestion_start, "drop(".to_string()), (self.multi_suggestion_end, ")".to_string()), @@ -568,6 +568,38 @@ pub struct OverflowingLiteral<'a> { #[diag(lint_unused_comparisons)] pub struct UnusedComparisons; +pub struct ImproperCTypes<'a> { + pub ty: Ty<'a>, + pub desc: &'a str, + pub label: Span, + pub help: Option, + pub note: DiagnosticMessage, + pub span_note: Option, +} + +impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { + diag.set_arg("ty", self.ty); + diag.set_arg("desc", self.desc); + diag.span_label(self.label, fluent::label); + if let Some(help) = self.help { + diag.help(help); + } + diag.note(self.note); + if let Some(note) = self.span_note { + diag.span_note(note, fluent::note); + } + diag + } + + fn msg(&self) -> rustc_errors::DiagnosticMessage { + fluent::lint_improper_ctypes + } +} + #[derive(LintDiagnostic)] #[diag(lint_variant_size_differences)] pub struct VariantSizeDifferencesDiag { diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 3d797d84c04f7..a112292eb1412 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1,10 +1,10 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] use crate::lints::{ - AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, InvalidAtomicOrderingDiag, - OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSub, - OverflowingInt, OverflowingLiteral, OverflowingUInt, RangeEndpointOutOfRange, - UnusedComparisons, VariantSizeDifferencesDiag, + AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes, + InvalidAtomicOrderingDiag, OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, + OverflowingBinHexSub, OverflowingInt, OverflowingLiteral, OverflowingUInt, + RangeEndpointOutOfRange, UnusedComparisons, VariantSizeDifferencesDiag, }; use crate::{LateContext, LateLintPass, LintContext}; use rustc_ast as ast; @@ -1131,27 +1131,21 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { CItemKind::Declaration => IMPROPER_CTYPES, CItemKind::Definition => IMPROPER_CTYPES_DEFINITIONS, }; - - self.cx.struct_span_lint(lint, sp, fluent::lint_improper_ctypes, |lint| { - let item_description = match self.mode { - CItemKind::Declaration => "block", - CItemKind::Definition => "fn", + let desc = match self.mode { + CItemKind::Declaration => "block", + CItemKind::Definition => "fn", + }; + let span_note = if let ty::Adt(def, _) = ty.kind() + && let Some(sp) = self.cx.tcx.hir().span_if_local(def.did()) { + Some(sp) + } else { + None }; - #[allow(rustc::diagnostic_outside_of_impl)] - lint.set_arg("ty", ty); - lint.set_arg("desc", item_description); - lint.span_label(sp, fluent::label); - if let Some(help) = help { - lint.help(help); - } - lint.note(note); - if let ty::Adt(def, _) = ty.kind() { - if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did()) { - lint.span_note(sp, fluent::note); - } - } - lint - }); + self.cx.emit_spanned_lint( + lint, + sp, + ImproperCTypes { ty, desc, label: sp, help, note, span_note }, + ); } fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { From 0b19227524622d953fbaefa272b36b0ef2fa263e Mon Sep 17 00:00:00 2001 From: Rejyr Date: Sat, 22 Oct 2022 16:32:54 -0400 Subject: [PATCH 22/33] migrate: `internal.rs` --- .../locales/en-US/lint.ftl | 2 + compiler/rustc_lint/src/internal.rs | 111 ++++++------------ compiler/rustc_lint/src/lints.rs | 62 ++++++++++ 3 files changed, 99 insertions(+), 76 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl index 2423d9c0ef998..747588c683cc5 100644 --- a/compiler/rustc_error_messages/locales/en-US/lint.ftl +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -83,6 +83,8 @@ lint_diag_out_of_impl = lint_untranslatable_diag = diagnostics should be created using translatable messages +lint_bad_opt_access = {$msg} + lint_cstring_ptr = getting the inner pointer of a temporary `CString` .as_ptr_label = this pointer will be invalid .unwrap_label = this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 48902cd05695c..7d13bcff7fd5d 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -1,9 +1,14 @@ //! Some lints that are only useful in the compiler or crates that use compiler internals, such as //! Clippy. +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +use crate::lints::{ + BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistantDocKeyword, + QueryInstability, TyQualified, TykindDiag, TykindKind, UntranslatableDiag, +}; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_ast as ast; -use rustc_errors::{fluent, Applicability}; use rustc_hir::def::Res; use rustc_hir::{def_id::DefId, Expr, ExprKind, GenericArg, PatKind, Path, PathSegment, QPath}; use rustc_hir::{HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind}; @@ -29,20 +34,15 @@ impl LateLintPass<'_> for DefaultHashTypes { // don't lint imports, only actual usages return; } - let replace = match cx.tcx.get_diagnostic_name(def_id) { + let preferred = match cx.tcx.get_diagnostic_name(def_id) { Some(sym::HashMap) => "FxHashMap", Some(sym::HashSet) => "FxHashSet", _ => return, }; - cx.struct_span_lint( + cx.emit_spanned_lint( DEFAULT_HASH_TYPES, path.span, - fluent::lint_default_hash_types, - |lint| { - lint.set_arg("preferred", replace) - .set_arg("used", cx.tcx.item_name(def_id)) - .note(fluent::note) - }, + DefaultHashTypesDiag { preferred, used: cx.tcx.item_name(def_id) }, ); } } @@ -83,12 +83,11 @@ impl LateLintPass<'_> for QueryStability { if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs) { let def_id = instance.def_id(); if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) { - cx.struct_span_lint( + cx.emit_spanned_lint( POTENTIAL_QUERY_INSTABILITY, span, - fluent::lint_query_instability, - |lint| lint.set_arg("query", cx.tcx.item_name(def_id)).note(fluent::note), - ) + QueryInstability { query: cx.tcx.item_name(def_id) }, + ); } } } @@ -126,14 +125,8 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind { let span = path.span.with_hi( segment.args.map_or(segment.ident.span, |a| a.span_ext).hi() ); - cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, fluent::lint_tykind_kind, |lint| { - lint - .span_suggestion( - span, - fluent::suggestion, - "ty", - Applicability::MaybeIncorrect, // ty maybe needs an import - ) + cx.emit_spanned_lint(USAGE_OF_TY_TYKIND, path.span, TykindKind { + suggestion: span, }); } } @@ -190,39 +183,17 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind { match span { Some(span) => { - cx.struct_span_lint( - USAGE_OF_TY_TYKIND, - path.span, - fluent::lint_tykind_kind, - |lint| lint.span_suggestion( - span, - fluent::suggestion, - "ty", - Applicability::MaybeIncorrect, // ty maybe needs an import - ) - ) + cx.emit_spanned_lint(USAGE_OF_TY_TYKIND, path.span, TykindKind { + suggestion: span, + }); }, - None => cx.struct_span_lint( - USAGE_OF_TY_TYKIND, - path.span, - fluent::lint_tykind, - |lint| lint.help(fluent::help) - ) - } - } else if !ty.span.from_expansion() && let Some(t) = is_ty_or_ty_ctxt(cx, &path) { - if path.segments.len() > 1 { - cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, fluent::lint_ty_qualified, |lint| { - lint - .set_arg("ty", t.clone()) - .span_suggestion( - path.span, - fluent::suggestion, - t, - // The import probably needs to be changed - Applicability::MaybeIncorrect, - ) - }) + None => cx.emit_spanned_lint(USAGE_OF_TY_TYKIND, path.span, TykindDiag), } + } else if !ty.span.from_expansion() && path.segments.len() > 1 && let Some(t) = is_ty_or_ty_ctxt(cx, &path) { + cx.emit_spanned_lint(USAGE_OF_QUALIFIED_TY, path.span, TyQualified { + ty: t.clone(), + suggestion: path.span, + }); } } _ => {} @@ -303,12 +274,11 @@ impl EarlyLintPass for LintPassImpl { && call_site.ctxt().outer_expn_data().kind != ExpnKind::Macro(MacroKind::Bang, sym::declare_lint_pass) { - cx.struct_span_lint( + cx.emit_spanned_lint( LINT_PASS_IMPL_WITHOUT_MACRO, lint_pass.path.span, - fluent::lint_lintpass_by_hand, - |lint| lint.help(fluent::help), - ) + LintPassByHand, + ); } } } @@ -338,17 +308,16 @@ impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword { if let Some(list) = attr.meta_item_list() { for nested in list { if nested.has_name(sym::keyword) { - let v = nested + let keyword = nested .value_str() .expect("#[doc(keyword = \"...\")] expected a value!"); - if is_doc_keyword(v) { + if is_doc_keyword(keyword) { return; } - cx.struct_span_lint( + cx.emit_spanned_lint( EXISTING_DOC_KEYWORD, attr.span, - fluent::lint_non_existant_doc_keyword, - |lint| lint.set_arg("keyword", v).help(fluent::help), + NonExistantDocKeyword { keyword }, ); } } @@ -407,12 +376,7 @@ impl LateLintPass<'_> for Diagnostics { } debug!(?found_impl); if !found_parent_with_attr && !found_impl { - cx.struct_span_lint( - DIAGNOSTIC_OUTSIDE_OF_IMPL, - span, - fluent::lint_diag_out_of_impl, - |lint| lint, - ) + cx.emit_spanned_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, DiagOutOfImpl); } let mut found_diagnostic_message = false; @@ -428,12 +392,7 @@ impl LateLintPass<'_> for Diagnostics { } debug!(?found_diagnostic_message); if !found_parent_with_attr && !found_diagnostic_message { - cx.struct_span_lint( - UNTRANSLATABLE_DIAGNOSTIC, - span, - fluent::lint_untranslatable_diag, - |lint| lint, - ) + cx.emit_spanned_lint(UNTRANSLATABLE_DIAGNOSTIC, span, UntranslatableDiag); } } } @@ -465,9 +424,9 @@ impl LateLintPass<'_> for BadOptAccess { let Some(lit) = item.lit() && let ast::LitKind::Str(val, _) = lit.kind { - cx.struct_span_lint(BAD_OPT_ACCESS, expr.span, val.as_str(), |lint| - lint - ); + cx.emit_spanned_lint(BAD_OPT_ACCESS, expr.span, BadOptAccessDiag { + msg: val.as_str(), + }); } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index a6e00c3e883f3..196922b78c30c 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -49,6 +49,68 @@ pub struct EnumIntrinsicsMemVariant<'a> { pub ty_param: Ty<'a>, } +// internal.rs +#[derive(LintDiagnostic)] +#[diag(lint_default_hash_types)] +#[note] +pub struct DefaultHashTypesDiag<'a> { + pub preferred: &'a str, + pub used: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(lint_query_instability)] +#[note] +pub struct QueryInstability { + pub query: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(lint_tykind_kind)] +pub struct TykindKind { + #[suggestion(code = "ty", applicability = "maybe-incorrect")] + pub suggestion: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_tykind)] +#[help] +pub struct TykindDiag; + +#[derive(LintDiagnostic)] +#[diag(lint_ty_qualified)] +pub struct TyQualified { + pub ty: String, + #[suggestion(code = "{ty}", applicability = "maybe-incorrect")] + pub suggestion: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_lintpass_by_hand)] +#[help] +pub struct LintPassByHand; + +#[derive(LintDiagnostic)] +#[diag(lint_non_existant_doc_keyword)] +#[help] +pub struct NonExistantDocKeyword { + pub keyword: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(lint_diag_out_of_impl)] +pub struct DiagOutOfImpl; + +#[derive(LintDiagnostic)] +#[diag(lint_untranslatable_diag)] +pub struct UntranslatableDiag; + +#[derive(LintDiagnostic)] +#[diag(lint_bad_opt_access)] +pub struct BadOptAccessDiag<'a> { + pub msg: &'a str, +} + // let_underscore.rs #[derive(LintDiagnostic)] pub enum NonBindingLet { From 6ffecd2059316e2eb07ee0983e62f24027e52704 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Sat, 22 Oct 2022 21:50:44 -0400 Subject: [PATCH 23/33] migrate(wip): `builtin.rs` --- .../locales/en-US/lint.ftl | 7 + compiler/rustc_lint/src/builtin.rs | 348 ++++++------------ compiler/rustc_lint/src/lints.rs | 257 ++++++++++++- 3 files changed, 383 insertions(+), 229 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl index 747588c683cc5..1080ba2d2b565 100644 --- a/compiler/rustc_error_messages/locales/en-US/lint.ftl +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -433,6 +433,13 @@ lint_builtin_deref_nullptr = dereferencing a null pointer lint_builtin_asm_labels = avoid using named labels in inline assembly +lint_builtin_special_module_name_used_lib = found module declaration for lib.rs + .note = lib.rs is the root of this crate's library target + .help = to refer to it from other targets, use the library's name as the path + +lint_builtin_special_module_name_used_main = found module declaration for main.rs + .note = a binary crate cannot be used as library + lint_overruled_attribute = {$lint_level}({$lint_source}) incompatible with previous forbid .label = overruled by previous forbid diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index d58168ff37721..8a34afb1ff524 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -22,6 +22,17 @@ use crate::{ errors::BuiltinEllpisisInclusiveRangePatterns, + lints::{ + BuiltinAnonymousParams, BuiltinBoxPointers, BuiltinConstNoMangle, + BuiltinDeprecatedAttrUsed, BuiltinDerefNullptr, BuiltinEllipsisInclusiveRangePatternsLint, + BuiltinExplicitOutlives, BuiltinExplicitOutlivesSuggestion, BuiltinIncompleteFeatures, + BuiltinKeywordIdents, BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, + BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, + BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinUnexpectedCliConfigName, + BuiltinUnexpectedCliConfigValue, BuiltinUnnameableTestItems, BuiltinUnreachablePub, + BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, + BuiltinWhileTrue, + }, types::{transparent_newtype_field, CItemKind}, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext, }; @@ -110,25 +121,17 @@ impl EarlyLintPass for WhileTrue { && !cond.span.from_expansion() { let condition_span = e.span.with_hi(cond.span.hi()); - cx.struct_span_lint( - WHILE_TRUE, - condition_span, - fluent::lint_builtin_while_true, - |lint| { - lint.span_suggestion_short( - condition_span, - fluent::suggestion, - format!( + let replace = format!( "{}loop", label.map_or_else(String::new, |label| format!( "{}: ", label.ident, )) - ), - Applicability::MachineApplicable, - ) - }, - ) + ); + cx.emit_spanned_lint(WHILE_TRUE, condition_span, BuiltinWhileTrue { + suggestion: condition_span, + replace, + }); } } } @@ -164,12 +167,7 @@ impl BoxPointers { for leaf in ty.walk() { if let GenericArgKind::Type(leaf_ty) = leaf.unpack() { if leaf_ty.is_box() { - cx.struct_span_lint( - BOX_POINTERS, - span, - fluent::lint_builtin_box_pointers, - |lint| lint.set_arg("ty", ty), - ); + cx.emit_spanned_lint(BOX_POINTERS, span, BuiltinBoxPointers { ty }); } } } @@ -267,19 +265,13 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns { if cx.tcx.find_field_index(ident, &variant) == Some(cx.typeck_results().field_index(fieldpat.hir_id)) { - cx.struct_span_lint( + cx.emit_spanned_lint( NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, - fluent::lint_builtin_non_shorthand_field_patterns, - |lint| { - let suggested_ident = - format!("{}{}", binding_annot.prefix_str(), ident); - lint.set_arg("ident", ident).span_suggestion( - fieldpat.span, - fluent::suggestion, - suggested_ident, - Applicability::MachineApplicable, - ) + BuiltinNonShorthandFieldPatterns { + ident, + suggestion: fieldpat.span, + prefix: binding_annot.prefix_str(), }, ); } @@ -578,11 +570,10 @@ impl MissingDoc { let attrs = cx.tcx.hir().attrs(cx.tcx.hir().local_def_id_to_hir_id(def_id)); let has_doc = attrs.iter().any(has_doc); if !has_doc { - cx.struct_span_lint( + cx.emit_spanned_lint( MISSING_DOCS, cx.tcx.def_span(def_id), - fluent::lint_builtin_missing_doc, - |lint| lint.set_arg("article", article).set_arg("desc", desc), + BuiltinMissingDoc { article, desc }, ); } } @@ -799,12 +790,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { ) .is_ok() { - cx.struct_span_lint( - MISSING_COPY_IMPLEMENTATIONS, - item.span, - fluent::lint_builtin_missing_copy_impl, - |lint| lint, - ) + cx.emit_spanned_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, BuiltinMissingCopyImpl); } } } @@ -878,11 +864,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { } if !self.impling_types.as_ref().unwrap().contains(&item.owner_id.def_id) { - cx.struct_span_lint( + cx.emit_spanned_lint( MISSING_DEBUG_IMPLEMENTATIONS, item.span, - fluent::lint_builtin_missing_debug_impl, - |lint| lint.set_arg("debug", cx.tcx.def_path_str(debug)), + BuiltinMissingDebugImpl { tcx: cx.tcx, def_id: debug }, ); } } @@ -958,19 +943,11 @@ impl EarlyLintPass for AnonymousParameters { } else { ("", Applicability::HasPlaceholders) }; - cx.struct_span_lint( + cx.emit_spanned_lint( ANONYMOUS_PARAMETERS, arg.pat.span, - fluent::lint_builtin_anonymous_params, - |lint| { - lint.span_suggestion( - arg.pat.span, - fluent::suggestion, - format!("_: {}", ty_snip), - appl, - ) - }, - ) + BuiltinAnonymousParams { suggestion: (arg.pat.span, appl), ty_snip }, + ); } } } @@ -1029,18 +1006,12 @@ impl EarlyLintPass for DeprecatedAttr { } } if attr.has_name(sym::no_start) || attr.has_name(sym::crate_id) { - cx.struct_span_lint( + cx.emit_spanned_lint( DEPRECATED, attr.span, - fluent::lint_builtin_deprecated_attr_used, - |lint| { - lint.set_arg("name", pprust::path_to_string(&attr.get_normal_item().path)) - .span_suggestion_short( - attr.span, - fluent::lint_builtin_deprecated_attr_default_suggestion, - "", - Applicability::MachineApplicable, - ) + BuiltinDeprecatedAttrUsed { + name: pprust::path_to_string(&attr.get_normal_item().path), + suggestion: attr.span, }, ); } @@ -1069,20 +1040,18 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: & let span = sugared_span.take().unwrap_or(attr.span); if is_doc_comment || attr.has_name(sym::doc) { - cx.struct_span_lint( + let sub = match attr.kind { + AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => { + BuiltinUnusedDocCommentSub::PlainHelp + } + AttrKind::DocComment(CommentKind::Block, _) => { + BuiltinUnusedDocCommentSub::BlockHelp + } + }; + cx.emit_spanned_lint( UNUSED_DOC_COMMENTS, span, - fluent::lint_builtin_unused_doc_comment, - |lint| { - lint.set_arg("kind", node_kind).span_label(node_span, fluent::label).help( - match attr.kind { - AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => { - fluent::plain_help - } - AttrKind::DocComment(CommentKind::Block, _) => fluent::block_help, - }, - ) - }, + BuiltinUnusedDocComment { kind: node_kind, label: node_span, sub }, ); } } @@ -1197,20 +1166,10 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { match param.kind { GenericParamKind::Lifetime { .. } => {} GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { - cx.struct_span_lint( + cx.emit_spanned_lint( NO_MANGLE_GENERIC_ITEMS, span, - fluent::lint_builtin_no_mangle_generic, - |lint| { - lint.span_suggestion_short( - no_mangle_attr.span, - fluent::suggestion, - "", - // Use of `#[no_mangle]` suggests FFI intent; correct - // fix may be to monomorphize source by hand - Applicability::MaybeIncorrect, - ) - }, + BuiltinNoMangleGeneric { suggestion: no_mangle_attr.span }, ); break; } @@ -1225,30 +1184,23 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { } hir::ItemKind::Const(..) => { if cx.sess().contains_name(attrs, sym::no_mangle) { + // account for "pub const" (#45562) + let start = cx + .tcx + .sess + .source_map() + .span_to_snippet(it.span) + .map(|snippet| snippet.find("const").unwrap_or(0)) + .unwrap_or(0) as u32; + // `const` is 5 chars + let suggestion = it.span.with_hi(BytePos(it.span.lo().0 + start + 5)); + // Const items do not refer to a particular location in memory, and therefore // don't have anything to attach a symbol to - cx.struct_span_lint( + cx.emit_spanned_lint( NO_MANGLE_CONST_ITEMS, it.span, - fluent::lint_builtin_const_no_mangle, - |lint| { - // account for "pub const" (#45562) - let start = cx - .tcx - .sess - .source_map() - .span_to_snippet(it.span) - .map(|snippet| snippet.find("const").unwrap_or(0)) - .unwrap_or(0) as u32; - // `const` is 5 chars - let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5)); - lint.span_suggestion( - const_span, - fluent::suggestion, - "pub static", - Applicability::MachineApplicable, - ) - }, + BuiltinConstNoMangle { suggestion }, ); } } @@ -1309,12 +1261,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes { get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind())) { if from_mutbl < to_mutbl { - cx.struct_span_lint( - MUTABLE_TRANSMUTES, - expr.span, - fluent::lint_builtin_mutable_transmutes, - |lint| lint, - ); + cx.emit_spanned_lint(MUTABLE_TRANSMUTES, expr.span, BuiltinMutablesTransmutes); } } @@ -1362,12 +1309,7 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures { if attr.has_name(sym::feature) { if let Some(items) = attr.meta_item_list() { for item in items { - cx.struct_span_lint( - UNSTABLE_FEATURES, - item.span(), - fluent::lint_builtin_unstable_features, - |lint| lint, - ); + cx.emit_spanned_lint(UNSTABLE_FEATURES, item.span(), BuiltinUnstableFeatures); } } } @@ -1493,18 +1435,13 @@ impl UnreachablePub { applicability = Applicability::MaybeIncorrect; } let def_span = cx.tcx.def_span(def_id); - cx.struct_span_lint( + cx.emit_spanned_lint( UNREACHABLE_PUB, def_span, - fluent::lint_builtin_unreachable_pub, - |lint| { - lint.set_arg("what", what); - - lint.span_suggestion(vis_span, fluent::suggestion, "pub(crate)", applicability); - if exportable { - lint.help(fluent::help); - } - lint + BuiltinUnreachablePub { + what, + suggestion: (vis_span, applicability), + help: exportable.then_some(()), }, ); } @@ -1767,14 +1704,10 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { TypeWellFormedFromEnv(..) => continue, }; if predicate.is_global() { - cx.struct_span_lint( + cx.emit_spanned_lint( TRIVIAL_BOUNDS, span, - fluent::lint_builtin_trivial_bounds, - |lint| { - lint.set_arg("predicate_kind_name", predicate_kind_name) - .set_arg("predicate", predicate) - }, + BuiltinTrivialBounds { predicate_kind_name, predicate }, ); } } @@ -1875,8 +1808,6 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { }; if let Some((start, end, join)) = endpoints { - let msg = fluent::lint_builtin_ellipsis_inclusive_range_patterns; - let suggestion = fluent::suggestion; if parenthesise { self.node_id = Some(pat.id); let end = expr_to_string(&end); @@ -1891,14 +1822,14 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { replace, }); } else { - cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, msg, |lint| { - lint.span_suggestion( - pat.span, - suggestion, + cx.emit_spanned_lint( + ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, + pat.span, + BuiltinEllipsisInclusiveRangePatternsLint::Parenthesise { + suggestion: pat.span, replace, - Applicability::MachineApplicable, - ) - }); + }, + ); } } else { let replace = "..="; @@ -1909,14 +1840,13 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { replace: replace.to_string(), }); } else { - cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, msg, |lint| { - lint.span_suggestion_short( - join, - suggestion, - replace, - Applicability::MachineApplicable, - ) - }); + cx.emit_spanned_lint( + ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, + join, + BuiltinEllipsisInclusiveRangePatternsLint::NonParenthesise { + suggestion: join, + }, + ); } }; } @@ -1996,12 +1926,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems { let attrs = cx.tcx.hir().attrs(it.hir_id()); if let Some(attr) = cx.sess().find_by_name(attrs, sym::rustc_test_marker) { - cx.struct_span_lint( - UNNAMEABLE_TEST_ITEMS, - attr.span, - fluent::lint_builtin_unnameable_test_items, - |lint| lint, - ); + cx.emit_spanned_lint(UNNAMEABLE_TEST_ITEMS, attr.span, BuiltinUnnameableTestItems); } } @@ -2117,18 +2042,10 @@ impl KeywordIdents { return; } - cx.struct_span_lint( + cx.emit_spanned_lint( KEYWORD_IDENTS, ident.span, - fluent::lint_builtin_keyword_idents, - |lint| { - lint.set_arg("kw", ident).set_arg("next", next_edition).span_suggestion( - ident.span, - fluent::suggestion, - format!("r#{}", ident), - Applicability::MachineApplicable, - ) - }, + BuiltinKeywordIdents { kw: ident, next: next_edition, suggestion: ident.span }, ); } } @@ -2405,16 +2322,15 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { Applicability::MaybeIncorrect }; - cx.struct_span_lint( + cx.emit_spanned_lint( EXPLICIT_OUTLIVES_REQUIREMENTS, lint_spans.clone(), - fluent::lint_builtin_explicit_outlives, - |lint| { - lint.set_arg("count", bound_count).multipart_suggestion( - fluent::suggestion, - lint_spans.into_iter().map(|span| (span, String::new())).collect(), + BuiltinExplicitOutlives { + count: bound_count, + suggestion: BuiltinExplicitOutlivesSuggestion { + spans: lint_spans, applicability, - ) + }, }, ); } @@ -2463,24 +2379,15 @@ impl EarlyLintPass for IncompleteFeatures { .chain(features.declared_lib_features.iter().map(|(name, span)| (name, span))) .filter(|(&name, _)| features.incomplete(name)) .for_each(|(&name, &span)| { - cx.struct_span_lint( + cx.emit_spanned_lint( INCOMPLETE_FEATURES, span, - fluent::lint_builtin_incomplete_features, - |lint| { - lint.set_arg("name", name); - if let Some(n) = - rustc_feature::find_feature_issue(name, GateIssue::Language) - { - lint.set_arg("n", n); - lint.note(fluent::note); - } - if HAS_MIN_FEATURES.contains(&name) { - lint.help(fluent::help); - } - lint + BuiltinIncompleteFeatures { + name, + note: rustc_feature::find_feature_issue(name, GateIssue::Language), + help: HAS_MIN_FEATURES.contains(&name).then_some(()), }, - ) + ); }); } } @@ -3275,11 +3182,10 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr { if let rustc_hir::ExprKind::Unary(rustc_hir::UnOp::Deref, expr_deref) = expr.kind { if is_null_ptr(cx, expr_deref) { - cx.struct_span_lint( + cx.emit_spanned_lint( DEREF_NULLPTR, expr.span, - fluent::lint_builtin_deref_nullptr, - |lint| lint.span_label(expr.span, fluent::label), + BuiltinDerefNullptr { label: expr.span }, ); } } @@ -3464,16 +3370,17 @@ impl EarlyLintPass for SpecialModuleName { } match item.ident.name.as_str() { - "lib" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, "found module declaration for lib.rs", |lint| { - lint - .note("lib.rs is the root of this crate's library target") - .help("to refer to it from other targets, use the library's name as the path") - }), - "main" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, "found module declaration for main.rs", |lint| { - lint - .note("a binary crate cannot be used as library") - }), - _ => continue + "lib" => cx.emit_spanned_lint( + SPECIAL_MODULE_NAME, + item.span, + BuiltinSpecialModuleNameUsed::Lib, + ), + "main" => cx.emit_spanned_lint( + SPECIAL_MODULE_NAME, + item.span, + BuiltinSpecialModuleNameUsed::Main, + ), + _ => continue, } } } @@ -3489,31 +3396,16 @@ impl EarlyLintPass for UnexpectedCfgs { let cfg = &cx.sess().parse_sess.config; let check_cfg = &cx.sess().parse_sess.check_config; for &(name, value) in cfg { - if let Some(names_valid) = &check_cfg.names_valid { - if !names_valid.contains(&name) { - cx.lookup( - UNEXPECTED_CFGS, - None::, - fluent::lint_builtin_unexpected_cli_config_name, - |diag| diag.help(fluent::help).set_arg("name", name), - ); - } + if let Some(names_valid) = &check_cfg.names_valid && !names_valid.contains(&name){ + cx.emit_lint(UNEXPECTED_CFGS, BuiltinUnexpectedCliConfigName { + name, + }); } - if let Some(value) = value { - if let Some(values) = &check_cfg.values_valid.get(&name) { - if !values.contains(&value) { - cx.lookup( - UNEXPECTED_CFGS, - None::, - fluent::lint_builtin_unexpected_cli_config_value, - |diag| { - diag.help(fluent::help) - .set_arg("name", name) - .set_arg("value", value) - }, - ); - } - } + if let Some(value) = value && let Some(values) = check_cfg.values_valid.get(&name) && !values.contains(&value) { + cx.emit_lint( + UNEXPECTED_CFGS, + BuiltinUnexpectedCliConfigValue { name, value }, + ); } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 196922b78c30c..ceecc2c9501ee 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1,8 +1,10 @@ +use std::num::NonZeroU32; + use rustc_errors::{fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage}; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{Predicate, Ty, TyCtxt}; -use rustc_span::{symbol::Ident, Span, Symbol}; +use rustc_span::{edition::Edition, symbol::Ident, Span, Symbol}; use crate::{errors::OverruledAttributeSub, LateContext}; @@ -33,6 +35,259 @@ pub enum ArrayIntoIterDiagSub { }, } +// builtin.rs +#[derive(LintDiagnostic)] +#[diag(lint_builtin_while_true)] +pub struct BuiltinWhileTrue { + #[suggestion(style = "short", code = "{replace}", applicability = "machine-applicable")] + pub suggestion: Span, + pub replace: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_box_pointers)] +pub struct BuiltinBoxPointers<'a> { + pub ty: Ty<'a>, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_non_shorthand_field_patterns)] +pub struct BuiltinNonShorthandFieldPatterns { + pub ident: Ident, + #[suggestion(code = "{prefix}{ident}", applicability = "machine-applicable")] + pub suggestion: Span, + pub prefix: &'static str, +} + +// FIXME: add lint::unsafe_code + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_missing_doc)] +pub struct BuiltinMissingDoc<'a> { + pub article: &'a str, + pub desc: &'a str, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_missing_copy_impl)] +pub struct BuiltinMissingCopyImpl; + +pub struct BuiltinMissingDebugImpl<'a> { + pub tcx: TyCtxt<'a>, + pub def_id: DefId, +} + +impl<'a> DecorateLint<'a, ()> for BuiltinMissingDebugImpl<'_> { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { + diag.set_arg("debug", self.tcx.def_path_str(self.def_id)); + diag + } + + fn msg(&self) -> DiagnosticMessage { + fluent::lint_builtin_missing_debug_impl + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_anonymous_params)] +pub struct BuiltinAnonymousParams<'a> { + #[suggestion(code = "_: {ty_snip}")] + pub suggestion: (Span, Applicability), + pub ty_snip: &'a str, +} + +// FIXME: add lint::builtin_deprecated_attr_link + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_deprecated_attr_used)] +pub struct BuiltinDeprecatedAttrUsed { + pub name: String, + #[suggestion( + lint_builtin_deprecated_attr_default_suggestion, + style = "short", + code = "", + applicability = "machine-applicable" + )] + pub suggestion: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_unused_doc_comment)] +pub struct BuiltinUnusedDocComment<'a> { + pub kind: &'a str, + #[label] + pub label: Span, + #[subdiagnostic] + pub sub: BuiltinUnusedDocCommentSub, +} + +#[derive(Subdiagnostic)] +pub enum BuiltinUnusedDocCommentSub { + #[help(plain_help)] + PlainHelp, + #[help(block_help)] + BlockHelp, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_no_mangle_generic)] +pub struct BuiltinNoMangleGeneric { + // Use of `#[no_mangle]` suggests FFI intent; correct + // fix may be to monomorphize source by hand + #[suggestion(style = "short", code = "", applicability = "maybe-incorrect")] + pub suggestion: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_const_no_mangle)] +pub struct BuiltinConstNoMangle { + #[suggestion(code = "pub static", applicability = "machine-applicable")] + pub suggestion: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_mutable_transmutes)] +pub struct BuiltinMutablesTransmutes; + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_unstable_features)] +pub struct BuiltinUnstableFeatures; + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_unreachable_pub)] +pub struct BuiltinUnreachablePub<'a> { + pub what: &'a str, + #[suggestion(code = "pub(crate)")] + pub suggestion: (Span, Applicability), + #[help] + pub help: Option<()>, +} + +// FIXME: migrate builtin_type_alias_where_clause + +// FIXME: migrate builtin_type_alias_generic_bounds + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_trivial_bounds)] +pub struct BuiltinTrivialBounds<'a> { + pub predicate_kind_name: &'a str, + pub predicate: Predicate<'a>, +} + +#[derive(LintDiagnostic)] +pub enum BuiltinEllipsisInclusiveRangePatternsLint { + #[diag(lint_builtin_ellipsis_inclusive_range_patterns)] + Parenthesise { + #[suggestion(code = "{replace}", applicability = "machine-applicable")] + suggestion: Span, + replace: String, + }, + #[diag(lint_builtin_ellipsis_inclusive_range_patterns)] + NonParenthesise { + #[suggestion(style = "short", code = "..=", applicability = "machine-applicable")] + suggestion: Span, + }, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_unnameable_test_items)] +pub struct BuiltinUnnameableTestItems; + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_keyword_idents)] +pub struct BuiltinKeywordIdents { + pub kw: Ident, + pub next: Edition, + #[suggestion(code = "r#{kw}", applicability = "machine-applicable")] + pub suggestion: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_explicit_outlives)] +pub struct BuiltinExplicitOutlives { + pub count: usize, + #[subdiagnostic] + pub suggestion: BuiltinExplicitOutlivesSuggestion, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(suggestion)] +pub struct BuiltinExplicitOutlivesSuggestion { + #[suggestion_part(code = "")] + pub spans: Vec, + #[applicability] + pub applicability: Applicability, +} + +pub struct BuiltinIncompleteFeatures { + pub name: Symbol, + pub note: Option, + pub help: Option<()>, +} + +impl<'a> DecorateLint<'a, ()> for BuiltinIncompleteFeatures { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { + diag.set_arg("name", self.name); + if let Some(n) = self.note { + diag.set_arg("n", n); + diag.note(fluent::note); + } + if let Some(_) = self.help { + diag.help(fluent::help); + } + diag + } + + fn msg(&self) -> DiagnosticMessage { + fluent::lint_builtin_incomplete_features + } +} + +// FIXME: migrate "the type `{}` does not permit {}" + +// FIXME: fluent::lint::builtin_clashing_extern_{same,diff}_name + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_deref_nullptr)] +pub struct BuiltinDerefNullptr { + #[label] + pub label: Span, +} + +// FIXME: migrate fluent::lint::builtin_asm_labels + +#[derive(LintDiagnostic)] +pub enum BuiltinSpecialModuleNameUsed { + #[diag(lint_builtin_special_module_name_used_lib)] + #[note] + #[help] + Lib, + #[diag(lint_builtin_special_module_name_used_main)] + #[note] + Main, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_unexpected_cli_config_name)] +#[help] +pub struct BuiltinUnexpectedCliConfigName { + pub name: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_unexpected_cli_config_value)] +#[help] +pub struct BuiltinUnexpectedCliConfigValue { + pub name: Symbol, + pub value: Symbol, +} + // enum_intrinsics_non_enums.rs #[derive(LintDiagnostic)] #[diag(lint_enum_intrinsics_mem_discriminant)] From 3c1a1f3643efb57b9bba515fc753d84ce39819e0 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Wed, 9 Nov 2022 18:22:48 -0500 Subject: [PATCH 24/33] migrate: `expect.rs` --- compiler/rustc_lint/src/expect.rs | 40 +++++++++---------------------- compiler/rustc_lint/src/lints.rs | 31 +++++++++++++++++++++++- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index cf8f31bcbd065..c0e62a8d9fc09 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -1,8 +1,9 @@ -use crate::builtin; -use rustc_errors::fluent; -use rustc_hir::HirId; +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +use crate::lints::Expectation; use rustc_middle::ty::query::Providers; -use rustc_middle::{lint::LintExpectation, ty::TyCtxt}; +use rustc_middle::ty::TyCtxt; +use rustc_session::lint::builtin::UNFULFILLED_LINT_EXPECTATIONS; use rustc_session::lint::LintExpectationId; use rustc_span::symbol::sym; use rustc_span::Symbol; @@ -28,34 +29,15 @@ fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option) { if !fulfilled_expectations.contains(&id) && tool_filter.map_or(true, |filter| expectation.lint_tool == Some(filter)) { - emit_unfulfilled_expectation_lint(tcx, *hir_id, expectation); + tcx.emit_spanned_lint( + UNFULFILLED_LINT_EXPECTATIONS, + *hir_id, + expectation.emission_span, + Expectation { expectation }, + ); } } else { unreachable!("at this stage all `LintExpectationId`s are stable"); } } } - -fn emit_unfulfilled_expectation_lint( - tcx: TyCtxt<'_>, - hir_id: HirId, - expectation: &LintExpectation, -) { - tcx.struct_span_lint_hir( - builtin::UNFULFILLED_LINT_EXPECTATIONS, - hir_id, - expectation.emission_span, - fluent::lint_expectation, - |lint| { - if let Some(rationale) = expectation.reason { - lint.note(rationale.as_str()); - } - - if expectation.is_unfulfilled_lint_expectations { - lint.note(fluent::note); - } - - lint - }, - ); -} diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index ceecc2c9501ee..782cf668b290b 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3,7 +3,10 @@ use std::num::NonZeroU32; use rustc_errors::{fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage}; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; -use rustc_middle::ty::{Predicate, Ty, TyCtxt}; +use rustc_middle::{ + lint::LintExpectation, + ty::{Predicate, Ty, TyCtxt}, +}; use rustc_span::{edition::Edition, symbol::Ident, Span, Symbol}; use crate::{errors::OverruledAttributeSub, LateContext}; @@ -304,6 +307,32 @@ pub struct EnumIntrinsicsMemVariant<'a> { pub ty_param: Ty<'a>, } +// expect.rs +pub struct Expectation<'a> { + pub expectation: &'a LintExpectation, +} + +impl<'a> DecorateLint<'a, ()> for Expectation<'_> { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { + if let Some(rationale) = self.expectation.reason { + diag.note(rationale.as_str()); + } + + if self.expectation.is_unfulfilled_lint_expectations { + diag.note(fluent::note); + } + + diag + } + + fn msg(&self) -> DiagnosticMessage { + fluent::lint_expectation + } +} + // internal.rs #[derive(LintDiagnostic)] #[diag(lint_default_hash_types)] From ca7df9a2a9c4b1f751e91040fe659f682c976919 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Wed, 9 Nov 2022 19:34:49 -0500 Subject: [PATCH 25/33] migrate: `for_loops_over_fallibles.rs` --- .../locales/en-US/lint.ftl | 7 ++ .../src/for_loops_over_fallibles.rs | 75 +++++++------------ compiler/rustc_lint/src/lints.rs | 49 ++++++++++++ 3 files changed, 85 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl index 1080ba2d2b565..5330ce504b2c2 100644 --- a/compiler/rustc_error_messages/locales/en-US/lint.ftl +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -16,6 +16,13 @@ lint_enum_intrinsics_mem_variant = lint_expectation = this lint expectation is unfulfilled .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message +lint_for_loops_over_fallibles = + for loop over {$article} `{$ty}`. This is more readably written as an `if let` statement + .suggestion = consider using `if let` to clear intent + .remove_next = to iterate over `{$recv_snip}` remove the call to `next` + .use_while_let = to check pattern in a loop use `while let` + .use_question_mark = consider unwrapping the `Result` with `?` to iterate over its contents + lint_non_binding_let_on_sync_lock = non-binding let on a synchronization lock diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index 182734fa9fc8f..7526b8c06327a 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -1,7 +1,14 @@ -use crate::{LateContext, LateLintPass, LintContext}; +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +use crate::{ + lints::{ + ForLoopsOverFalliblesDiag, ForLoopsOverFalliblesLoopSub, ForLoopsOverFalliblesQuestionMark, + ForLoopsOverFalliblesSuggestion, + }, + LateContext, LateLintPass, LintContext, +}; use hir::{Expr, Pat}; -use rustc_errors::{Applicability, DelayDm}; use rustc_hir as hir; use rustc_infer::{infer::TyCtxtInferExt, traits::ObligationCause}; use rustc_middle::ty::{self, List}; @@ -53,53 +60,29 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles { _ => return, }; - let msg = DelayDm(|| { - format!( - "for loop over {article} `{ty}`. This is more readably written as an `if let` statement", - ) - }); - - cx.struct_span_lint(FOR_LOOPS_OVER_FALLIBLES, arg.span, msg, |lint| { - if let Some(recv) = extract_iterator_next_call(cx, arg) + let sub = if let Some(recv) = extract_iterator_next_call(cx, arg) && let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span) { - lint.span_suggestion( - recv.span.between(arg.span.shrink_to_hi()), - format!("to iterate over `{recv_snip}` remove the call to `next`"), - ".by_ref()", - Applicability::MaybeIncorrect - ); + ForLoopsOverFalliblesLoopSub::RemoveNext { suggestion: recv.span.between(arg.span.shrink_to_hi()), recv_snip } } else { - lint.multipart_suggestion_verbose( - "to check pattern in a loop use `while let`", - vec![ - // NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts - (expr.span.with_hi(pat.span.lo()), format!("while let {var}(")), - (pat.span.between(arg.span), ") = ".to_string()), - ], - Applicability::MaybeIncorrect - ); - } - - if suggest_question_mark(cx, adt, substs, expr.span) { - lint.span_suggestion( - arg.span.shrink_to_hi(), - "consider unwrapping the `Result` with `?` to iterate over its contents", - "?", - Applicability::MaybeIncorrect, - ); - } - - lint.multipart_suggestion_verbose( - "consider using `if let` to clear intent", - vec![ - // NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts - (expr.span.with_hi(pat.span.lo()), format!("if let {var}(")), - (pat.span.between(arg.span), ") = ".to_string()), - ], - Applicability::MaybeIncorrect, - ) - }) + ForLoopsOverFalliblesLoopSub::UseWhileLet { start_span: expr.span.with_hi(pat.span.lo()), end_span: pat.span.between(arg.span), var } + } ; + let question_mark = if suggest_question_mark(cx, adt, substs, expr.span) { + Some(ForLoopsOverFalliblesQuestionMark { suggestion: arg.span.shrink_to_hi() }) + } else { + None + }; + let suggestion = ForLoopsOverFalliblesSuggestion { + var, + start_span: expr.span.with_hi(pat.span.lo()), + end_span: pat.span.between(arg.span), + }; + + cx.emit_spanned_lint( + FOR_LOOPS_OVER_FALLIBLES, + arg.span, + ForLoopsOverFalliblesDiag { article, ty, sub, question_mark, suggestion }, + ); } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 782cf668b290b..a354934660406 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -333,6 +333,55 @@ impl<'a> DecorateLint<'a, ()> for Expectation<'_> { } } +// for_loops_over_fallibles.rs +#[derive(LintDiagnostic)] +#[diag(lint_for_loops_over_fallibles)] +pub struct ForLoopsOverFalliblesDiag<'a> { + pub article: &'static str, + pub ty: &'static str, + #[subdiagnostic] + pub sub: ForLoopsOverFalliblesLoopSub<'a>, + #[subdiagnostic] + pub question_mark: Option, + #[subdiagnostic] + pub suggestion: ForLoopsOverFalliblesSuggestion<'a>, +} + +#[derive(Subdiagnostic)] +pub enum ForLoopsOverFalliblesLoopSub<'a> { + #[suggestion(remove_next, code = ".by_ref()", applicability = "maybe-incorrect")] + RemoveNext { + #[primary_span] + suggestion: Span, + recv_snip: String, + }, + #[multipart_suggestion(use_while_let, applicability = "maybe-incorrect")] + UseWhileLet { + #[suggestion_part(code = "while let {var}(")] + start_span: Span, + #[suggestion_part(code = ") = ")] + end_span: Span, + var: &'a str, + }, +} + +#[derive(Subdiagnostic)] +#[suggestion(use_question_mark, code = "?", applicability = "maybe-incorrect")] +pub struct ForLoopsOverFalliblesQuestionMark { + #[primary_span] + pub suggestion: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(suggestion, applicability = "maybe-incorrect")] +pub struct ForLoopsOverFalliblesSuggestion<'a> { + pub var: &'a str, + #[suggestion_part(code = "if let {var}(")] + pub start_span: Span, + #[suggestion_part(code = ") = ")] + pub end_span: Span, +} + // internal.rs #[derive(LintDiagnostic)] #[diag(lint_default_hash_types)] From 78fce795d8084e288278270438a49df6172dd36c Mon Sep 17 00:00:00 2001 From: Rejyr Date: Thu, 10 Nov 2022 19:32:30 -0500 Subject: [PATCH 26/33] refactor: refactor to derive for some lints. --- .../locales/en-US/lint.ftl | 4 +- compiler/rustc_lint/src/builtin.rs | 16 +- compiler/rustc_lint/src/expect.rs | 6 +- compiler/rustc_lint/src/levels.rs | 13 +- compiler/rustc_lint/src/lints.rs | 174 +++++++----------- compiler/rustc_lint/src/types.rs | 26 +-- 6 files changed, 99 insertions(+), 140 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl index 5330ce504b2c2..1518adf8e4e24 100644 --- a/compiler/rustc_error_messages/locales/en-US/lint.ftl +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -15,6 +15,7 @@ lint_enum_intrinsics_mem_variant = 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_for_loops_over_fallibles = for loop over {$article} `{$ty}`. This is more readably written as an `if let` statement @@ -39,7 +40,8 @@ lint_deprecated_lint_name = lint name `{$name}` is deprecated and may not have an effect in the future. .suggestion = change it to -lint_renamed_or_removed_lint_suggestion = use the new name +lint_renamed_or_removed_lint = {$msg} + .suggestion = use the new name lint_unknown_lint = unknown lint: `{$name}` diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 8a34afb1ff524..1dae563577a01 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -26,7 +26,8 @@ use crate::{ BuiltinAnonymousParams, BuiltinBoxPointers, BuiltinConstNoMangle, BuiltinDeprecatedAttrUsed, BuiltinDerefNullptr, BuiltinEllipsisInclusiveRangePatternsLint, BuiltinExplicitOutlives, BuiltinExplicitOutlivesSuggestion, BuiltinIncompleteFeatures, - BuiltinKeywordIdents, BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, + BuiltinIncompleteFeaturesHelp, BuiltinIncompleteFeaturesNote, BuiltinKeywordIdents, + BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinUnexpectedCliConfigName, BuiltinUnexpectedCliConfigValue, BuiltinUnnameableTestItems, BuiltinUnreachablePub, @@ -2379,14 +2380,17 @@ impl EarlyLintPass for IncompleteFeatures { .chain(features.declared_lib_features.iter().map(|(name, span)| (name, span))) .filter(|(&name, _)| features.incomplete(name)) .for_each(|(&name, &span)| { + let note = rustc_feature::find_feature_issue(name, GateIssue::Language) + .map(|n| BuiltinIncompleteFeaturesNote { n }); + let help = if HAS_MIN_FEATURES.contains(&name) { + Some(BuiltinIncompleteFeaturesHelp) + } else { + None + }; cx.emit_spanned_lint( INCOMPLETE_FEATURES, span, - BuiltinIncompleteFeatures { - name, - note: rustc_feature::find_feature_issue(name, GateIssue::Language), - help: HAS_MIN_FEATURES.contains(&name).then_some(()), - }, + BuiltinIncompleteFeatures { name, note, help }, ); }); } diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index c0e62a8d9fc09..8985ccee0cdf4 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -1,6 +1,6 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -use crate::lints::Expectation; +use crate::lints::{Expectation, ExpectationNote}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::UNFULFILLED_LINT_EXPECTATIONS; @@ -29,11 +29,13 @@ fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option) { if !fulfilled_expectations.contains(&id) && tool_filter.map_or(true, |filter| expectation.lint_tool == Some(filter)) { + let rationale = expectation.reason.map(|rationale| ExpectationNote { rationale }); + let note = expectation.is_unfulfilled_lint_expectations.then_some(()); tcx.emit_spanned_lint( UNFULFILLED_LINT_EXPECTATIONS, *hir_id, expectation.emission_span, - Expectation { expectation }, + Expectation { rationale, note }, ); } } else { diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index b335f330f5d41..500b1f36558d7 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -4,7 +4,7 @@ use crate::context::{CheckLintNameResult, LintStore}; use crate::late::unerased_lint_store; use crate::lints::{ DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAtributeLint, RenamedOrRemovedLint, - UnknownLint, + RenamedOrRemovedLintSuggestion, UnknownLint, UnknownLintSuggestion, }; use rustc_ast as ast; use rustc_ast_pretty::pprust; @@ -887,10 +887,15 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { _ if !self.warn_about_weird_lints => {} CheckLintNameResult::Warning(msg, renamed) => { + let suggestion = + renamed.as_ref().map(|replace| RenamedOrRemovedLintSuggestion { + suggestion: sp, + replace: replace.as_str(), + }); self.emit_spanned_lint( RENAMED_AND_REMOVED_LINTS, sp.into(), - RenamedOrRemovedLint { msg, suggestion: sp, renamed }, + RenamedOrRemovedLint { msg, suggestion }, ); } CheckLintNameResult::NoLint(suggestion) => { @@ -899,10 +904,12 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } else { name.to_string() }; + let suggestion = suggestion + .map(|replace| UnknownLintSuggestion { suggestion: sp, replace }); self.emit_spanned_lint( UNKNOWN_LINTS, sp.into(), - UnknownLint { name, suggestion: sp, replace: suggestion }, + UnknownLint { name, suggestion }, ); } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index a354934660406..faeb396ce8ca1 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3,10 +3,7 @@ use std::num::NonZeroU32; use rustc_errors::{fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage}; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; -use rustc_middle::{ - lint::LintExpectation, - ty::{Predicate, Ty, TyCtxt}, -}; +use rustc_middle::ty::{Predicate, Ty, TyCtxt}; use rustc_span::{edition::Edition, symbol::Ident, Span, Symbol}; use crate::{errors::OverruledAttributeSub, LateContext}; @@ -80,6 +77,7 @@ pub struct BuiltinMissingDebugImpl<'a> { pub def_id: DefId, } +// Needed for def_path_str impl<'a> DecorateLint<'a, ()> for BuiltinMissingDebugImpl<'_> { fn decorate_lint<'b>( self, @@ -225,31 +223,24 @@ pub struct BuiltinExplicitOutlivesSuggestion { pub applicability: Applicability, } +#[derive(LintDiagnostic)] +#[diag(lint_builtin_incomplete_features)] pub struct BuiltinIncompleteFeatures { pub name: Symbol, - pub note: Option, - pub help: Option<()>, + #[subdiagnostic] + pub note: Option, + #[subdiagnostic] + pub help: Option, } -impl<'a> DecorateLint<'a, ()> for BuiltinIncompleteFeatures { - fn decorate_lint<'b>( - self, - diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, - ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { - diag.set_arg("name", self.name); - if let Some(n) = self.note { - diag.set_arg("n", n); - diag.note(fluent::note); - } - if let Some(_) = self.help { - diag.help(fluent::help); - } - diag - } +#[derive(Subdiagnostic)] +#[help(help)] +pub struct BuiltinIncompleteFeaturesHelp; - fn msg(&self) -> DiagnosticMessage { - fluent::lint_builtin_incomplete_features - } +#[derive(Subdiagnostic)] +#[note(note)] +pub struct BuiltinIncompleteFeaturesNote { + pub n: NonZeroU32, } // FIXME: migrate "the type `{}` does not permit {}" @@ -308,29 +299,19 @@ pub struct EnumIntrinsicsMemVariant<'a> { } // expect.rs -pub struct Expectation<'a> { - pub expectation: &'a LintExpectation, +#[derive(LintDiagnostic)] +#[diag(lint_expectation)] +pub struct Expectation { + #[subdiagnostic] + pub rationale: Option, + #[note] + pub note: Option<()>, } -impl<'a> DecorateLint<'a, ()> for Expectation<'_> { - fn decorate_lint<'b>( - self, - diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, - ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { - if let Some(rationale) = self.expectation.reason { - diag.note(rationale.as_str()); - } - - if self.expectation.is_unfulfilled_lint_expectations { - diag.note(fluent::note); - } - - diag - } - - fn msg(&self) -> DiagnosticMessage { - fluent::lint_expectation - } +#[derive(Subdiagnostic)] +#[note(rationale)] +pub struct ExpectationNote { + pub rationale: Symbol, } // for_loops_over_fallibles.rs @@ -511,59 +492,37 @@ pub struct DeprecatedLintName<'a> { pub replace: &'a str, } +// FIXME: Non-translatable msg +#[derive(LintDiagnostic)] +#[diag(lint_renamed_or_removed_lint)] pub struct RenamedOrRemovedLint<'a> { pub msg: &'a str, - pub suggestion: Span, - pub renamed: &'a Option, + #[subdiagnostic] + pub suggestion: Option>, } -impl<'a> DecorateLint<'a, ()> for RenamedOrRemovedLint<'_> { - fn decorate_lint<'b>( - self, - diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, - ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { - if let Some(new_name) = self.renamed { - diag.span_suggestion( - self.suggestion, - fluent::lint_renamed_or_removed_lint_suggestion, - new_name, - Applicability::MachineApplicable, - ); - }; - diag - } - - fn msg(&self) -> rustc_errors::DiagnosticMessage { - rustc_errors::DiagnosticMessage::Str(self.msg.to_string()) - } +#[derive(Subdiagnostic)] +#[suggestion(suggestion, code = "{replace}", applicability = "machine-applicable")] +pub struct RenamedOrRemovedLintSuggestion<'a> { + #[primary_span] + pub suggestion: Span, + pub replace: &'a str, } -pub struct UnknownLint<'a> { +#[derive(LintDiagnostic)] +#[diag(lint_unknown_lint)] +pub struct UnknownLint { pub name: String, - pub suggestion: Span, - pub replace: &'a Option, + #[subdiagnostic] + pub suggestion: Option, } -impl<'a> DecorateLint<'a, ()> for UnknownLint<'_> { - fn decorate_lint<'b>( - self, - diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, - ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { - diag.set_arg("name", self.name); - if let Some(replace) = self.replace { - diag.span_suggestion( - self.suggestion, - fluent::suggestion, - replace, - Applicability::MaybeIncorrect, - ); - }; - diag - } - - fn msg(&self) -> rustc_errors::DiagnosticMessage { - fluent::lint_unknown_lint - } +#[derive(Subdiagnostic)] +#[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")] +pub struct UnknownLintSuggestion { + #[primary_span] + pub suggestion: Span, + pub replace: Symbol, } #[derive(LintDiagnostic)] @@ -618,6 +577,7 @@ pub struct NonFmtPanicUnused { pub suggestion: Option, } +// Used because of two suggestions based on one Option impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused { fn decorate_lint<'b>( self, @@ -803,6 +763,7 @@ pub struct DropTraitConstraintsDiag<'a> { pub def_id: DefId, } +// Needed for def_path_str impl<'a> DecorateLint<'a, ()> for DropTraitConstraintsDiag<'_> { fn decorate_lint<'b>( self, @@ -822,6 +783,7 @@ pub struct DropGlue<'a> { pub def_id: DefId, } +// Needed for def_path_str impl<'a> DecorateLint<'a, ()> for DropGlue<'_> { fn decorate_lint<'b>( self, @@ -902,35 +864,22 @@ pub enum OverflowingBinHexSub<'a> { Help { suggestion_ty: &'a str }, } +#[derive(LintDiagnostic)] +#[diag(lint_overflowing_int)] +#[note] pub struct OverflowingInt<'a> { pub ty: &'a str, pub lit: String, pub min: i128, pub max: u128, - pub suggestion_ty: Option<&'a str>, + #[subdiagnostic] + pub help: Option>, } -// FIXME: refactor with `Option<&'a str>` in macro -impl<'a> DecorateLint<'a, ()> for OverflowingInt<'_> { - fn decorate_lint<'b>( - self, - diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, - ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { - diag.set_arg("ty", self.ty); - diag.set_arg("lit", self.lit); - diag.set_arg("min", self.min); - diag.set_arg("max", self.max); - diag.note(fluent::note); - if let Some(suggestion_ty) = self.suggestion_ty { - diag.set_arg("suggestion_ty", suggestion_ty); - diag.help(fluent::help); - } - diag - } - - fn msg(&self) -> rustc_errors::DiagnosticMessage { - fluent::lint_overflowing_int - } +#[derive(Subdiagnostic)] +#[help(help)] +pub struct OverflowingIntHelp<'a> { + pub suggestion_ty: &'a str, } #[derive(LintDiagnostic)] @@ -972,6 +921,7 @@ pub struct ImproperCTypes<'a> { pub span_note: Option, } +// Used because of the complexity of Option, DiagnosticMessage, and Option impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> { fn decorate_lint<'b>( self, @@ -1074,7 +1024,7 @@ pub struct UnusedDef<'a, 'b> { pub note: Option, } -// FIXME: refactor with `Option` in macro +// Needed because of def_path_str impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> { fn decorate_lint<'b>( self, diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index a112292eb1412..1300a2fe27aa3 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -3,7 +3,7 @@ use crate::lints::{ AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, - OverflowingBinHexSub, OverflowingInt, OverflowingLiteral, OverflowingUInt, + OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral, OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, VariantSizeDifferencesDiag, }; use crate::{LateContext, LateLintPass, LintContext}; @@ -339,24 +339,18 @@ fn lint_int_literal<'tcx>( return; } + let lit = cx + .sess() + .source_map() + .span_to_snippet(lit.span) + .expect("must get snippet from literal"); + let help = get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative) + .map(|suggestion_ty| OverflowingIntHelp { suggestion_ty }); + cx.emit_spanned_lint( OVERFLOWING_LITERALS, e.span, - OverflowingInt { - ty: t.name_str(), - lit: cx - .sess() - .source_map() - .span_to_snippet(lit.span) - .expect("must get snippet from literal"), - min, - max, - suggestion_ty: get_type_suggestion( - cx.typeck_results().node_type(e.hir_id), - v, - negative, - ), - }, + OverflowingInt { ty: t.name_str(), lit, min, max, help }, ); } } From ce72f942d7a9ba564332dd8b6afba05799f1f45e Mon Sep 17 00:00:00 2001 From: Rejyr Date: Thu, 10 Nov 2022 21:01:45 -0500 Subject: [PATCH 27/33] add: `#[rustc_lint_diagnostics]` for more `context.rs` functions. --- compiler/rustc_lint/src/context.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index a16bb7f1a5f47..de9e71d26e17f 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -13,6 +13,8 @@ //! previous lint state is pushed onto a stack and the ast is then recursed //! upon. As the ast is traversed, this keeps track of the current lint level //! for all lint attributes. +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] use self::TargetLint::*; @@ -965,6 +967,7 @@ pub trait LintContext: Sized { /// Note that this function should only be called for [`LintExpectationId`]s /// retrieved from the current lint pass. Buffered or manually created ids can /// cause ICEs. + #[rustc_lint_diagnostics] fn fulfill_expectation(&self, expectation: LintExpectationId) { // We need to make sure that submitted expectation ids are correctly fulfilled suppressed // and stored between compilation sessions. To not manually do these steps, we simply create @@ -1011,6 +1014,7 @@ impl<'tcx> LintContext for LateContext<'tcx> { &*self.lint_store } + #[rustc_lint_diagnostics] fn lookup>( &self, lint: &'static Lint, @@ -1045,6 +1049,7 @@ impl LintContext for EarlyContext<'_> { self.builder.lint_store() } + #[rustc_lint_diagnostics] fn lookup>( &self, lint: &'static Lint, From c06a2426b2d260b39b1601dd732777df667428ed Mon Sep 17 00:00:00 2001 From: Rejyr Date: Fri, 11 Nov 2022 22:39:37 -0500 Subject: [PATCH 28/33] migrate: `hidden_unicode_codepoints.rs` --- .../src/hidden_unicode_codepoints.rs | 67 ++++---------- compiler/rustc_lint/src/lints.rs | 90 ++++++++++++++++++- 2 files changed, 107 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs index dc2f5c0e2967e..7c1af6bee1dd6 100644 --- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs +++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs @@ -1,7 +1,12 @@ -use crate::{EarlyContext, EarlyLintPass, LintContext}; +use crate::{ + lints::{ + HiddenUnicodeCodepointsDiag, HiddenUnicodeCodepointsDiagLabels, + HiddenUnicodeCodepointsDiagSub, + }, + EarlyContext, EarlyLintPass, LintContext, +}; use ast::util::unicode::{contains_text_flow_control_chars, TEXT_FLOW_CONTROL_CHARS}; use rustc_ast as ast; -use rustc_errors::{fluent, Applicability, SuggestionStyle}; use rustc_span::{BytePos, Span, Symbol}; declare_lint! { @@ -60,55 +65,19 @@ impl HiddenUnicodeCodepoints { }) .collect(); - cx.struct_span_lint( + let count = spans.len(); + let labels = point_at_inner_spans + .then_some(HiddenUnicodeCodepointsDiagLabels { spans: spans.clone() }); + let sub = if point_at_inner_spans && !spans.is_empty() { + HiddenUnicodeCodepointsDiagSub::Escape { spans } + } else { + HiddenUnicodeCodepointsDiagSub::NoEscape { spans } + }; + + cx.emit_spanned_lint( TEXT_DIRECTION_CODEPOINT_IN_LITERAL, span, - fluent::lint_hidden_unicode_codepoints, - |lint| { - lint.set_arg("label", label); - lint.set_arg("count", spans.len()); - lint.span_label(span, fluent::label); - lint.note(fluent::note); - if point_at_inner_spans { - for (c, span) in &spans { - lint.span_label(*span, format!("{:?}", c)); - } - } - if point_at_inner_spans && !spans.is_empty() { - lint.multipart_suggestion_with_style( - fluent::suggestion_remove, - spans.iter().map(|(_, span)| (*span, "".to_string())).collect(), - Applicability::MachineApplicable, - SuggestionStyle::HideCodeAlways, - ); - lint.multipart_suggestion( - fluent::suggestion_escape, - spans - .into_iter() - .map(|(c, span)| { - let c = format!("{:?}", c); - (span, c[1..c.len() - 1].to_string()) - }) - .collect(), - Applicability::MachineApplicable, - ); - } else { - // FIXME: in other suggestions we've reversed the inner spans of doc comments. We - // should do the same here to provide the same good suggestions as we do for - // literals above. - lint.set_arg( - "escaped", - spans - .into_iter() - .map(|(c, _)| format!("{:?}", c)) - .collect::>() - .join(", "), - ); - lint.note(fluent::suggestion_remove); - lint.note(fluent::no_suggestion_note_escape); - } - lint - }, + HiddenUnicodeCodepointsDiag { label, count, span_label: span, labels, sub }, ); } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index faeb396ce8ca1..4da099dcc1d6b 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1,6 +1,8 @@ use std::num::NonZeroU32; -use rustc_errors::{fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage}; +use rustc_errors::{ + fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage, SuggestionStyle, +}; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{Predicate, Ty, TyCtxt}; @@ -363,6 +365,92 @@ pub struct ForLoopsOverFalliblesSuggestion<'a> { pub end_span: Span, } +// hidden_unicode_codepoints.rs +#[derive(LintDiagnostic)] +#[diag(lint_hidden_unicode_codepoints)] +#[note] +pub struct HiddenUnicodeCodepointsDiag<'a> { + pub label: &'a str, + pub count: usize, + #[label] + pub span_label: Span, + #[subdiagnostic] + pub labels: Option, + #[subdiagnostic] + pub sub: HiddenUnicodeCodepointsDiagSub, +} + +pub struct HiddenUnicodeCodepointsDiagLabels { + pub spans: Vec<(char, Span)>, +} + +impl AddToDiagnostic for HiddenUnicodeCodepointsDiagLabels { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { + for (c, span) in self.spans { + diag.span_label(span, format!("{:?}", c)); + } + } +} + +pub enum HiddenUnicodeCodepointsDiagSub { + Escape { spans: Vec<(char, Span)> }, + NoEscape { spans: Vec<(char, Span)> }, +} + +// Used because of multiple multipart_suggestion and note +impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { + match self { + HiddenUnicodeCodepointsDiagSub::Escape { spans } => { + diag.multipart_suggestion_with_style( + fluent::suggestion_remove, + spans.iter().map(|(_, span)| (*span, "".to_string())).collect(), + Applicability::MachineApplicable, + SuggestionStyle::HideCodeAlways, + ); + diag.multipart_suggestion( + fluent::suggestion_escape, + spans + .into_iter() + .map(|(c, span)| { + let c = format!("{:?}", c); + (span, c[1..c.len() - 1].to_string()) + }) + .collect(), + Applicability::MachineApplicable, + ); + } + HiddenUnicodeCodepointsDiagSub::NoEscape { spans } => { + // FIXME: in other suggestions we've reversed the inner spans of doc comments. We + // should do the same here to provide the same good suggestions as we do for + // literals above. + diag.set_arg( + "escaped", + spans + .into_iter() + .map(|(c, _)| format!("{:?}", c)) + .collect::>() + .join(", "), + ); + diag.note(fluent::suggestion_remove); + diag.note(fluent::no_suggestion_note_escape); + } + } + } +} + // internal.rs #[derive(LintDiagnostic)] #[diag(lint_default_hash_types)] From 587d49766b711fab79015adecb101138fffa8acc Mon Sep 17 00:00:00 2001 From: Rejyr Date: Sat, 12 Nov 2022 20:18:55 -0500 Subject: [PATCH 29/33] migrate: `UnsafeCode` in `builtin.rs` --- compiler/rustc_lint/src/builtin.rs | 104 ++++++----------------------- compiler/rustc_lint/src/lints.rs | 42 +++++++++++- 2 files changed, 63 insertions(+), 83 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 1dae563577a01..f7055019bab69 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -31,8 +31,8 @@ use crate::{ BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinUnexpectedCliConfigName, BuiltinUnexpectedCliConfigValue, BuiltinUnnameableTestItems, BuiltinUnreachablePub, - BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, - BuiltinWhileTrue, + BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, + BuiltinUnusedDocCommentSub, BuiltinWhileTrue, }, types::{transparent_newtype_field, CItemKind}, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext, @@ -46,8 +46,7 @@ use rustc_ast_pretty::pprust::{self, expr_to_string}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ - fluent, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, DiagnosticMessage, - DiagnosticStyledString, MultiSpan, + fluent, Applicability, DecorateLint, DelayDm, Diagnostic, DiagnosticStyledString, MultiSpan, }; use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability}; use rustc_hir as hir; @@ -314,48 +313,21 @@ impl UnsafeCode { &self, cx: &EarlyContext<'_>, span: Span, - msg: impl Into, - decorate: impl for<'a, 'b> FnOnce( - &'b mut DiagnosticBuilder<'a, ()>, - ) -> &'b mut DiagnosticBuilder<'a, ()>, + decorate: impl for<'a> DecorateLint<'a, ()>, ) { // This comes from a macro that has `#[allow_internal_unsafe]`. if span.allows_unsafe() { return; } - cx.struct_span_lint(UNSAFE_CODE, span, msg, decorate); - } - - fn report_overridden_symbol_name( - &self, - cx: &EarlyContext<'_>, - span: Span, - msg: DiagnosticMessage, - ) { - self.report_unsafe(cx, span, msg, |lint| { - lint.note(fluent::lint_builtin_overridden_symbol_name) - }) - } - - fn report_overridden_symbol_section( - &self, - cx: &EarlyContext<'_>, - span: Span, - msg: DiagnosticMessage, - ) { - self.report_unsafe(cx, span, msg, |lint| { - lint.note(fluent::lint_builtin_overridden_symbol_section) - }) + cx.emit_spanned_lint(UNSAFE_CODE, span, decorate); } } impl EarlyLintPass for UnsafeCode { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { if attr.has_name(sym::allow_internal_unsafe) { - self.report_unsafe(cx, attr.span, fluent::lint_builtin_allow_internal_unsafe, |lint| { - lint - }); + self.report_unsafe(cx, attr.span, BuiltinUnsafe::AllowInternalUnsafe); } } @@ -364,7 +336,7 @@ impl EarlyLintPass for UnsafeCode { if let ast::ExprKind::Block(ref blk, _) = e.kind { // Don't warn about generated blocks; that'll just pollute the output. if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) { - self.report_unsafe(cx, blk.span, fluent::lint_builtin_unsafe_block, |lint| lint); + self.report_unsafe(cx, blk.span, BuiltinUnsafe::UnsafeBlock); } } } @@ -372,62 +344,38 @@ impl EarlyLintPass for UnsafeCode { fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { match it.kind { ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => { - self.report_unsafe(cx, it.span, fluent::lint_builtin_unsafe_trait, |lint| lint) + self.report_unsafe(cx, it.span, BuiltinUnsafe::UnsafeTrait); } ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => { - self.report_unsafe(cx, it.span, fluent::lint_builtin_unsafe_impl, |lint| lint) + self.report_unsafe(cx, it.span, BuiltinUnsafe::UnsafeImpl); } ast::ItemKind::Fn(..) => { if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) { - self.report_overridden_symbol_name( - cx, - attr.span, - fluent::lint_builtin_no_mangle_fn, - ); + self.report_unsafe(cx, attr.span, BuiltinUnsafe::NoMangleFn); } if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) { - self.report_overridden_symbol_name( - cx, - attr.span, - fluent::lint_builtin_export_name_fn, - ); + self.report_unsafe(cx, attr.span, BuiltinUnsafe::ExportNameFn); } if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::link_section) { - self.report_overridden_symbol_section( - cx, - attr.span, - fluent::lint_builtin_link_section_fn, - ); + self.report_unsafe(cx, attr.span, BuiltinUnsafe::LinkSectionFn); } } ast::ItemKind::Static(..) => { if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) { - self.report_overridden_symbol_name( - cx, - attr.span, - fluent::lint_builtin_no_mangle_static, - ); + self.report_unsafe(cx, attr.span, BuiltinUnsafe::NoMangleStatic); } if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) { - self.report_overridden_symbol_name( - cx, - attr.span, - fluent::lint_builtin_export_name_static, - ); + self.report_unsafe(cx, attr.span, BuiltinUnsafe::ExportNameStatic); } if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::link_section) { - self.report_overridden_symbol_section( - cx, - attr.span, - fluent::lint_builtin_link_section_static, - ); + self.report_unsafe(cx, attr.span, BuiltinUnsafe::LinkSectionStatic); } } @@ -438,18 +386,10 @@ impl EarlyLintPass for UnsafeCode { fn check_impl_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) { if let ast::AssocItemKind::Fn(..) = it.kind { if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) { - self.report_overridden_symbol_name( - cx, - attr.span, - fluent::lint_builtin_no_mangle_method, - ); + self.report_unsafe(cx, attr.span, BuiltinUnsafe::NoMangleMethod); } if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) { - self.report_overridden_symbol_name( - cx, - attr.span, - fluent::lint_builtin_export_name_method, - ); + self.report_unsafe(cx, attr.span, BuiltinUnsafe::ExportNameMethod); } } } @@ -464,13 +404,13 @@ impl EarlyLintPass for UnsafeCode { body, ) = fk { - let msg = match ctxt { + let decorator = match ctxt { FnCtxt::Foreign => return, - FnCtxt::Free => fluent::lint_builtin_decl_unsafe_fn, - FnCtxt::Assoc(_) if body.is_none() => fluent::lint_builtin_decl_unsafe_method, - FnCtxt::Assoc(_) => fluent::lint_builtin_impl_unsafe_method, + FnCtxt::Free => BuiltinUnsafe::DeclUnsafeFn, + FnCtxt::Assoc(_) if body.is_none() => BuiltinUnsafe::DeclUnsafeMethod, + FnCtxt::Assoc(_) => BuiltinUnsafe::ImplUnsafeMethod, }; - self.report_unsafe(cx, span, msg, |lint| lint); + self.report_unsafe(cx, span, decorator); } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 4da099dcc1d6b..147cd3e046085 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -61,7 +61,47 @@ pub struct BuiltinNonShorthandFieldPatterns { pub prefix: &'static str, } -// FIXME: add lint::unsafe_code +#[derive(LintDiagnostic)] +pub enum BuiltinUnsafe { + #[diag(lint_builtin_allow_internal_unsafe)] + AllowInternalUnsafe, + #[diag(lint_builtin_unsafe_block)] + UnsafeBlock, + #[diag(lint_builtin_unsafe_trait)] + UnsafeTrait, + #[diag(lint_builtin_unsafe_impl)] + UnsafeImpl, + #[diag(lint_builtin_no_mangle_fn)] + #[note(lint_builtin_overridden_symbol_name)] + NoMangleFn, + #[diag(lint_builtin_export_name_fn)] + #[note(lint_builtin_overridden_symbol_name)] + ExportNameFn, + #[diag(lint_builtin_link_section_fn)] + #[note(lint_builtin_overridden_symbol_section)] + LinkSectionFn, + #[diag(lint_builtin_no_mangle_static)] + #[note(lint_builtin_overridden_symbol_name)] + NoMangleStatic, + #[diag(lint_builtin_export_name_static)] + #[note(lint_builtin_overridden_symbol_name)] + ExportNameStatic, + #[diag(lint_builtin_link_section_static)] + #[note(lint_builtin_overridden_symbol_section)] + LinkSectionStatic, + #[diag(lint_builtin_no_mangle_method)] + #[note(lint_builtin_overridden_symbol_name)] + NoMangleMethod, + #[diag(lint_builtin_export_name_method)] + #[note(lint_builtin_overridden_symbol_name)] + ExportNameMethod, + #[diag(lint_builtin_decl_unsafe_fn)] + DeclUnsafeFn, + #[diag(lint_builtin_decl_unsafe_method)] + DeclUnsafeMethod, + #[diag(lint_builtin_impl_unsafe_method)] + ImplUnsafeMethod, +} #[derive(LintDiagnostic)] #[diag(lint_builtin_missing_doc)] From 758140e196ae2d520d3f286797c654d517bed5b5 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Sun, 13 Nov 2022 09:46:31 -0500 Subject: [PATCH 30/33] migrate: rest of `builtin.rs` without `builtin_asm_labels` --- .../locales/en-US/lint.ftl | 12 +- compiler/rustc_lint/src/builtin.rs | 295 +++++++----------- compiler/rustc_lint/src/lints.rs | 241 +++++++++++++- 3 files changed, 363 insertions(+), 185 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl index 1518adf8e4e24..3fa52ff0eb31e 100644 --- a/compiler/rustc_error_messages/locales/en-US/lint.ftl +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -370,6 +370,8 @@ lint_builtin_anonymous_params = anonymous parameters are deprecated and will be .suggestion = try naming the parameter or explicitly ignoring it lint_builtin_deprecated_attr_link = use of deprecated attribute `{$name}`: {$reason}. See {$link} + .msg_suggestion = {$msg} + .default_suggestion = remove this attribute lint_builtin_deprecated_attr_used = use of deprecated attribute `{$name}`: no longer used. lint_builtin_deprecated_attr_default_suggestion = remove this attribute @@ -430,10 +432,16 @@ lint_builtin_incomplete_features = the feature `{$name}` is incomplete and may n .note = see issue #{$n} for more information .help = consider using `min_{$name}` instead, which is more stable and complete -lint_builtin_clashing_extern_same_name = `{$this_fi}` redeclared with a different signature +lint_builtin_unpermitted_type_init_zeroed = the type `{$ty}` does not permit zero-initialization +lint_builtin_unpermitted_type_init_unint = the type `{$ty}` does not permit being left uninitialized + +lint_builtin_unpermitted_type_init_label = this code causes undefined behavior when executed +lint_builtin_unpermitted_type_init_label_suggestion = help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + +lint_builtin_clashing_extern_same_name = `{$this}` redeclared with a different signature .previous_decl_label = `{$orig}` previously declared here .mismatch_label = this signature doesn't match the previous declaration -lint_builtin_clashing_extern_diff_name = `{$this_fi}` redeclares `{$orig}` with a different signature +lint_builtin_clashing_extern_diff_name = `{$this}` redeclares `{$orig}` with a different signature .previous_decl_label = `{$orig}` previously declared here .mismatch_label = this signature doesn't match the previous declaration diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index f7055019bab69..2bdff0d5a09c7 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1,3 +1,5 @@ +// #![deny(rustc::untranslatable_diagnostic)] +// #![deny(rustc::diagnostic_outside_of_impl)] //! Lints in the Rust compiler. //! //! This contains lints which can feasibly be implemented as their own @@ -23,16 +25,21 @@ use crate::{ errors::BuiltinEllpisisInclusiveRangePatterns, lints::{ - BuiltinAnonymousParams, BuiltinBoxPointers, BuiltinConstNoMangle, - BuiltinDeprecatedAttrUsed, BuiltinDerefNullptr, BuiltinEllipsisInclusiveRangePatternsLint, - BuiltinExplicitOutlives, BuiltinExplicitOutlivesSuggestion, BuiltinIncompleteFeatures, + BuiltinAnonymousParams, BuiltinBoxPointers, BuiltinClashingExtern, + BuiltinClashingExternSub, BuiltinConstNoMangle, BuiltinDeprecatedAttrLink, + BuiltinDeprecatedAttrLinkSuggestion, BuiltinDeprecatedAttrUsed, BuiltinDerefNullptr, + BuiltinEllipsisInclusiveRangePatternsLint, BuiltinExplicitOutlives, + BuiltinExplicitOutlivesSuggestion, BuiltinIncompleteFeatures, BuiltinIncompleteFeaturesHelp, BuiltinIncompleteFeaturesNote, BuiltinKeywordIdents, BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, - BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinUnexpectedCliConfigName, - BuiltinUnexpectedCliConfigValue, BuiltinUnnameableTestItems, BuiltinUnreachablePub, - BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, - BuiltinUnusedDocCommentSub, BuiltinWhileTrue, + BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasGenericBounds, + BuiltinTypeAliasGenericBoundsSuggestion, BuiltinTypeAliasWhereClause, + BuiltinUnexpectedCliConfigName, BuiltinUnexpectedCliConfigValue, + BuiltinUngatedAsyncFnTrackCaller, BuiltinUnnameableTestItems, BuiltinUnpermittedTypeInit, + BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe, + BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, + BuiltinWhileTrue, SuggestChangingAssocTypes, }, types::{transparent_newtype_field, CItemKind}, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext, @@ -45,9 +52,7 @@ use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust::{self, expr_to_string}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::{ - fluent, Applicability, DecorateLint, DelayDm, Diagnostic, DiagnosticStyledString, MultiSpan, -}; +use rustc_errors::{fluent, Applicability, DecorateLint, MultiSpan}; use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -923,24 +928,18 @@ impl EarlyLintPass for DeprecatedAttr { _, ) = gate { - // FIXME(davidtwco) translatable deprecated attr - cx.struct_span_lint( + let suggestion = match suggestion { + Some(msg) => { + BuiltinDeprecatedAttrLinkSuggestion::Msg { suggestion: attr.span, msg } + } + None => { + BuiltinDeprecatedAttrLinkSuggestion::Default { suggestion: attr.span } + } + }; + cx.emit_spanned_lint( DEPRECATED, attr.span, - fluent::lint_builtin_deprecated_attr_link, - |lint| { - lint.set_arg("name", name) - .set_arg("reason", reason) - .set_arg("link", link) - .span_suggestion_short( - attr.span, - suggestion.map(|s| s.into()).unwrap_or( - fluent::lint_builtin_deprecated_attr_default_suggestion, - ), - "", - Applicability::MachineApplicable, - ) - }, + BuiltinDeprecatedAttrLink { name, reason, link, suggestion }, ); } return; @@ -1305,20 +1304,10 @@ impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller { // Now, check if the function has the `#[track_caller]` attribute && let Some(attr) = attrs.iter().find(|attr| attr.has_name(sym::track_caller)) { - cx.struct_span_lint( - UNGATED_ASYNC_FN_TRACK_CALLER, - attr.span, - fluent::lint_ungated_async_fn_track_caller, - |lint| { - lint.span_label(span, fluent::label); - rustc_session::parse::add_feature_diagnostics( - lint, - &cx.tcx.sess.parse_sess, - sym::closure_track_caller, - ); - lint - }, - ); + cx.emit_spanned_lint(UNGATED_ASYNC_FN_TRACK_CALLER, attr.span, BuiltinUngatedAsyncFnTrackCaller { + label: span, + parse_sess: &cx.tcx.sess.parse_sess, + }); } } } @@ -1447,7 +1436,7 @@ declare_lint_pass!( ); impl TypeAliasBounds { - fn is_type_variable_assoc(qpath: &hir::QPath<'_>) -> bool { + pub(crate) fn is_type_variable_assoc(qpath: &hir::QPath<'_>) -> bool { match *qpath { hir::QPath::TypeRelative(ref ty, _) => { // If this is a type variable, we found a `T::Assoc`. @@ -1461,29 +1450,6 @@ impl TypeAliasBounds { hir::QPath::Resolved(..) | hir::QPath::LangItem(..) => false, } } - - fn suggest_changing_assoc_types(ty: &hir::Ty<'_>, err: &mut Diagnostic) { - // Access to associates types should use `::Assoc`, which does not need a - // bound. Let's see if this type does that. - - // We use a HIR visitor to walk the type. - use rustc_hir::intravisit::{self, Visitor}; - struct WalkAssocTypes<'a> { - err: &'a mut Diagnostic, - } - impl Visitor<'_> for WalkAssocTypes<'_> { - fn visit_qpath(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) { - if TypeAliasBounds::is_type_variable_assoc(qpath) { - self.err.span_help(span, fluent::lint_builtin_type_alias_bounds_help); - } - intravisit::walk_qpath(self, qpath, id) - } - } - - // Let's go for a walk! - let mut visitor = WalkAssocTypes { err }; - visitor.visit_ty(ty); - } } impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { @@ -1517,35 +1483,31 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { let mut suggested_changing_assoc_types = false; if !where_spans.is_empty() { - cx.lint(TYPE_ALIAS_BOUNDS, fluent::lint_builtin_type_alias_where_clause, |lint| { - lint.set_span(where_spans); - lint.span_suggestion( - type_alias_generics.where_clause_span, - fluent::suggestion, - "", - Applicability::MachineApplicable, - ); - if !suggested_changing_assoc_types { - TypeAliasBounds::suggest_changing_assoc_types(ty, lint); - suggested_changing_assoc_types = true; - } - lint + let sub = (!suggested_changing_assoc_types).then(|| { + suggested_changing_assoc_types = true; + SuggestChangingAssocTypes { ty } }); + cx.emit_spanned_lint( + TYPE_ALIAS_BOUNDS, + where_spans, + BuiltinTypeAliasWhereClause { + suggestion: type_alias_generics.where_clause_span, + sub, + }, + ); } if !inline_spans.is_empty() { - cx.lint(TYPE_ALIAS_BOUNDS, fluent::lint_builtin_type_alias_generic_bounds, |lint| { - lint.set_span(inline_spans); - lint.multipart_suggestion( - fluent::suggestion, - inline_sugg, - Applicability::MachineApplicable, - ); - if !suggested_changing_assoc_types { - TypeAliasBounds::suggest_changing_assoc_types(ty, lint); - } - lint + let suggestion = BuiltinTypeAliasGenericBoundsSuggestion { suggestions: inline_sugg }; + let sub = (!suggested_changing_assoc_types).then(|| { + suggested_changing_assoc_types = true; + SuggestChangingAssocTypes { ty } }); + cx.emit_spanned_lint( + TYPE_ALIAS_BOUNDS, + inline_spans, + BuiltinTypeAliasGenericBounds { suggestion, sub }, + ); } } } @@ -2376,6 +2338,36 @@ declare_lint! { declare_lint_pass!(InvalidValue => [INVALID_VALUE]); +/// Information about why a type cannot be initialized this way. +pub struct InitError { + pub(crate) message: String, + /// Spans from struct fields and similar that can be obtained from just the type. + pub(crate) span: Option, + /// Used to report a trace through adts. + pub(crate) nested: Option>, +} +impl InitError { + fn spanned(self, span: Span) -> InitError { + Self { span: Some(span), ..self } + } + + fn nested(self, nested: impl Into>) -> InitError { + assert!(self.nested.is_none()); + Self { nested: nested.into().map(Box::new), ..self } + } +} + +impl<'a> From<&'a str> for InitError { + fn from(s: &'a str) -> Self { + s.to_owned().into() + } +} +impl From for InitError { + fn from(message: String) -> Self { + Self { message, span: None, nested: None } + } +} + impl<'tcx> LateLintPass<'tcx> for InvalidValue { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) { #[derive(Debug, Copy, Clone, PartialEq)] @@ -2384,36 +2376,6 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { Uninit, } - /// Information about why a type cannot be initialized this way. - struct InitError { - message: String, - /// Spans from struct fields and similar that can be obtained from just the type. - span: Option, - /// Used to report a trace through adts. - nested: Option>, - } - impl InitError { - fn spanned(self, span: Span) -> InitError { - Self { span: Some(span), ..self } - } - - fn nested(self, nested: impl Into>) -> InitError { - assert!(self.nested.is_none()); - Self { nested: nested.into().map(Box::new), ..self } - } - } - - impl<'a> From<&'a str> for InitError { - fn from(s: &'a str) -> Self { - s.to_owned().into() - } - } - impl From for InitError { - fn from(message: String) -> Self { - Self { message, span: None, nested: None } - } - } - /// Test if this constant is all-0. fn is_zero(expr: &hir::Expr<'_>) -> bool { use hir::ExprKind::*; @@ -2637,46 +2599,16 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { // using zeroed or uninitialized memory. // We are extremely conservative with what we warn about. let conjured_ty = cx.typeck_results().expr_ty(expr); - if let Some(mut err) = with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init)) - { - // FIXME(davidtwco): make translatable - cx.struct_span_lint( + if let Some(err) = with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init)) { + let msg = match init { + InitKind::Zeroed => fluent::lint_builtin_unpermitted_type_init_zeroed, + InitKind::Uninit => fluent::lint_builtin_unpermitted_type_init_unint, + }; + let sub = BuiltinUnpermittedTypeInitSub { err }; + cx.emit_spanned_lint( INVALID_VALUE, expr.span, - DelayDm(|| { - format!( - "the type `{}` does not permit {}", - conjured_ty, - match init { - InitKind::Zeroed => "zero-initialization", - InitKind::Uninit => "being left uninitialized", - }, - ) - }), - |lint| { - lint.span_label( - expr.span, - "this code causes undefined behavior when executed", - ); - lint.span_label( - expr.span, - "help: use `MaybeUninit` instead, \ - and only call `assume_init` after initialization is done", - ); - loop { - if let Some(span) = err.span { - lint.span_note(span, &err.message); - } else { - lint.note(&err.message); - } - if let Some(e) = err.nested { - err = *e; - } else { - break; - } - } - lint - }, + BuiltinUnpermittedTypeInit { msg, ty: conjured_ty, label: expr.span, sub }, ); } } @@ -3022,31 +2954,44 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations { SymbolName::Normal(_) => fi.span, SymbolName::Link(_, annot_span) => fi.span.to(annot_span), }; - // Finally, emit the diagnostic. - let msg = if orig.get_name() == this_fi.ident.name { - fluent::lint_builtin_clashing_extern_same_name + // Finally, emit the diagnostic. + let mut expected_str = DiagnosticStyledString::new(); + expected_str.push(existing_decl_ty.fn_sig(tcx).to_string(), false); + let mut found_str = DiagnosticStyledString::new(); + found_str.push(this_decl_ty.fn_sig(tcx).to_string(), true); + + let this = this_fi.ident.name; + let orig = orig.get_name(); + let previous_decl_label = get_relevant_span(orig_fi); + let mismatch_label = get_relevant_span(this_fi); + let sub = BuiltinClashingExternSub { + tcx, + expected: existing_decl_ty, + found: this_decl_ty, + }; + let decorator = if orig == this { + BuiltinClashingExtern::SameName { + this, + orig, + previous_decl_label, + mismatch_label, + sub, + } } else { - fluent::lint_builtin_clashing_extern_diff_name + BuiltinClashingExtern::DiffName { + this, + orig, + previous_decl_label, + mismatch_label, + sub, + } }; - tcx.struct_span_lint_hir( + tcx.emit_spanned_lint( CLASHING_EXTERN_DECLARATIONS, this_fi.hir_id(), get_relevant_span(this_fi), - msg, - |lint| { - let mut expected_str = DiagnosticStyledString::new(); - expected_str.push(existing_decl_ty.fn_sig(tcx).to_string(), false); - let mut found_str = DiagnosticStyledString::new(); - found_str.push(this_decl_ty.fn_sig(tcx).to_string(), true); - - lint.set_arg("this_fi", this_fi.ident.name) - .set_arg("orig", orig.get_name()) - .span_label(get_relevant_span(orig_fi), fluent::previous_decl_label) - .span_label(get_relevant_span(this_fi), fluent::mismatch_label) - // FIXME(davidtwco): translatable expected/found - .note_expected_found(&"", expected_str, &"", found_str) - }, + decorator, ); } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 147cd3e046085..ee6fa5300f4a3 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1,14 +1,18 @@ use std::num::NonZeroU32; use rustc_errors::{ - fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage, SuggestionStyle, + fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage, + DiagnosticStyledString, SuggestionStyle, }; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{Predicate, Ty, TyCtxt}; -use rustc_span::{edition::Edition, symbol::Ident, Span, Symbol}; +use rustc_session::parse::ParseSess; +use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol}; -use crate::{errors::OverruledAttributeSub, LateContext}; +use crate::{ + builtin::InitError, builtin::TypeAliasBounds, errors::OverruledAttributeSub, LateContext, +}; // array_into_iter.rs #[derive(LintDiagnostic)] @@ -142,7 +146,31 @@ pub struct BuiltinAnonymousParams<'a> { pub ty_snip: &'a str, } -// FIXME: add lint::builtin_deprecated_attr_link +// FIXME(davidtwco) translatable deprecated attr +#[derive(LintDiagnostic)] +#[diag(lint_builtin_deprecated_attr_link)] +pub struct BuiltinDeprecatedAttrLink<'a> { + pub name: Symbol, + pub reason: &'a str, + pub link: &'a str, + #[subdiagnostic] + pub suggestion: BuiltinDeprecatedAttrLinkSuggestion<'a>, +} + +#[derive(Subdiagnostic)] +pub enum BuiltinDeprecatedAttrLinkSuggestion<'a> { + #[suggestion(msg_suggestion, code = "", applicability = "machine-applicable")] + Msg { + #[primary_span] + suggestion: Span, + msg: &'a str, + }, + #[suggestion(default_suggestion, code = "", applicability = "machine-applicable")] + Default { + #[primary_span] + suggestion: Span, + }, +} #[derive(LintDiagnostic)] #[diag(lint_builtin_deprecated_attr_used)] @@ -199,6 +227,31 @@ pub struct BuiltinMutablesTransmutes; #[diag(lint_builtin_unstable_features)] pub struct BuiltinUnstableFeatures; +// lint_ungated_async_fn_track_caller +pub struct BuiltinUngatedAsyncFnTrackCaller<'a> { + pub label: Span, + pub parse_sess: &'a ParseSess, +} + +impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { + diag.span_label(self.label, fluent::label); + rustc_session::parse::add_feature_diagnostics( + diag, + &self.parse_sess, + sym::closure_track_caller, + ); + diag + } + + fn msg(&self) -> DiagnosticMessage { + fluent::lint_ungated_async_fn_track_caller + } +} + #[derive(LintDiagnostic)] #[diag(lint_builtin_unreachable_pub)] pub struct BuiltinUnreachablePub<'a> { @@ -209,9 +262,83 @@ pub struct BuiltinUnreachablePub<'a> { pub help: Option<()>, } -// FIXME: migrate builtin_type_alias_where_clause +pub struct SuggestChangingAssocTypes<'a, 'b> { + pub ty: &'a rustc_hir::Ty<'b>, +} + +impl AddToDiagnostic for SuggestChangingAssocTypes<'_, '_> { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { + // Access to associates types should use `::Assoc`, which does not need a + // bound. Let's see if this type does that. + + // We use a HIR visitor to walk the type. + use rustc_hir::intravisit::{self, Visitor}; + struct WalkAssocTypes<'a> { + err: &'a mut rustc_errors::Diagnostic, + } + impl Visitor<'_> for WalkAssocTypes<'_> { + fn visit_qpath( + &mut self, + qpath: &rustc_hir::QPath<'_>, + id: rustc_hir::HirId, + span: Span, + ) { + if TypeAliasBounds::is_type_variable_assoc(qpath) { + self.err.span_help(span, fluent::lint_builtin_type_alias_bounds_help); + } + intravisit::walk_qpath(self, qpath, id) + } + } + + // Let's go for a walk! + let mut visitor = WalkAssocTypes { err: diag }; + visitor.visit_ty(self.ty); + } +} -// FIXME: migrate builtin_type_alias_generic_bounds +#[derive(LintDiagnostic)] +#[diag(lint_builtin_type_alias_where_clause)] +pub struct BuiltinTypeAliasWhereClause<'a, 'b> { + #[suggestion(code = "", applicability = "machine-applicable")] + pub suggestion: Span, + #[subdiagnostic] + pub sub: Option>, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_type_alias_generic_bounds)] +pub struct BuiltinTypeAliasGenericBounds<'a, 'b> { + #[subdiagnostic] + pub suggestion: BuiltinTypeAliasGenericBoundsSuggestion, + #[subdiagnostic] + pub sub: Option>, +} + +pub struct BuiltinTypeAliasGenericBoundsSuggestion { + pub suggestions: Vec<(Span, String)>, +} + +impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { + diag.multipart_suggestion( + fluent::suggestion, + self.suggestions, + Applicability::MachineApplicable, + ); + } +} #[derive(LintDiagnostic)] #[diag(lint_builtin_trivial_bounds)] @@ -285,9 +412,107 @@ pub struct BuiltinIncompleteFeaturesNote { pub n: NonZeroU32, } -// FIXME: migrate "the type `{}` does not permit {}" +pub struct BuiltinUnpermittedTypeInit<'a> { + pub msg: DiagnosticMessage, + pub ty: Ty<'a>, + pub label: Span, + pub sub: BuiltinUnpermittedTypeInitSub, +} + +impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { + diag.set_arg("ty", self.ty); + diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label); + diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label_suggestion); + self.sub.add_to_diagnostic(diag); + diag + } + + fn msg(&self) -> rustc_errors::DiagnosticMessage { + self.msg.clone() + } +} + +// FIXME(davidtwco): make translatable +pub struct BuiltinUnpermittedTypeInitSub { + pub err: InitError, +} -// FIXME: fluent::lint::builtin_clashing_extern_{same,diff}_name +impl AddToDiagnostic for BuiltinUnpermittedTypeInitSub { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { + let mut err = self.err; + loop { + if let Some(span) = err.span { + diag.span_note(span, err.message); + } else { + diag.note(err.message); + } + if let Some(e) = err.nested { + err = *e; + } else { + break; + } + } + } +} + +#[derive(LintDiagnostic)] +pub enum BuiltinClashingExtern<'a> { + #[diag(lint_builtin_clashing_extern_same_name)] + SameName { + this: Symbol, + orig: Symbol, + #[label(previous_decl_label)] + previous_decl_label: Span, + #[label(mismatch_label)] + mismatch_label: Span, + #[subdiagnostic] + sub: BuiltinClashingExternSub<'a>, + }, + #[diag(lint_builtin_clashing_extern_diff_name)] + DiffName { + this: Symbol, + orig: Symbol, + #[label(previous_decl_label)] + previous_decl_label: Span, + #[label(mismatch_label)] + mismatch_label: Span, + #[subdiagnostic] + sub: BuiltinClashingExternSub<'a>, + }, +} + +// FIXME(davidtwco): translatable expected/found +pub struct BuiltinClashingExternSub<'a> { + pub tcx: TyCtxt<'a>, + pub expected: Ty<'a>, + pub found: Ty<'a>, +} + +impl AddToDiagnostic for BuiltinClashingExternSub<'_> { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { + let mut expected_str = DiagnosticStyledString::new(); + expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false); + let mut found_str = DiagnosticStyledString::new(); + found_str.push(self.found.fn_sig(self.tcx).to_string(), true); + diag.note_expected_found(&"", expected_str, &"", found_str); + } +} #[derive(LintDiagnostic)] #[diag(lint_builtin_deref_nullptr)] From f38db48dbd534af0ef67c39299a393e7d1fe49e9 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Sun, 13 Nov 2022 10:42:49 -0500 Subject: [PATCH 31/33] add: allow lints in `lints.rs` --- compiler/rustc_lint/src/lints.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index ee6fa5300f4a3..a98d5cec97911 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1,3 +1,5 @@ +#![allow(rustc::untranslatable_diagnostic)] +#![allow(rustc::diagnostic_outside_of_impl)] use std::num::NonZeroU32; use rustc_errors::{ From fe09291036ca0d4c97d67f592442d09a1c45abd0 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Thu, 24 Nov 2022 20:03:06 -0500 Subject: [PATCH 32/33] migrate: `deref_into_dyn_supertrait.rs` --- .../locales/en-US/lint.ftl | 3 ++ .../src/deref_into_dyn_supertrait.rs | 30 ++++++++----------- compiler/rustc_lint/src/lints.rs | 18 +++++++++++ 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl index 3fa52ff0eb31e..d63ff77d8e255 100644 --- a/compiler/rustc_error_messages/locales/en-US/lint.ftl +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -457,6 +457,9 @@ lint_builtin_special_module_name_used_lib = found module declaration for lib.rs lint_builtin_special_module_name_used_main = found module declaration for main.rs .note = a binary crate cannot be used as library +lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target + .label = target type is set here + lint_overruled_attribute = {$lint_level}({$lint_source}) incompatible with previous forbid .label = overruled by previous forbid diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index 1d29a234a3c88..dff5a645c175e 100644 --- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -1,6 +1,8 @@ -use crate::{LateContext, LateLintPass, LintContext}; +use crate::{ + lints::{SupertraitAsDerefTarget, SupertraitAsDerefTargetLabel}, + LateContext, LateLintPass, LintContext, +}; -use rustc_errors::DelayDm; use rustc_hir as hir; use rustc_middle::{traits::util::supertraits, ty}; use rustc_span::sym; @@ -71,22 +73,14 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait { && supertraits(cx.tcx, t_principal.with_self_ty(cx.tcx, cx.tcx.types.trait_object_dummy_self)) .any(|sup| sup.map_bound(|x| ty::ExistentialTraitRef::erase_self_ty(cx.tcx, x)) == target_principal) { - cx.struct_span_lint( - DEREF_INTO_DYN_SUPERTRAIT, - cx.tcx.def_span(item.owner_id.def_id), - DelayDm(|| { - format!( - "`{t}` implements `Deref` with supertrait `{target_principal}` as target" - ) - }), - |lint| { - if let Some(target_span) = impl_.items.iter().find_map(|i| (i.ident.name == sym::Target).then_some(i.span)) { - lint.span_label(target_span, "target type is set here"); - } - - lint - }, - ) + let label = impl_.items.iter().find_map(|i| (i.ident.name == sym::Target).then_some(i.span)).map(|label| SupertraitAsDerefTargetLabel { + label, + }); + cx.emit_spanned_lint(DEREF_INTO_DYN_SUPERTRAIT, cx.tcx.def_span(item.owner_id.def_id), SupertraitAsDerefTarget { + t, + target_principal: target_principal.to_string(), + label, + }); } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index a98d5cec97911..c3782a496891d 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -551,6 +551,24 @@ pub struct BuiltinUnexpectedCliConfigValue { pub value: Symbol, } +// deref_into_dyn_supertrait.rs +#[derive(LintDiagnostic)] +#[diag(lint_supertrait_as_deref_target)] +pub struct SupertraitAsDerefTarget<'a> { + pub t: Ty<'a>, + pub target_principal: String, + // pub target_principal: Binder<'a, ExistentialTraitRef<'b>>, + #[subdiagnostic] + pub label: Option, +} + +#[derive(Subdiagnostic)] +#[label(label)] +pub struct SupertraitAsDerefTargetLabel { + #[primary_span] + pub label: Span, +} + // enum_intrinsics_non_enums.rs #[derive(LintDiagnostic)] #[diag(lint_enum_intrinsics_mem_discriminant)] From 88e5dd2530a48b046d35402807c4b3bb44775688 Mon Sep 17 00:00:00 2001 From: Rejyr Date: Wed, 23 Nov 2022 15:52:03 -0500 Subject: [PATCH 33/33] refactor: cleanup --- compiler/rustc_lint/src/array_into_iter.rs | 2 -- compiler/rustc_lint/src/builtin.rs | 8 +------- compiler/rustc_lint/src/context.rs | 2 -- compiler/rustc_lint/src/early.rs | 2 -- compiler/rustc_lint/src/enum_intrinsics_non_enums.rs | 2 -- compiler/rustc_lint/src/errors.rs | 2 -- compiler/rustc_lint/src/expect.rs | 2 -- compiler/rustc_lint/src/for_loops_over_fallibles.rs | 2 -- compiler/rustc_lint/src/internal.rs | 2 -- compiler/rustc_lint/src/let_underscore.rs | 2 -- compiler/rustc_lint/src/levels.rs | 2 -- compiler/rustc_lint/src/lib.rs | 4 ++-- compiler/rustc_lint/src/methods.rs | 2 -- compiler/rustc_lint/src/non_ascii_idents.rs | 2 -- compiler/rustc_lint/src/non_fmt_panic.rs | 2 -- compiler/rustc_lint/src/nonstandard_style.rs | 2 -- compiler/rustc_lint/src/noop_method_call.rs | 2 -- compiler/rustc_lint/src/pass_by_value.rs | 2 -- compiler/rustc_lint/src/redundant_semicolon.rs | 2 -- compiler/rustc_lint/src/traits.rs | 2 -- compiler/rustc_lint/src/types.rs | 2 -- compiler/rustc_lint/src/unused.rs | 2 -- 22 files changed, 3 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index ea5975ed4f0b3..3593f141df61b 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::lints::{ArrayIntoIterDiag, ArrayIntoIterDiagSub}; use crate::{LateContext, LateLintPass, LintContext}; use rustc_hir as hir; diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 2bdff0d5a09c7..6f445426df70e 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1,5 +1,3 @@ -// #![deny(rustc::untranslatable_diagnostic)] -// #![deny(rustc::diagnostic_outside_of_impl)] //! Lints in the Rust compiler. //! //! This contains lints which can feasibly be implemented as their own @@ -2956,11 +2954,6 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations { }; // Finally, emit the diagnostic. - let mut expected_str = DiagnosticStyledString::new(); - expected_str.push(existing_decl_ty.fn_sig(tcx).to_string(), false); - let mut found_str = DiagnosticStyledString::new(); - found_str.push(this_decl_ty.fn_sig(tcx).to_string(), true); - let this = this_fi.ident.name; let orig = orig.get_name(); let previous_decl_label = get_relevant_span(orig_fi); @@ -3119,6 +3112,7 @@ declare_lint! { declare_lint_pass!(NamedAsmLabels => [NAMED_ASM_LABELS]); impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { + #[allow(rustc::diagnostic_outside_of_impl)] fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { if let hir::Expr { kind: hir::ExprKind::InlineAsm(hir::InlineAsm { template_strs, .. }), diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index de9e71d26e17f..c9b9a62257148 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -13,8 +13,6 @@ //! previous lint state is pushed onto a stack and the ast is then recursed //! upon. As the ast is traversed, this keeps track of the current lint level //! for all lint attributes. -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use self::TargetLint::*; diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 58b1ae6e80010..769c2f88ff3da 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! Implementation of lint checking. //! //! The lint checking is mostly consolidated into one pass which runs diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs index 6c398cebee770..73bd4173270ba 100644 --- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs +++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::{ context::LintContext, lints::{EnumIntrinsicsMemDiscriminate, EnumIntrinsicsMemVariant}, diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 0ea643fd69b68..f3ae26091863d 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_errors::{ fluent, AddToDiagnostic, Diagnostic, ErrorGuaranteed, Handler, IntoDiagnostic, SubdiagnosticMessage, diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index 8985ccee0cdf4..70c999811a52b 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::lints::{Expectation, ExpectationNote}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index 7526b8c06327a..5219992ee94f0 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::{ lints::{ ForLoopsOverFalliblesDiag, ForLoopsOverFalliblesLoopSub, ForLoopsOverFalliblesQuestionMark, diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 7d13bcff7fd5d..5eb54cc003427 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -1,8 +1,6 @@ //! Some lints that are only useful in the compiler or crates that use compiler internals, such as //! Clippy. -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::lints::{ BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistantDocKeyword, QueryInstability, TyQualified, TykindDiag, TykindKind, UntranslatableDiag, diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index 991b3e920adbc..b83a9665fc0c6 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::{ lints::{NonBindingLet, NonBindingLetSub}, LateContext, LateLintPass, LintContext, diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 500b1f36558d7..09dfb1022d857 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::context::{CheckLintNameResult, LintStore}; use crate::late::unerased_lint_store; use crate::lints::{ diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index afcf8b54322f6..3d818154cb94f 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -38,8 +38,8 @@ #![feature(never_type)] #![feature(rustc_attrs)] #![recursion_limit = "256"] -// #![deny(rustc::untranslatable_diagnostic)] -// #![deny(rustc::diagnostic_outside_of_impl)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs index 06d4d2d23403d..3045fc1a4761e 100644 --- a/compiler/rustc_lint/src/methods.rs +++ b/compiler/rustc_lint/src/methods.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::lints::CStringPtr; use crate::LateContext; use crate::LateLintPass; diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 1cac1508bbd6b..f130a98185d61 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::lints::{ ConfusableIdentifierPair, IdentifierNonAsciiChar, IdentifierUncommonCodepoints, MixedScriptConfusables, diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index b86097a4bfc4a..4a02c6cce47ed 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::lints::{NonFmtPanicBraces, NonFmtPanicUnused}; use crate::{LateContext, LateLintPass, LintContext}; use rustc_ast as ast; diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 34e3751c061f1..74d234fabea08 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::lints::{ NonCamelCaseType, NonCamelCaseTypeSub, NonSnakeCaseDiag, NonSnakeCaseDiagSub, NonUpperCaseGlobal, NonUpperCaseGlobalSub, diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index ed796940b89df..d67a00619dd09 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::context::LintContext; use crate::lints::NoopMethodCallDiag; use crate::LateContext; diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index 3df0fc385952d..57482a9edba88 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::lints::PassByValueDiag; use crate::{LateContext, LateLintPass, LintContext}; use rustc_hir as hir; diff --git a/compiler/rustc_lint/src/redundant_semicolon.rs b/compiler/rustc_lint/src/redundant_semicolon.rs index 6c6add34a520c..9a8b14b4907ea 100644 --- a/compiler/rustc_lint/src/redundant_semicolon.rs +++ b/compiler/rustc_lint/src/redundant_semicolon.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::{lints::RedundantSemicolonsDiag, EarlyContext, EarlyLintPass, LintContext}; use rustc_ast::{Block, StmtKind}; use rustc_span::Span; diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index 2e778cf0d0fe0..7ea1a138b7e60 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::lints::{DropGlue, DropTraitConstraintsDiag}; use crate::LateContext; use crate::LateLintPass; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 1300a2fe27aa3..625258991a387 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::lints::{ AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 8c5f68d614461..ac2b32b44e6a1 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::lints::{ PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag, UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDelim, UnusedDelimSuggestion,