diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 68e62c9789a..5b7e994e035 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -197,7 +197,9 @@ lint_drop_glue = types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}` - .suggestion = use an inclusive range instead + +lint_range_use_inclusive_range = use an inclusive range instead + lint_overflowing_bin_hex = literal out of range for `{$ty}` .negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 925e9654f93..8ec4c2b3d46 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1210,12 +1210,33 @@ impl<'a> DecorateLint<'a, ()> for DropGlue<'_> { #[diag(lint_range_endpoint_out_of_range)] pub struct RangeEndpointOutOfRange<'a> { pub ty: &'a str, - #[suggestion(code = "=", applicability = "machine-applicable")] - pub eq_suggestion: Span, - #[suggestion(code = "{literal}{suffix}", applicability = "machine-applicable")] - pub lit_suggestion: Span, - pub literal: u128, - pub suffix: &'a str, + #[subdiagnostic] + pub sub: UseInclusiveRange<'a>, +} + +#[derive(Subdiagnostic)] +pub enum UseInclusiveRange<'a> { + #[suggestion( + lint_range_use_inclusive_range, + code = "{start}..={literal}{suffix}", + applicability = "machine-applicable" + )] + WithoutParen { + #[primary_span] + sugg: Span, + start: String, + literal: u128, + suffix: &'a str, + }, + #[multipart_suggestion(lint_range_use_inclusive_range, applicability = "machine-applicable")] + WithParen { + #[suggestion_part(code = "=")] + eq_sugg: Span, + #[suggestion_part(code = "{literal}{suffix}")] + lit_sugg: Span, + literal: u128, + suffix: &'a str, + }, } #[derive(LintDiagnostic)] diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 1cc873c6de9..f6bca7045c8 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -4,7 +4,8 @@ use crate::{ AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral, - OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, VariantSizeDifferencesDiag, + OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange, + VariantSizeDifferencesDiag, }, }; use crate::{LateContext, LateLintPass, LintContext}; @@ -172,16 +173,27 @@ fn lint_overflowing_range_endpoint<'tcx>( _ => bug!(), }; + let sub_sugg = if expr.span.lo() == lit_span.lo() { + let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) else { return false }; + UseInclusiveRange::WithoutParen { + sugg: struct_expr.span.shrink_to_lo().to(lit_span.shrink_to_hi()), + start, + literal: lit_val - 1, + suffix, + } + } else { + UseInclusiveRange::WithParen { + eq_sugg: expr.span.shrink_to_lo(), + lit_sugg: lit_span, + literal: lit_val - 1, + suffix, + } + }; + cx.emit_spanned_lint( OVERFLOWING_LITERALS, struct_expr.span, - RangeEndpointOutOfRange { - ty, - eq_suggestion: expr.span.shrink_to_lo(), - lit_suggestion: lit_span, - literal: lit_val - 1, - suffix, - }, + RangeEndpointOutOfRange { ty, sub: sub_sugg }, ); // We've just emitted a lint, special cased for `(...)..MAX+1` ranges, diff --git a/tests/ui/lint/issue-109529.rs b/tests/ui/lint/issue-109529.rs index 36c6d4fdfe3..c9b4da4b26e 100644 --- a/tests/ui/lint/issue-109529.rs +++ b/tests/ui/lint/issue-109529.rs @@ -1,5 +1,4 @@ fn main() { - for i in 0..(256 as u8) { //~ ERROR range endpoint is out of range - println!("{}", i); - } + for _ in 0..256 as u8 {} //~ ERROR range endpoint is out of range + for _ in 0..(256 as u8) {} //~ ERROR range endpoint is out of range } diff --git a/tests/ui/lint/issue-109529.stderr b/tests/ui/lint/issue-109529.stderr index e9f6d546ac2..15b259ad55e 100644 --- a/tests/ui/lint/issue-109529.stderr +++ b/tests/ui/lint/issue-109529.stderr @@ -1,18 +1,23 @@ error: range endpoint is out of range for `u8` --> $DIR/issue-109529.rs:2:14 | -LL | for i in 0..(256 as u8) { - | ^^^^^^^^^^^^^^ +LL | for _ in 0..256 as u8 {} + | ------^^^^^^ + | | + | help: use an inclusive range instead: `0..=255` | = note: `#[deny(overflowing_literals)]` on by default + +error: range endpoint is out of range for `u8` + --> $DIR/issue-109529.rs:3:14 + | +LL | for _ in 0..(256 as u8) {} + | ^^^^^^^^^^^^^^ + | help: use an inclusive range instead | -LL | for i in 0..=(256 as u8) { - | + -help: use an inclusive range instead - | -LL | for i in 0..(255 as u8) { - | ~~~ +LL | for _ in 0..=(255 as u8) {} + | + ~~~ -error: aborting due to previous error +error: aborting due to 2 previous errors