Skip to content

Commit 83573a3

Browse files
authored
Rollup merge of #109554 - MU001999:master, r=WaffleLapkin
Suggest ..= when someone tries to create an overflowing range Fixes #109529
2 parents 9f28c98 + dde26b3 commit 83573a3

File tree

6 files changed

+94
-15
lines changed

6 files changed

+94
-15
lines changed

compiler/rustc_lint/messages.ftl

+3-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,9 @@ lint_drop_glue =
197197
types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped
198198
199199
lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}`
200-
.suggestion = use an inclusive range instead
200+
201+
lint_range_use_inclusive_range = use an inclusive range instead
202+
201203
202204
lint_overflowing_bin_hex = literal out of range for `{$ty}`
203205
.negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}`

compiler/rustc_lint/src/lints.rs

+27-5
Original file line numberDiff line numberDiff line change
@@ -1210,11 +1210,33 @@ impl<'a> DecorateLint<'a, ()> for DropGlue<'_> {
12101210
#[diag(lint_range_endpoint_out_of_range)]
12111211
pub struct RangeEndpointOutOfRange<'a> {
12121212
pub ty: &'a str,
1213-
#[suggestion(code = "{start}..={literal}{suffix}", applicability = "machine-applicable")]
1214-
pub suggestion: Span,
1215-
pub start: String,
1216-
pub literal: u128,
1217-
pub suffix: &'a str,
1213+
#[subdiagnostic]
1214+
pub sub: UseInclusiveRange<'a>,
1215+
}
1216+
1217+
#[derive(Subdiagnostic)]
1218+
pub enum UseInclusiveRange<'a> {
1219+
#[suggestion(
1220+
lint_range_use_inclusive_range,
1221+
code = "{start}..={literal}{suffix}",
1222+
applicability = "machine-applicable"
1223+
)]
1224+
WithoutParen {
1225+
#[primary_span]
1226+
sugg: Span,
1227+
start: String,
1228+
literal: u128,
1229+
suffix: &'a str,
1230+
},
1231+
#[multipart_suggestion(lint_range_use_inclusive_range, applicability = "machine-applicable")]
1232+
WithParen {
1233+
#[suggestion_part(code = "=")]
1234+
eq_sugg: Span,
1235+
#[suggestion_part(code = "{literal}{suffix}")]
1236+
lit_sugg: Span,
1237+
literal: u128,
1238+
suffix: &'a str,
1239+
},
12181240
}
12191241

12201242
#[derive(LintDiagnostic)]

compiler/rustc_lint/src/types.rs

+29-9
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use crate::{
44
AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes,
55
InvalidAtomicOrderingDiag, OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign,
66
OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral,
7-
OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, VariantSizeDifferencesDiag,
7+
OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange,
8+
VariantSizeDifferencesDiag,
89
},
910
};
1011
use crate::{LateContext, LateLintPass, LintContext};
@@ -136,6 +137,14 @@ fn lint_overflowing_range_endpoint<'tcx>(
136137
expr: &'tcx hir::Expr<'tcx>,
137138
ty: &str,
138139
) -> bool {
140+
// Look past casts to support cases like `0..256 as u8`
141+
let (expr, lit_span) = if let Node::Expr(par_expr) = cx.tcx.hir().get(cx.tcx.hir().parent_id(expr.hir_id))
142+
&& let ExprKind::Cast(_, _) = par_expr.kind {
143+
(par_expr, expr.span)
144+
} else {
145+
(expr, expr.span)
146+
};
147+
139148
// We only want to handle exclusive (`..`) ranges,
140149
// which are represented as `ExprKind::Struct`.
141150
let par_id = cx.tcx.hir().parent_id(expr.hir_id);
@@ -155,7 +164,6 @@ fn lint_overflowing_range_endpoint<'tcx>(
155164
if !(eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max) {
156165
return false;
157166
};
158-
let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) else { return false };
159167

160168
use rustc_ast::{LitIntType, LitKind};
161169
let suffix = match lit.node {
@@ -164,16 +172,28 @@ fn lint_overflowing_range_endpoint<'tcx>(
164172
LitKind::Int(_, LitIntType::Unsuffixed) => "",
165173
_ => bug!(),
166174
};
167-
cx.emit_spanned_lint(
168-
OVERFLOWING_LITERALS,
169-
struct_expr.span,
170-
RangeEndpointOutOfRange {
171-
ty,
172-
suggestion: struct_expr.span,
175+
176+
let sub_sugg = if expr.span.lo() == lit_span.lo() {
177+
let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) else { return false };
178+
UseInclusiveRange::WithoutParen {
179+
sugg: struct_expr.span.shrink_to_lo().to(lit_span.shrink_to_hi()),
173180
start,
174181
literal: lit_val - 1,
175182
suffix,
176-
},
183+
}
184+
} else {
185+
UseInclusiveRange::WithParen {
186+
eq_sugg: expr.span.shrink_to_lo(),
187+
lit_sugg: lit_span,
188+
literal: lit_val - 1,
189+
suffix,
190+
}
191+
};
192+
193+
cx.emit_spanned_lint(
194+
OVERFLOWING_LITERALS,
195+
struct_expr.span,
196+
RangeEndpointOutOfRange { ty, sub: sub_sugg },
177197
);
178198

179199
// We've just emitted a lint, special cased for `(...)..MAX+1` ranges,

tests/ui/lint/issue-109529.fixed

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// run-rustfix
2+
3+
fn main() {
4+
for _ in 0..=255 as u8 {} //~ ERROR range endpoint is out of range
5+
for _ in 0..=(255 as u8) {} //~ ERROR range endpoint is out of range
6+
}

tests/ui/lint/issue-109529.rs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// run-rustfix
2+
3+
fn main() {
4+
for _ in 0..256 as u8 {} //~ ERROR range endpoint is out of range
5+
for _ in 0..(256 as u8) {} //~ ERROR range endpoint is out of range
6+
}

tests/ui/lint/issue-109529.stderr

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error: range endpoint is out of range for `u8`
2+
--> $DIR/issue-109529.rs:4:14
3+
|
4+
LL | for _ in 0..256 as u8 {}
5+
| ------^^^^^^
6+
| |
7+
| help: use an inclusive range instead: `0..=255`
8+
|
9+
= note: `#[deny(overflowing_literals)]` on by default
10+
11+
error: range endpoint is out of range for `u8`
12+
--> $DIR/issue-109529.rs:5:14
13+
|
14+
LL | for _ in 0..(256 as u8) {}
15+
| ^^^^^^^^^^^^^^
16+
|
17+
help: use an inclusive range instead
18+
|
19+
LL | for _ in 0..=(255 as u8) {}
20+
| + ~~~
21+
22+
error: aborting due to 2 previous errors
23+

0 commit comments

Comments
 (0)