1
Fork 0

Uniformly handle HIR literals in visitors and lints

This commit is contained in:
Oli Scherer 2025-02-01 10:06:35 +00:00
parent 9f5473f7ad
commit 9a2073d500
8 changed files with 57 additions and 29 deletions

View file

@ -345,6 +345,9 @@ pub trait Visitor<'v>: Sized {
fn visit_pat_expr(&mut self, expr: &'v PatExpr<'v>) -> Self::Result {
walk_pat_expr(self, expr)
}
fn visit_lit(&mut self, _hir_id: HirId, _lit: &'v Lit, _negated: bool) -> Self::Result {
Self::Result::output()
}
fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
walk_anon_const(self, c)
}
@ -764,7 +767,7 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'
pub fn walk_pat_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v PatExpr<'v>) -> V::Result {
try_visit!(visitor.visit_id(expr.hir_id));
match &expr.kind {
PatExprKind::Lit { .. } => V::Result::output(),
PatExprKind::Lit { lit, negated } => visitor.visit_lit(expr.hir_id, lit, *negated),
PatExprKind::ConstBlock(c) => visitor.visit_inline_const(c),
PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, expr.hir_id, expr.span),
}
@ -912,7 +915,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
try_visit!(visitor.visit_expr(expr));
visit_opt!(visitor, visit_ty_unambig, ty);
}
ExprKind::Lit(_) | ExprKind::Err(_) => {}
ExprKind::Lit(lit) => try_visit!(visitor.visit_lit(expression.hir_id, lit, false)),
ExprKind::Err(_) => {}
}
V::Result::output()
}

View file

@ -152,6 +152,10 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
hir_visit::walk_pat(self, p);
}
fn visit_lit(&mut self, hir_id: HirId, lit: &'tcx hir::Lit, negated: bool) {
lint_callback!(self, check_lit, hir_id, lit, negated);
}
fn visit_expr_field(&mut self, field: &'tcx hir::ExprField<'tcx>) {
self.with_lint_attrs(field.hir_id, |cx| hir_visit::walk_expr_field(cx, field))
}

View file

@ -23,6 +23,7 @@ macro_rules! late_lint_methods {
fn check_stmt(a: &'tcx rustc_hir::Stmt<'tcx>);
fn check_arm(a: &'tcx rustc_hir::Arm<'tcx>);
fn check_pat(a: &'tcx rustc_hir::Pat<'tcx>);
fn check_lit(hir_id: rustc_hir::HirId, a: &'tcx rustc_hir::Lit, negated: bool);
fn check_expr(a: &'tcx rustc_hir::Expr<'tcx>);
fn check_expr_post(a: &'tcx rustc_hir::Expr<'tcx>);
fn check_ty(a: &'tcx rustc_hir::Ty<'tcx, rustc_hir::AmbigArg>);

View file

@ -5,7 +5,7 @@ use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, VariantIdx, Variants, Wrapp
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::DiagMessage;
use rustc_hir::intravisit::VisitorExt;
use rustc_hir::{AmbigArg, Expr, ExprKind, LangItem};
use rustc_hir::{AmbigArg, Expr, ExprKind, HirId, LangItem};
use rustc_middle::bug;
use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton};
use rustc_middle::ty::{
@ -536,6 +536,16 @@ fn lint_fn_pointer<'tcx>(
}
impl<'tcx> LateLintPass<'tcx> for TypeLimits {
fn check_lit(
&mut self,
cx: &LateContext<'tcx>,
hir_id: HirId,
lit: &'tcx hir::Lit,
negated: bool,
) {
lint_literal(cx, self, hir_id, lit.span, lit, negated)
}
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) {
match e.kind {
hir::ExprKind::Unary(hir::UnOp::Neg, expr) => {
@ -557,7 +567,6 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
}
}
}
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()

View file

@ -245,11 +245,12 @@ fn lint_int_literal<'tcx>(
lit: &hir::Lit,
t: ty::IntTy,
v: u128,
negated: bool,
) {
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(hir_id);
let negative = negated ^ (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
@ -359,17 +360,21 @@ pub(crate) fn lint_literal<'tcx>(
hir_id: HirId,
span: Span,
lit: &hir::Lit,
negated: bool,
) {
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, hir_id, span, lit, t, v.get())
lint_int_literal(cx, type_limits, hir_id, span, lit, t, v.get(), negated)
}
_ => bug!(),
};
}
ty::Uint(t) => lint_uint_literal(cx, hir_id, span, lit, t),
ty::Uint(t) => {
assert!(!negated);
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 {