Skip to content

Commit 663191d

Browse files
committed
Uniformly handle HIR literals in visitors and lints
1 parent c766b94 commit 663191d

File tree

8 files changed

+57
-30
lines changed

8 files changed

+57
-30
lines changed

compiler/rustc_hir/src/intravisit.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,9 @@ pub trait Visitor<'v>: Sized {
345345
fn visit_pat_expr(&mut self, expr: &'v PatExpr<'v>) -> Self::Result {
346346
walk_pat_expr(self, expr)
347347
}
348+
fn visit_lit(&mut self, _hir_id: HirId, _lit: &'v Lit, _negated: bool) -> Self::Result {
349+
Self::Result::output()
350+
}
348351
fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
349352
walk_anon_const(self, c)
350353
}
@@ -754,7 +757,7 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'
754757
pub fn walk_pat_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v PatExpr<'v>) -> V::Result {
755758
try_visit!(visitor.visit_id(expr.hir_id));
756759
match &expr.kind {
757-
PatExprKind::Lit { .. } => V::Result::output(),
760+
PatExprKind::Lit { lit, negated } => visitor.visit_lit(expr.hir_id, lit, *negated),
758761
PatExprKind::ConstBlock(c) => visitor.visit_inline_const(c),
759762
PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, expr.hir_id, expr.span),
760763
}
@@ -902,7 +905,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
902905
try_visit!(visitor.visit_expr(expr));
903906
visit_opt!(visitor, visit_ty_unambig, ty);
904907
}
905-
ExprKind::Lit(_) | ExprKind::Err(_) => {}
908+
ExprKind::Lit(lit) => try_visit!(visitor.visit_lit(expression.hir_id, lit, false)),
909+
ExprKind::Err(_) => {}
906910
}
907911
V::Result::output()
908912
}

compiler/rustc_lint/src/late.rs

+4
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
152152
hir_visit::walk_pat(self, p);
153153
}
154154

155+
fn visit_lit(&mut self, hir_id: HirId, lit: &'tcx hir::Lit, negated: bool) {
156+
lint_callback!(self, check_lit, hir_id, lit, negated);
157+
}
158+
155159
fn visit_expr_field(&mut self, field: &'tcx hir::ExprField<'tcx>) {
156160
self.with_lint_attrs(field.hir_id, |cx| hir_visit::walk_expr_field(cx, field))
157161
}

