diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 308c02929ca..925e9654f93 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1210,9 +1210,10 @@ impl<'a> DecorateLint<'a, ()> for DropGlue<'_> { #[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, + #[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, } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index db93f6d3402..1cc873c6de9 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -136,11 +136,12 @@ fn lint_overflowing_range_endpoint<'tcx>( expr: &'tcx hir::Expr<'tcx>, ty: &str, ) -> bool { - let (expr, cast_ty) = if let Node::Expr(par_expr) = cx.tcx.hir().get(cx.tcx.hir().parent_id(expr.hir_id)) - && let ExprKind::Cast(_, ty) = par_expr.kind { - (par_expr, Some(ty)) + // Look past casts to support cases like `0..256 as u8` + let (expr, lit_span) = if let Node::Expr(par_expr) = cx.tcx.hir().get(cx.tcx.hir().parent_id(expr.hir_id)) + && let ExprKind::Cast(_, _) = par_expr.kind { + (par_expr, expr.span) } else { - (expr, None) + (expr, expr.span) }; // We only want to handle exclusive (`..`) ranges, @@ -162,19 +163,13 @@ fn lint_overflowing_range_endpoint<'tcx>( if !(eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max) { return false; }; - let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) else { return false }; - let suffix = if let Some(cast_ty) = cast_ty { - let Ok(ty) = cx.sess().source_map().span_to_snippet(cast_ty.span) else { return false }; - format!(" as {}", ty) - } else { - use rustc_ast::{LitIntType, LitKind}; - match lit.node { - LitKind::Int(_, LitIntType::Signed(s)) => s.name_str().to_owned(), - LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str().to_owned(), - LitKind::Int(_, LitIntType::Unsuffixed) => "".to_owned(), - _ => bug!(), - } + 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( @@ -182,10 +177,10 @@ fn lint_overflowing_range_endpoint<'tcx>( struct_expr.span, RangeEndpointOutOfRange { ty, - suggestion: struct_expr.span, - start, + eq_suggestion: expr.span.shrink_to_lo(), + lit_suggestion: lit_span, literal: lit_val - 1, - suffix: &suffix, + suffix, }, ); diff --git a/tests/ui/lint/issue-109529.rs b/tests/ui/lint/issue-109529.rs index f6829d0c76a..36c6d4fdfe3 100644 --- a/tests/ui/lint/issue-109529.rs +++ b/tests/ui/lint/issue-109529.rs @@ -1,5 +1,5 @@ fn main() { - for i in 0..256 as u8 { //~ ERROR range endpoint is out of range + for i in 0..(256 as u8) { //~ ERROR range endpoint is out of range println!("{}", i); } } diff --git a/tests/ui/lint/issue-109529.stderr b/tests/ui/lint/issue-109529.stderr index 87c9119ee6f..e9f6d546ac2 100644 --- a/tests/ui/lint/issue-109529.stderr +++ b/tests/ui/lint/issue-109529.stderr @@ -1,10 +1,18 @@ error: range endpoint is out of range for `u8` --> $DIR/issue-109529.rs:2:14 | -LL | for i in 0..256 as u8 { - | ^^^^^^^^^^^^ help: use an inclusive range instead: `0..=255 as u8` +LL | for i in 0..(256 as u8) { + | ^^^^^^^^^^^^^^ | = note: `#[deny(overflowing_literals)]` on by default +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) { + | ~~~ error: aborting due to previous error