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_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<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)]
#[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 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())
}
};
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);
let (t, actually) = match ty {
attr::IntType::SignedInt(t) => {
let actually = if negative {
-(size.sign_extend(val) as i128)
} else {
lint.note(fluent::positive_note);
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 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 {
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);
}
}