compiler/rustc_lint/src/passes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ macro_rules! late_lint_methods {
2323
fn check_stmt(a: &'tcx rustc_hir::Stmt<'tcx>);
2424
fn check_arm(a: &'tcx rustc_hir::Arm<'tcx>);
2525
fn check_pat(a: &'tcx rustc_hir::Pat<'tcx>);
26+
fn check_lit(hir_id: rustc_hir::HirId, a: &'tcx rustc_hir::Lit, negated: bool);
2627
fn check_expr(a: &'tcx rustc_hir::Expr<'tcx>);
2728
fn check_expr_post(a: &'tcx rustc_hir::Expr<'tcx>);
2829
fn check_ty(a: &'tcx rustc_hir::Ty<'tcx, rustc_hir::AmbigArg>);

compiler/rustc_lint/src/types.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, VariantIdx, Variants, Wrapp
55
use rustc_data_structures::fx::FxHashSet;
66
use rustc_errors::DiagMessage;
77
use rustc_hir::intravisit::VisitorExt;
8-
use rustc_hir::{AmbigArg, Expr, ExprKind, LangItem};
8+
use rustc_hir::{AmbigArg, Expr, ExprKind, HirId, LangItem};
99
use rustc_middle::bug;
1010
use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton};
1111
use rustc_middle::ty::{
@@ -536,6 +536,16 @@ fn lint_fn_pointer<'tcx>(
536536
}
537537

538538
impl<'tcx> LateLintPass<'tcx> for TypeLimits {
539+
fn check_lit(
540+
&mut self,
541+
cx: &LateContext<'tcx>,
542+
hir_id: HirId,
543+
lit: &'tcx hir::Lit,
544+
negated: bool,
545+
) {
546+
lint_literal(cx, self, hir_id, lit.span, lit, negated)
547+
}
548+
539549
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) {
540550
match e.kind {
541551
hir::ExprKind::Unary(hir::UnOp::Neg, expr) => {
@@ -557,7 +567,6 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
557567
}
558568
}
559569
}
560-
hir::ExprKind::Lit(lit) => lint_literal(cx, self, e.hir_id, e.span, lit),
561570
hir::ExprKind::Call(path, [l, r])
562571
if let ExprKind::Path(ref qpath) = path.kind
563572
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()

compiler/rustc_lint/src/types/literal.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -245,11 +245,12 @@ fn lint_int_literal<'tcx>(
245245
lit: &hir::Lit,
246246
t: ty::IntTy,
247247
v: u128,
248+
negated: bool,
248249
) {
249250
let int_type = t.normalize(cx.sess().target.pointer_width);
250251
let (min, max) = int_ty_range(int_type);
251252
let max = max as u128;
252-
let negative = type_limits.negated_expr_id == Some(hir_id);
253+
let negative = negated ^ (type_limits.negated_expr_id == Some(hir_id));
253254

254255
// Detect literal value out of range [min, max] inclusive
255256
// avoiding use of -min to prevent overflow/panic
@@ -359,17 +360,21 @@ pub(crate) fn lint_literal<'tcx>(
359360
hir_id: HirId,
360361
span: Span,
361362
lit: &hir::Lit,
363+
negated: bool,
362364
) {
363365
match *cx.typeck_results().node_type(hir_id).kind() {
364366
ty::Int(t) => {
365367
match lit.node {
366368
ast::LitKind::Int(v, ast::LitIntType::Signed(_) | ast::LitIntType::Unsuffixed) => {
367-
lint_int_literal(cx, type_limits, hir_id, span, lit, t, v.get())
369+
lint_int_literal(cx, type_limits, hir_id, span, lit, t, v.get(), negated)
368370
}
369371
_ => bug!(),
370372
};
371373
}
372-
ty::Uint(t) => lint_uint_literal(cx, hir_id, span, lit, t),
374+
ty::Uint(t) => {
375+
assert!(!negated);
376+
lint_uint_literal(cx, hir_id, span, lit, t)
377+
}
373378
ty::Float(t) => {
374379
let (is_infinite, sym) = match lit.node {
375380
ast::LitKind::Float(v, _) => match t {

src/tools/clippy/clippy_lints/src/approx_const.rs

+15-21
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ use clippy_utils::diagnostics::span_lint_and_help;
33
use clippy_utils::msrvs::{self, Msrv};
44
use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
55
use rustc_attr_parsing::RustcVersion;
6-
use rustc_hir::{Expr, ExprKind};
6+
use rustc_hir::{HirId, Lit};
77
use rustc_lint::{LateContext, LateLintPass};
88
use rustc_session::impl_lint_pass;
9-
use rustc_span::symbol;
9+
use rustc_span::{Span, symbol};
1010
use std::f64::consts as f64;
1111

1212
declare_clippy_lint! {
@@ -74,29 +74,15 @@ impl ApproxConstant {
7474
}
7575
}
7676

77-
fn check_lit(&self, cx: &LateContext<'_>, lit: &LitKind, e: &Expr<'_>) {
78-
match *lit {
79-
LitKind::Float(s, LitFloatType::Suffixed(fty)) => match fty {
80-
FloatTy::F16 => self.check_known_consts(cx, e, s, "f16"),
81-
FloatTy::F32 => self.check_known_consts(cx, e, s, "f32"),
82-
FloatTy::F64 => self.check_known_consts(cx, e, s, "f64"),
83-
FloatTy::F128 => self.check_known_consts(cx, e, s, "f128"),
84-
},
85-
// FIXME(f16_f128): add `f16` and `f128` when these types become stable.
86-
LitKind::Float(s, LitFloatType::Unsuffixed) => self.check_known_consts(cx, e, s, "f{32, 64}"),
87-
_ => (),
88-
}
89-
}
90-
91-
fn check_known_consts(&self, cx: &LateContext<'_>, e: &Expr<'_>, s: symbol::Symbol, module: &str) {
77+
fn check_known_consts(&self, cx: &LateContext<'_>, span: Span, s: symbol::Symbol, module: &str) {
9278
let s = s.as_str();
9379
if s.parse::<f64>().is_ok() {
9480
for &(constant, name, min_digits, msrv) in &KNOWN_CONSTS {
9581
if is_approx_const(constant, s, min_digits) && msrv.is_none_or(|msrv| self.msrv.meets(msrv)) {
9682
span_lint_and_help(
9783
cx,
9884
APPROX_CONSTANT,
99-
e.span,
85+
span,
10086
format!("approximate value of `{module}::consts::{name}` found"),
10187
None,
10288
"consider using the constant directly",
@@ -111,9 +97,17 @@ impl ApproxConstant {
11197
impl_lint_pass!(ApproxConstant => [APPROX_CONSTANT]);
11298

11399
impl<'tcx> LateLintPass<'tcx> for ApproxConstant {
114-
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
115-
if let ExprKind::Lit(lit) = &e.kind {
116-
self.check_lit(cx, &lit.node, e);
100+
fn check_lit(&mut self, cx: &LateContext<'_>, _hir_id: HirId, lit: &Lit, _negated: bool) {
101+
match lit.node {
102+
LitKind::Float(s, LitFloatType::Suffixed(fty)) => match fty {
103+
FloatTy::F16 => self.check_known_consts(cx, lit.span, s, "f16"),
104+
FloatTy::F32 => self.check_known_consts(cx, lit.span, s, "f32"),
105+
FloatTy::F64 => self.check_known_consts(cx, lit.span, s, "f64"),
106+
FloatTy::F128 => self.check_known_consts(cx, lit.span, s, "f128"),
107+
},
108+
// FIXME(f16_f128): add `f16` and `f128` when these types become stable.
109+
LitKind::Float(s, LitFloatType::Unsuffixed) => self.check_known_consts(cx, lit.span, s, "f{32, 64}"),
110+
_ => (),
117111
}
118112
}
119113

tests/ui/pattern/overflowing-literals.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
#![feature(pattern_types)]
44
#![feature(pattern_type_macro)]
55

6-
//@ check-pass
7-
86
use std::pat::pattern_type;
97

108
// FIXME(pattern_types): also reject overflowing literals
@@ -14,6 +12,7 @@ type TooSmall = pattern_type!(i8 is -500..);
1412
fn main() {
1513
match 5_u8 {
1614
500 => {}
15+
//~^ ERROR literal out of range for `u8`
1716
_ => {}
1817
}
1918
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: literal out of range for `u8`
2+
--> $DIR/overflowing-literals.rs:14:9
3+
|
4+
LL | 500 => {}
5+
| ^^^
6+
|
7+
= note: the literal `500` does not fit into the type `u8` whose range is `0..=255`
8+
= note: `#[deny(overflowing_literals)]` on by default
9+
10+
error: aborting due to 1 previous error
11+

0 commit comments

Comments
 (0)