1
Fork 0

migrate: types.rs

This commit is contained in:
Rejyr 2022-08-28 19:07:58 -04:00
parent 5a90537b62
commit d44ccaa56f
2 changed files with 249 additions and 155 deletions

View file

@ -1,5 +1,142 @@
use rustc_macros::LintDiagnostic; use rustc_errors::{fluent, AddSubdiagnostic, DecorateLint, EmissionGuarantee};
use rustc_span::{Symbol, Span}; 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<OverflowingBinHexSub<'a>>,
}
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)] #[derive(LintDiagnostic)]
#[diag(lint_atomic_ordering_invalid)] #[diag(lint_atomic_ordering_invalid)]

View file

@ -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 crate::{LateContext, LateLintPass, LintContext};
use rustc_ast as ast; use rustc_ast as ast;
use rustc_attr as attr; use rustc_attr as attr;
use rustc_data_structures::fx::FxHashSet; 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 as hir;
use rustc_hir::{is_range_literal, Expr, ExprKind, Node}; use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton}; 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 }; 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};
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 { let suffix = match lit.node {
LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(), LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(),
LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(), LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(),
LitKind::Int(_, LitIntType::Unsuffixed) => "", LitKind::Int(_, LitIntType::Unsuffixed) => "",
_ => bug!(), _ => bug!(),
}; };
let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix); cx.emit_spanned_lint(
lint.span_suggestion( OVERFLOWING_LITERALS,
struct_expr.span, struct_expr.span,
fluent::suggestion, RangeEndpointOutOfRange {
suggestion, ty,
Applicability::MachineApplicable, suggestion: struct_expr.span,
); start,
literal: lit_val - 1,
lint suffix,
}, },
); );
@ -228,11 +225,6 @@ fn report_bin_hex_error(
val: u128, val: u128,
negative: bool, negative: bool,
) { ) {
cx.struct_span_lint(
OVERFLOWING_LITERALS,
expr.span,
fluent::lint_overflowing_bin_hex,
|lint| {
let (t, actually) = match ty { let (t, actually) = match ty {
attr::IntType::SignedInt(t) => { attr::IntType::SignedInt(t) => {
let actually = if negative { let actually = if negative {
@ -247,39 +239,23 @@ fn report_bin_hex_error(
(t.name_str(), actually.to_string()) (t.name_str(), actually.to_string())
} }
}; };
let sign =
if negative { if negative { OverflowingBinHexSign::Negative } else { OverflowingBinHexSign::Positive };
// If the value is negative, let sub = get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative).map(
// emits a note about the value itself, apart from the literal. |suggestion_ty| {
lint.note(fluent::negative_note);
lint.note(fluent::negative_becomes_note);
} else {
lint.note(fluent::positive_note);
}
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') { if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
let (sans_suffix, _) = repr_str.split_at(pos); let (sans_suffix, _) = repr_str.split_at(pos);
lint.span_suggestion( OverflowingBinHexSub::Suggestion { span: expr.span, suggestion_ty, sans_suffix }
expr.span,
fluent::suggestion,
format!("{}{}", sans_suffix, sugg_ty),
Applicability::MachineApplicable,
);
} else { } else {
lint.help(fluent::help); OverflowingBinHexSub::Help { suggestion_ty }
} }
}
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. // This function finds the next fitting type and generates a suggestion string.
@ -363,28 +339,25 @@ fn lint_int_literal<'tcx>(
return; return;
} }
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, fluent::lint_overflowing_int, |lint| { cx.emit_spanned_lint(
lint.set_arg("ty", t.name_str()) OVERFLOWING_LITERALS,
.set_arg( e.span,
"lit", OverflowingInt {
cx.sess() ty: t.name_str(),
lit: cx
.sess()
.source_map() .source_map()
.span_to_snippet(lit.span) .span_to_snippet(lit.span)
.expect("must get snippet from literal"), .expect("must get snippet from literal"),
) min,
.set_arg("min", min) max,
.set_arg("max", max) suggestion_ty: get_type_suggestion(
.note(fluent::note); cx.typeck_results().node_type(e.hir_id),
v,
if let Some(sugg_ty) = negative,
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
});
} }
} }
@ -408,18 +381,10 @@ fn lint_uint_literal<'tcx>(
match par_e.kind { match par_e.kind {
hir::ExprKind::Cast(..) => { hir::ExprKind::Cast(..) => {
if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() { if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() {
cx.struct_span_lint( cx.emit_spanned_lint(
OVERFLOWING_LITERALS, OVERFLOWING_LITERALS,
par_e.span, par_e.span,
fluent::lint_only_cast_u8_to_char, OnlyCastu8ToChar { span: par_e.span, literal: lit_val },
|lint| {
lint.span_suggestion(
par_e.span,
fluent::suggestion,
format!("'\\u{{{:X}}}'", lit_val),
Applicability::MachineApplicable,
)
},
); );
return; return;
} }
@ -443,19 +408,20 @@ fn lint_uint_literal<'tcx>(
); );
return; return;
} }
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, fluent::lint_overflowing_uint, |lint| { cx.emit_spanned_lint(
lint.set_arg("ty", t.name_str()) OVERFLOWING_LITERALS,
.set_arg( e.span,
"lit", OverflowingUInt {
cx.sess() ty: t.name_str(),
lit: cx
.sess()
.source_map() .source_map()
.span_to_snippet(lit.span) .span_to_snippet(lit.span)
.expect("must get snippet from literal"), .expect("must get snippet from literal"),
) min,
.set_arg("min", min) max,
.set_arg("max", max) },
.note(fluent::note) );
});
} }
} }
@ -484,20 +450,16 @@ fn lint_literal<'tcx>(
_ => bug!(), _ => bug!(),
}; };
if is_infinite == Ok(true) { if is_infinite == Ok(true) {
cx.struct_span_lint( cx.emit_spanned_lint(
OVERFLOWING_LITERALS, OVERFLOWING_LITERALS,
e.span, e.span,
fluent::lint_overflowing_literal, OverflowingLiteral {
|lint| { ty: t.name_str(),
lint.set_arg("ty", t.name_str()) lit: cx
.set_arg( .sess()
"lit",
cx.sess()
.source_map() .source_map()
.span_to_snippet(lit.span) .span_to_snippet(lit.span)
.expect("must get snippet from literal"), .expect("must get snippet from literal"),
)
.note(fluent::note)
}, },
); );
} }
@ -517,12 +479,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
} }
hir::ExprKind::Binary(binop, ref l, ref r) => { hir::ExprKind::Binary(binop, ref l, ref r) => {
if is_comparison(binop) && !check_limits(cx, binop, &l, &r) { if is_comparison(binop) && !check_limits(cx, binop, &l, &r) {
cx.struct_span_lint( cx.emit_spanned_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons);
UNUSED_COMPARISONS,
e.span,
fluent::lint_unused_comparisons,
|lint| lint,
);
} }
} }
hir::ExprKind::Lit(ref lit) => lint_literal(cx, self, e, lit), 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::Declaration => "block",
CItemKind::Definition => "fn", CItemKind::Definition => "fn",
}; };
lint.set_arg("ty", ty); #[allow(rustc::diagnostic_outside_of_impl)]
lint.set_arg("desc", item_description); let mut diag = lint.build(fluent::lint_improper_ctypes);
lint.span_label(sp, fluent::label); diag.set_arg("ty", ty);
diag.set_arg("desc", item_description);
diag.span_label(sp, fluent::label);
if let Some(help) = help { if let Some(help) = help {
lint.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 // We only warn if the largest variant is at least thrice as large as
// the second-largest. // the second-largest.
if largest > slargest * 3 && slargest > 0 { if largest > slargest * 3 && slargest > 0 {
cx.struct_span_lint( cx.emit_spanned_lint(
VARIANT_SIZE_DIFFERENCES, VARIANT_SIZE_DIFFERENCES,
enum_definition.variants[largest_index].span, enum_definition.variants[largest_index].span,
fluent::lint_variant_size_differences, VariantSizeDifferencesDiag { largest },
|lint| lint.set_arg("largest", largest),
); );
} }
} }
@ -1509,17 +1467,19 @@ impl InvalidAtomicOrdering {
fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) { 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]) 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 { && let Some((ordering_arg, invalid_ordering)) = match method {
sym::load => Some((&args[0], sym::Release, fluent::lint_atomic_ordering_load)), sym::load => Some((&args[0], sym::Release)),
sym::store => Some((&args[1], sym::Acquire, fluent::lint_atomic_ordering_store)), sym::store => Some((&args[1], sym::Acquire)),
_ => None, _ => None,
} }
&& let Some(ordering) = Self::match_ordering(cx, ordering_arg) && let Some(ordering) = Self::match_ordering(cx, ordering_arg)
&& (ordering == invalid_ordering || ordering == sym::AcqRel) && (ordering == invalid_ordering || ordering == sym::AcqRel)
{ {
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, msg, |lint| { if method == sym::load {
lint.help(fluent::help) 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)) && matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::fence | sym::compiler_fence))
&& Self::match_ordering(cx, &args[0]) == Some(sym::Relaxed) && 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| { cx.emit_spanned_lint(INVALID_ATOMIC_ORDERING, args[0].span, AtomicOrderingFence);
lint
.help(fluent::help)
});
} }
} }