diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2023-03-29 21:19:48 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-29 21:19:48 +0200 |
| commit | 83573a377602a27dd65c8b564391e5706d5d76be (patch) | |
| tree | d6abcea1a5e2268e86198701740c36f7ce6cf7b4 /compiler | |
| parent | 9f28c983575e57e8692ce9429544d625b624962c (diff) | |
| parent | dde26b31b6b625496e8dc0933e231c27f35b8933 (diff) | |
| download | rust-83573a377602a27dd65c8b564391e5706d5d76be.tar.gz rust-83573a377602a27dd65c8b564391e5706d5d76be.zip | |
Rollup merge of #109554 - MU001999:master, r=WaffleLapkin
Suggest ..= when someone tries to create an overflowing range Fixes #109529
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_lint/messages.ftl | 4 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/lints.rs | 32 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/types.rs | 38 |
3 files changed, 59 insertions, 15 deletions
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 308c02929ca..8ec4c2b3d46 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1210,11 +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 = "{start}..={literal}{suffix}", applicability = "machine-applicable")] - pub suggestion: Span, - pub start: String, - 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 7ca50f5a2db..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}; @@ -136,6 +137,14 @@ fn lint_overflowing_range_endpoint<'tcx>( expr: &'tcx hir::Expr<'tcx>, ty: &str, ) -> bool { + // 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, expr.span) + }; + // We only want to handle exclusive (`..`) ranges, // which are represented as `ExprKind::Struct`. let par_id = cx.tcx.hir().parent_id(expr.hir_id); @@ -155,7 +164,6 @@ 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 }; use rustc_ast::{LitIntType, LitKind}; let suffix = match lit.node { @@ -164,16 +172,28 @@ fn lint_overflowing_range_endpoint<'tcx>( LitKind::Int(_, LitIntType::Unsuffixed) => "", _ => bug!(), }; - cx.emit_spanned_lint( - OVERFLOWING_LITERALS, - struct_expr.span, - RangeEndpointOutOfRange { - ty, - suggestion: struct_expr.span, + + 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, sub: sub_sugg }, ); // We've just emitted a lint, special cased for `(...)..MAX+1` ranges, |
