migrate: types.rs
This commit is contained in:
parent
5a90537b62
commit
d44ccaa56f
@ -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)]
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user