diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 0060f33888ebd..3c8a7ada4bf12 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -557,7 +557,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { } } } - hir::ExprKind::Lit(lit) => lint_literal(cx, self, e, lit), + hir::ExprKind::Lit(lit) => lint_literal(cx, self, e.hir_id, e.span, lit), hir::ExprKind::Call(path, [l, r]) if let ExprKind::Path(ref qpath) = path.kind && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs index 4b5163522f866..7d49b260acca8 100644 --- a/compiler/rustc_lint/src/types/literal.rs +++ b/compiler/rustc_lint/src/types/literal.rs @@ -1,8 +1,10 @@ use hir::{ExprKind, Node, is_range_literal}; use rustc_abi::{Integer, Size}; +use rustc_hir::HirId; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::{bug, ty}; +use rustc_span::Span; use {rustc_ast as ast, rustc_attr_parsing as attr, rustc_hir as hir}; use crate::LateContext; @@ -21,21 +23,22 @@ fn lint_overflowing_range_endpoint<'tcx>( lit: &hir::Lit, lit_val: u128, max: u128, - expr: &'tcx hir::Expr<'tcx>, + hir_id: HirId, + lit_span: Span, 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.parent_hir_node(expr.hir_id) + let (hir_id, span) = if let Node::Expr(par_expr) = cx.tcx.parent_hir_node(hir_id) && let ExprKind::Cast(_, _) = par_expr.kind { - (par_expr, expr.span) + (par_expr.hir_id, par_expr.span) } else { - (expr, expr.span) + (hir_id, lit_span) }; // We only want to handle exclusive (`..`) ranges, // which are represented as `ExprKind::Struct`. - let Node::ExprField(field) = cx.tcx.parent_hir_node(expr.hir_id) else { return false }; + let Node::ExprField(field) = cx.tcx.parent_hir_node(hir_id) else { return false }; let Node::Expr(struct_expr) = cx.tcx.parent_hir_node(field.hir_id) else { return false }; if !is_range_literal(struct_expr) { return false; @@ -45,7 +48,7 @@ fn lint_overflowing_range_endpoint<'tcx>( // We can suggest using an inclusive range // (`..=`) instead only if it is the `end` that is // overflowing and only by 1. - if !(end.expr.hir_id == expr.hir_id && lit_val - 1 == max) { + if !(end.expr.hir_id == hir_id && lit_val - 1 == max) { return false; }; @@ -57,7 +60,7 @@ fn lint_overflowing_range_endpoint<'tcx>( _ => bug!(), }; - let sub_sugg = if expr.span.lo() == lit_span.lo() { + let sub_sugg = if span.lo() == lit_span.lo() { let Ok(start) = cx.sess().source_map().span_to_snippet(start.span) else { return false }; UseInclusiveRange::WithoutParen { sugg: struct_expr.span.shrink_to_lo().to(lit_span.shrink_to_hi()), @@ -67,7 +70,7 @@ fn lint_overflowing_range_endpoint<'tcx>( } } else { UseInclusiveRange::WithParen { - eq_sugg: expr.span.shrink_to_lo(), + eq_sugg: span.shrink_to_lo(), lit_sugg: lit_span, literal: lit_val - 1, suffix, @@ -125,7 +128,8 @@ fn get_bin_hex_repr(cx: &LateContext<'_>, lit: &hir::Lit) -> Option { fn report_bin_hex_error( cx: &LateContext<'_>, - expr: &hir::Expr<'_>, + hir_id: HirId, + span: Span, ty: attr::IntType, size: Size, repr_str: String, @@ -144,11 +148,11 @@ fn report_bin_hex_error( }; let sign = if negative { OverflowingBinHexSign::Negative } else { OverflowingBinHexSign::Positive }; - let sub = get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative).map( + let sub = get_type_suggestion(cx.typeck_results().node_type(hir_id), val, negative).map( |suggestion_ty| { if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') { let (sans_suffix, _) = repr_str.split_at(pos); - OverflowingBinHexSub::Suggestion { span: expr.span, suggestion_ty, sans_suffix } + OverflowingBinHexSub::Suggestion { span, suggestion_ty, sans_suffix } } else { OverflowingBinHexSub::Help { suggestion_ty } } @@ -156,7 +160,7 @@ fn report_bin_hex_error( ); let sign_bit_sub = (!negative) .then(|| { - let ty::Int(int_ty) = cx.typeck_results().node_type(expr.hir_id).kind() else { + let ty::Int(int_ty) = cx.typeck_results().node_type(hir_id).kind() else { return None; }; @@ -177,7 +181,7 @@ fn report_bin_hex_error( }; Some(OverflowingBinHexSignBitSub { - span: expr.span, + span, lit_no_suffix, negative_val: actually.clone(), int_ty: int_ty.name_str(), @@ -186,7 +190,7 @@ fn report_bin_hex_error( }) .flatten(); - cx.emit_span_lint(OVERFLOWING_LITERALS, expr.span, OverflowingBinHex { + cx.emit_span_lint(OVERFLOWING_LITERALS, span, OverflowingBinHex { ty: t, lit: repr_str.clone(), dec: val, @@ -236,7 +240,8 @@ fn literal_to_i128(val: u128, negative: bool) -> Option { fn lint_int_literal<'tcx>( cx: &LateContext<'tcx>, type_limits: &TypeLimits, - e: &'tcx hir::Expr<'tcx>, + hir_id: HirId, + span: Span, lit: &hir::Lit, t: ty::IntTy, v: u128, @@ -244,7 +249,7 @@ fn lint_int_literal<'tcx>( let int_type = t.normalize(cx.sess().target.pointer_width); let (min, max) = int_ty_range(int_type); let max = max as u128; - let negative = type_limits.negated_expr_id == Some(e.hir_id); + let negative = type_limits.negated_expr_id == Some(hir_id); // Detect literal value out of range [min, max] inclusive // avoiding use of -min to prevent overflow/panic @@ -252,7 +257,8 @@ fn lint_int_literal<'tcx>( if let Some(repr_str) = get_bin_hex_repr(cx, lit) { report_bin_hex_error( cx, - e, + hir_id, + span, attr::IntType::SignedInt(ty::ast_int_ty(t)), Integer::from_int_ty(cx, t).size(), repr_str, @@ -262,18 +268,18 @@ fn lint_int_literal<'tcx>( return; } - if lint_overflowing_range_endpoint(cx, lit, v, max, e, t.name_str()) { + if lint_overflowing_range_endpoint(cx, lit, v, max, hir_id, span, t.name_str()) { // The overflowing literal lint was emitted by `lint_overflowing_range_endpoint`. return; } - let span = if negative { type_limits.negated_expr_span.unwrap() } else { e.span }; + let span = if negative { type_limits.negated_expr_span.unwrap() } else { span }; let lit = cx .sess() .source_map() .span_to_snippet(span) .unwrap_or_else(|_| if negative { format!("-{v}") } else { v.to_string() }); - let help = get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative) + let help = get_type_suggestion(cx.typeck_results().node_type(hir_id), v, negative) .map(|suggestion_ty| OverflowingIntHelp { suggestion_ty }); cx.emit_span_lint(OVERFLOWING_LITERALS, span, OverflowingInt { @@ -288,7 +294,8 @@ fn lint_int_literal<'tcx>( fn lint_uint_literal<'tcx>( cx: &LateContext<'tcx>, - e: &'tcx hir::Expr<'tcx>, + hir_id: HirId, + span: Span, lit: &hir::Lit, t: ty::UintTy, ) { @@ -302,7 +309,7 @@ fn lint_uint_literal<'tcx>( }; if lit_val < min || lit_val > max { - if let Node::Expr(par_e) = cx.tcx.parent_hir_node(e.hir_id) { + if let Node::Expr(par_e) = cx.tcx.parent_hir_node(hir_id) { match par_e.kind { hir::ExprKind::Cast(..) => { if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() { @@ -316,14 +323,15 @@ fn lint_uint_literal<'tcx>( _ => {} } } - if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, t.name_str()) { + if lint_overflowing_range_endpoint(cx, lit, lit_val, max, hir_id, span, t.name_str()) { // The overflowing literal lint was emitted by `lint_overflowing_range_endpoint`. return; } if let Some(repr_str) = get_bin_hex_repr(cx, lit) { report_bin_hex_error( cx, - e, + hir_id, + span, attr::IntType::UnsignedInt(ty::ast_uint_ty(t)), Integer::from_uint_ty(cx, t).size(), repr_str, @@ -332,7 +340,7 @@ fn lint_uint_literal<'tcx>( ); return; } - cx.emit_span_lint(OVERFLOWING_LITERALS, e.span, OverflowingUInt { + cx.emit_span_lint(OVERFLOWING_LITERALS, span, OverflowingUInt { ty: t.name_str(), lit: cx .sess() @@ -348,19 +356,20 @@ fn lint_uint_literal<'tcx>( pub(crate) fn lint_literal<'tcx>( cx: &LateContext<'tcx>, type_limits: &TypeLimits, - e: &'tcx hir::Expr<'tcx>, + hir_id: HirId, + span: Span, lit: &hir::Lit, ) { - match *cx.typeck_results().node_type(e.hir_id).kind() { + match *cx.typeck_results().node_type(hir_id).kind() { ty::Int(t) => { match lit.node { ast::LitKind::Int(v, ast::LitIntType::Signed(_) | ast::LitIntType::Unsuffixed) => { - lint_int_literal(cx, type_limits, e, lit, t, v.get()) + lint_int_literal(cx, type_limits, hir_id, span, lit, t, v.get()) } _ => bug!(), }; } - ty::Uint(t) => lint_uint_literal(cx, e, lit, t), + ty::Uint(t) => lint_uint_literal(cx, hir_id, span, lit, t), ty::Float(t) => { let (is_infinite, sym) = match lit.node { ast::LitKind::Float(v, _) => match t { @@ -374,7 +383,7 @@ pub(crate) fn lint_literal<'tcx>( _ => bug!(), }; if is_infinite == Ok(true) { - cx.emit_span_lint(OVERFLOWING_LITERALS, e.span, OverflowingLiteral { + cx.emit_span_lint(OVERFLOWING_LITERALS, span, OverflowingLiteral { ty: t.name_str(), lit: cx .sess()