diff options
Diffstat (limited to 'compiler/rustc_lint/src/types.rs')
-rw-r--r-- | compiler/rustc_lint/src/types.rs | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 85958c417..a6ba74220 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}; @@ -17,7 +18,7 @@ use rustc_hir::{is_range_literal, Expr, ExprKind, Node}; use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{ - self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, + self, AdtKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; use rustc_span::def_id::LocalDefId; use rustc_span::source_map; @@ -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, @@ -750,7 +770,7 @@ pub(crate) fn repr_nullable_ptr<'tcx>( debug!("is_repr_nullable_ptr(cx, ty = {:?})", ty); if let ty::Adt(ty_def, substs) = ty.kind() { let field_ty = match &ty_def.variants().raw[..] { - [var_one, var_two] => match (&var_one.fields[..], &var_two.fields[..]) { + [var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) { ([], [field]) | ([field], []) => field.ty(cx.tcx, substs), _ => return None, }, |