Skip to content

Commit 7a9bef4

Browse files
committed
lint: port overflowing literals diagnostics
Signed-off-by: David Wood <david.wood@huawei.com>
1 parent 7ef610c commit 7a9bef4

File tree

3 files changed

+79
-41
lines changed

3 files changed

+79
-41
lines changed

compiler/rustc_error_messages/locales/en-US/lint.ftl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,28 @@ lint-drop-trait-constraints =
147147
148148
lint-drop-glue =
149149
types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped
150+
151+
lint-range-endpoint-out-of-range = range endpoint is out of range for `{$ty}`
152+
.suggestion = use an inclusive range instead
153+
154+
lint-overflowing-bin-hex = literal out of range for `{$ty}`
155+
.negative-note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}`
156+
.negative-becomes-note = and the value `-{$lit}` will become `{$actually}{$ty}`
157+
.positive-note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` and will become `{$actually}{$ty}`
158+
.suggestion = consider using the type `{$suggestion_ty}` instead
159+
.help = consider using the type `{$suggestion_ty}` instead
160+
161+
lint-overflowing-int = literal out of range for `{$ty}`
162+
.note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`
163+
.help = consider using the type `{$suggestion_ty}` instead
164+
165+
lint-only-cast-u8-to-char = only `u8` can be cast into `char`
166+
.suggestion = use a `char` literal instead
167+
168+
lint-overflowing-uint = literal out of range for `{$ty}`
169+
.note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`
170+
171+
lint-overflowing-literal = literal out of range for `{$ty}`
172+
.note = the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY`
173+
174+
lint-unused-comparisons = comparison is useless due to type limits

compiler/rustc_errors/src/diagnostic.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,18 @@ impl IntoDiagnosticArg for bool {
4949
}
5050
}
5151

52+
impl IntoDiagnosticArg for i128 {
53+
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
54+
DiagnosticArgValue::Str(Cow::Owned(self.to_string()))
55+
}
56+
}
57+
58+
impl IntoDiagnosticArg for u128 {
59+
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
60+
DiagnosticArgValue::Str(Cow::Owned(self.to_string()))
61+
}
62+
}
63+
5264
impl IntoDiagnosticArg for String {
5365
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
5466
DiagnosticArgValue::Str(Cow::Owned(self))

compiler/rustc_lint/src/types.rs

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::{LateContext, LateLintPass, LintContext};
22
use rustc_ast as ast;
33
use rustc_attr as attr;
44
use rustc_data_structures::fx::FxHashSet;
5-
use rustc_errors::Applicability;
5+
use rustc_errors::{fluent, Applicability};
66
use rustc_hir as hir;
77
use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
88
use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
@@ -139,7 +139,8 @@ fn lint_overflowing_range_endpoint<'tcx>(
139139
// overflowing and only by 1.
140140
if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max {
141141
cx.struct_span_lint(OVERFLOWING_LITERALS, parent_expr.span, |lint| {
142-
let mut err = lint.build(&format!("range endpoint is out of range for `{}`", ty));
142+
let mut err = lint.build(fluent::lint::range_endpoint_out_of_range);
143+
err.set_arg("ty", ty);
143144
if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) {
144145
use ast::{LitIntType, LitKind};
145146
// We need to preserve the literal's suffix,
@@ -153,7 +154,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
153154
let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
154155
err.span_suggestion(
155156
parent_expr.span,
156-
"use an inclusive range instead",
157+
fluent::lint::suggestion,
157158
suggestion,
158159
Applicability::MachineApplicable,
159160
);
@@ -229,38 +230,35 @@ fn report_bin_hex_error(
229230
(t.name_str(), actually.to_string())
230231
}
231232
};
232-
let mut err = lint.build(&format!("literal out of range for `{}`", t));
233+
let mut err = lint.build(fluent::lint::overflowing_bin_hex);
233234
if negative {
234235
// If the value is negative,
235236
// emits a note about the value itself, apart from the literal.
236-
err.note(&format!(
237-
"the literal `{}` (decimal `{}`) does not fit into \
238-
the type `{}`",
239-
repr_str, val, t
240-
));
241-
err.note(&format!("and the value `-{}` will become `{}{}`", repr_str, actually, t));
237+
err.note(fluent::lint::negative_note);
238+
err.note(fluent::lint::negative_becomes_note);
242239
} else {
243-
err.note(&format!(
244-
"the literal `{}` (decimal `{}`) does not fit into \
245-
the type `{}` and will become `{}{}`",
246-
repr_str, val, t, actually, t
247-
));
240+
err.note(fluent::lint::positive_note);
248241
}
249242
if let Some(sugg_ty) =
250243
get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative)
251244
{
245+
err.set_arg("suggestion_ty", sugg_ty);
252246
if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
253247
let (sans_suffix, _) = repr_str.split_at(pos);
254248
err.span_suggestion(
255249
expr.span,
256-
&format!("consider using the type `{}` instead", sugg_ty),
250+
fluent::lint::suggestion,
257251
format!("{}{}", sans_suffix, sugg_ty),
258252
Applicability::MachineApplicable,
259253
);
260254
} else {
261-
err.help(&format!("consider using the type `{}` instead", sugg_ty));
255+
err.help(fluent::lint::help);
262256
}
263257
}
258+
err.set_arg("ty", t);
259+
err.set_arg("lit", repr_str);
260+
err.set_arg("dec", val);
261+
err.set_arg("actually", actually);
264262
err.emit();
265263
});
266264
}
@@ -353,21 +351,23 @@ fn lint_int_literal<'tcx>(
353351
}
354352

355353
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
356-
let mut err = lint.build(&format!("literal out of range for `{}`", t.name_str()));
357-
err.note(&format!(
358-
"the literal `{}` does not fit into the type `{}` whose range is `{}..={}`",
354+
let mut err = lint.build(fluent::lint::overflowing_int);
355+
err.set_arg("ty", t.name_str());
356+
err.set_arg(
357+
"lit",
359358
cx.sess()
360359
.source_map()
361360
.span_to_snippet(lit.span)
362361
.expect("must get snippet from literal"),
363-
t.name_str(),
364-
min,
365-
max,
366-
));
362+
);
363+
err.set_arg("min", min);
364+
err.set_arg("max", max);
365+
err.note(fluent::lint::note);
367366
if let Some(sugg_ty) =
368367
get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative)
369368
{
370-
err.help(&format!("consider using the type `{}` instead", sugg_ty));
369+
err.set_arg("suggestion_ty", sugg_ty);
370+
err.help(fluent::lint::help);
371371
}
372372
err.emit();
373373
});
@@ -395,10 +395,10 @@ fn lint_uint_literal<'tcx>(
395395
hir::ExprKind::Cast(..) => {
396396
if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() {
397397
cx.struct_span_lint(OVERFLOWING_LITERALS, par_e.span, |lint| {
398-
lint.build("only `u8` can be cast into `char`")
398+
lint.build(fluent::lint::only_cast_u8_to_char)
399399
.span_suggestion(
400400
par_e.span,
401-
"use a `char` literal instead",
401+
fluent::lint::suggestion,
402402
format!("'\\u{{{:X}}}'", lit_val),
403403
Applicability::MachineApplicable,
404404
)
@@ -429,17 +429,18 @@ fn lint_uint_literal<'tcx>(
429429
return;
430430
}
431431
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
432-
lint.build(&format!("literal out of range for `{}`", t.name_str()))
433-
.note(&format!(
434-
"the literal `{}` does not fit into the type `{}` whose range is `{}..={}`",
432+
lint.build(fluent::lint::overflowing_uint)
433+
.set_arg("ty", t.name_str())
434+
.set_arg(
435+
"lit",
435436
cx.sess()
436437
.source_map()
437438
.span_to_snippet(lit.span)
438439
.expect("must get snippet from literal"),
439-
t.name_str(),
440-
min,
441-
max,
442-
))
440+
)
441+
.set_arg("min", min)
442+
.set_arg("max", max)
443+
.note(fluent::lint::note)
443444
.emit();
444445
});
445446
}
@@ -471,16 +472,16 @@ fn lint_literal<'tcx>(
471472
};
472473
if is_infinite == Ok(true) {
473474
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
474-
lint.build(&format!("literal out of range for `{}`", t.name_str()))
475-
.note(&format!(
476-
"the literal `{}` does not fit into the type `{}` and will be converted to `{}::INFINITY`",
475+
lint.build(fluent::lint::overflowing_literal)
476+
.set_arg("ty", t.name_str())
477+
.set_arg(
478+
"lit",
477479
cx.sess()
478480
.source_map()
479481
.span_to_snippet(lit.span)
480482
.expect("must get snippet from literal"),
481-
t.name_str(),
482-
t.name_str(),
483-
))
483+
)
484+
.note(fluent::lint::note)
484485
.emit();
485486
});
486487
}
@@ -501,7 +502,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
501502
hir::ExprKind::Binary(binop, ref l, ref r) => {
502503
if is_comparison(binop) && !check_limits(cx, binop, &l, &r) {
503504
cx.struct_span_lint(UNUSED_COMPARISONS, e.span, |lint| {
504-
lint.build("comparison is useless due to type limits").emit();
505+
lint.build(fluent::lint::unused_comparisons).emit();
505506
});
506507
}
507508
}

0 commit comments

Comments
 (0)