Skip to content

Commit eba5ff9

Browse files
committed
Auto merge of #9636 - kraktus:numeric-fallback, r=dswij
[`default_numeric_fallback`] do not lint on constants fix #9632 changelog:[`default_numeric_fallback`] do not lint on constants
2 parents ff33d6e + d38175f commit eba5ff9

7 files changed

+107
-64
lines changed

clippy_lints/src/default_numeric_fallback.rs

+29-36
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use clippy_utils::diagnostics::span_lint_hir_and_then;
2-
use clippy_utils::numeric_literal;
32
use clippy_utils::source::snippet_opt;
3+
use clippy_utils::{get_parent_node, numeric_literal};
44
use if_chain::if_chain;
55
use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
66
use rustc_errors::Applicability;
77
use rustc_hir::{
88
intravisit::{walk_expr, walk_stmt, Visitor},
9-
Body, Expr, ExprKind, HirId, Lit, Stmt, StmtKind,
9+
Body, Expr, ExprKind, HirId, ItemKind, Lit, Node, Stmt, StmtKind,
1010
};
1111
use rustc_lint::{LateContext, LateLintPass, LintContext};
1212
use rustc_middle::{
@@ -55,22 +55,31 @@ declare_lint_pass!(DefaultNumericFallback => [DEFAULT_NUMERIC_FALLBACK]);
5555

5656
impl<'tcx> LateLintPass<'tcx> for DefaultNumericFallback {
5757
fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) {
58-
let mut visitor = NumericFallbackVisitor::new(cx);
58+
let is_parent_const = if let Some(Node::Item(item)) = get_parent_node(cx.tcx, body.id().hir_id) {
59+
matches!(item.kind, ItemKind::Const(..))
60+
} else {
61+
false
62+
};
63+
let mut visitor = NumericFallbackVisitor::new(cx, is_parent_const);
5964
visitor.visit_body(body);
6065
}
6166
}
6267

6368
struct NumericFallbackVisitor<'a, 'tcx> {
6469
/// Stack manages type bound of exprs. The top element holds current expr type.
65-
ty_bounds: Vec<TyBound<'tcx>>,
70+
ty_bounds: Vec<ExplicitTyBound>,
6671

6772
cx: &'a LateContext<'tcx>,
6873
}
6974

7075
impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
71-
fn new(cx: &'a LateContext<'tcx>) -> Self {
76+
fn new(cx: &'a LateContext<'tcx>, is_parent_const: bool) -> Self {
7277
Self {
73-
ty_bounds: vec![TyBound::Nothing],
78+
ty_bounds: vec![if is_parent_const {
79+
ExplicitTyBound(true)
80+
} else {
81+
ExplicitTyBound(false)
82+
}],
7483
cx,
7584
}
7685
}
@@ -79,10 +88,9 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
7988
fn check_lit(&self, lit: &Lit, lit_ty: Ty<'tcx>, emit_hir_id: HirId) {
8089
if_chain! {
8190
if !in_external_macro(self.cx.sess(), lit.span);
82-
if let Some(ty_bound) = self.ty_bounds.last();
91+
if matches!(self.ty_bounds.last(), Some(ExplicitTyBound(false)));
8392
if matches!(lit.node,
8493
LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed));
85-
if !ty_bound.is_numeric();
8694
then {
8795
let (suffix, is_float) = match lit_ty.kind() {
8896
ty::Int(IntTy::I32) => ("i32", false),
@@ -123,7 +131,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
123131
if let Some(fn_sig) = fn_sig_opt(self.cx, func.hir_id) {
124132
for (expr, bound) in iter::zip(*args, fn_sig.skip_binder().inputs()) {
125133
// Push found arg type, then visit arg.
126-
self.ty_bounds.push(TyBound::Ty(*bound));
134+
self.ty_bounds.push((*bound).into());
127135
self.visit_expr(expr);
128136
self.ty_bounds.pop();
129137
}
@@ -135,7 +143,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
135143
if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(expr.hir_id) {
136144
let fn_sig = self.cx.tcx.fn_sig(def_id).skip_binder();
137145
for (expr, bound) in iter::zip(std::iter::once(*receiver).chain(args.iter()), fn_sig.inputs()) {
138-
self.ty_bounds.push(TyBound::Ty(*bound));
146+
self.ty_bounds.push((*bound).into());
139147
self.visit_expr(expr);
140148
self.ty_bounds.pop();
141149
}
@@ -169,7 +177,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
169177

170178
// Visit base with no bound.
171179
if let Some(base) = base {
172-
self.ty_bounds.push(TyBound::Nothing);
180+
self.ty_bounds.push(ExplicitTyBound(false));
173181
self.visit_expr(base);
174182
self.ty_bounds.pop();
175183
}
@@ -192,15 +200,10 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
192200

193201
fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
194202
match stmt.kind {
195-
StmtKind::Local(local) => {
196-
if local.ty.is_some() {
197-
self.ty_bounds.push(TyBound::Any);
198-
} else {
199-
self.ty_bounds.push(TyBound::Nothing);
200-
}
201-
},
203+
// we cannot check the exact type since it's a hir::Ty which does not implement `is_numeric`
204+
StmtKind::Local(local) => self.ty_bounds.push(ExplicitTyBound(local.ty.is_some())),
202205

203-
_ => self.ty_bounds.push(TyBound::Nothing),
206+
_ => self.ty_bounds.push(ExplicitTyBound(false)),
204207
}
205208

206209
walk_stmt(self, stmt);
@@ -218,28 +221,18 @@ fn fn_sig_opt<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<PolyFnSig<'
218221
}
219222
}
220223

224+
/// Wrapper around a `bool` to make the meaning of the value clearer
221225
#[derive(Debug, Clone, Copy)]
222-
enum TyBound<'tcx> {
223-
Any,
224-
Ty(Ty<'tcx>),
225-
Nothing,
226-
}
226+
struct ExplicitTyBound(pub bool);
227227

228-
impl<'tcx> TyBound<'tcx> {
229-
fn is_numeric(self) -> bool {
230-
match self {
231-
TyBound::Any => true,
232-
TyBound::Ty(t) => t.is_numeric(),
233-
TyBound::Nothing => false,
234-
}
228+
impl<'tcx> From<Ty<'tcx>> for ExplicitTyBound {
229+
fn from(v: Ty<'tcx>) -> Self {
230+
Self(v.is_numeric())
235231
}
236232
}
237233

238-
impl<'tcx> From<Option<Ty<'tcx>>> for TyBound<'tcx> {
234+
impl<'tcx> From<Option<Ty<'tcx>>> for ExplicitTyBound {
239235
fn from(v: Option<Ty<'tcx>>) -> Self {
240-
match v {
241-
Some(t) => TyBound::Ty(t),
242-
None => TyBound::Nothing,
243-
}
236+
Self(v.map_or(false, Ty::is_numeric))
244237
}
245238
}

tests/ui/default_numeric_fallback_f64.fixed

+9
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ mod basic_expr {
3333
let x: [f64; 3] = [1., 2., 3.];
3434
let x: (f64, f64) = if true { (1., 2.) } else { (3., 4.) };
3535
let x: _ = 1.;
36+
const X: f32 = 1.;
3637
}
3738
}
3839

@@ -59,6 +60,14 @@ mod nested_local {
5960
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
6061
2.
6162
};
63+
64+
const X: f32 = {
65+
// Should lint this because this literal is not bound to any types.
66+
let y = 1.0_f64;
67+
68+
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
69+
1.
70+
};
6271
}
6372
}
6473

tests/ui/default_numeric_fallback_f64.rs

+9
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ mod basic_expr {
3333
let x: [f64; 3] = [1., 2., 3.];
3434
let x: (f64, f64) = if true { (1., 2.) } else { (3., 4.) };
3535
let x: _ = 1.;
36+
const X: f32 = 1.;
3637
}
3738
}
3839

@@ -59,6 +60,14 @@ mod nested_local {
5960
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
6061
2.
6162
};
63+
64+
const X: f32 = {
65+
// Should lint this because this literal is not bound to any types.
66+
let y = 1.;
67+
68+
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
69+
1.
70+
};
6271
}
6372
}
6473

tests/ui/default_numeric_fallback_f64.stderr

+20-14
Original file line numberDiff line numberDiff line change
@@ -61,79 +61,85 @@ LL | _ => 1.,
6161
| ^^ help: consider adding suffix: `1.0_f64`
6262

6363
error: default numeric fallback might occur
64-
--> $DIR/default_numeric_fallback_f64.rs:43:21
64+
--> $DIR/default_numeric_fallback_f64.rs:44:21
6565
|
6666
LL | let y = 1.;
6767
| ^^ help: consider adding suffix: `1.0_f64`
6868

6969
error: default numeric fallback might occur
70-
--> $DIR/default_numeric_fallback_f64.rs:51:21
70+
--> $DIR/default_numeric_fallback_f64.rs:52:21
7171
|
7272
LL | let y = 1.;
7373
| ^^ help: consider adding suffix: `1.0_f64`
7474

7575
error: default numeric fallback might occur
76-
--> $DIR/default_numeric_fallback_f64.rs:57:21
76+
--> $DIR/default_numeric_fallback_f64.rs:58:21
7777
|
7878
LL | let y = 1.;
7979
| ^^ help: consider adding suffix: `1.0_f64`
8080

8181
error: default numeric fallback might occur
82-
--> $DIR/default_numeric_fallback_f64.rs:69:9
82+
--> $DIR/default_numeric_fallback_f64.rs:66:21
83+
|
84+
LL | let y = 1.;
85+
| ^^ help: consider adding suffix: `1.0_f64`
86+
87+
error: default numeric fallback might occur
88+
--> $DIR/default_numeric_fallback_f64.rs:78:9
8389
|
8490
LL | 1.
8591
| ^^ help: consider adding suffix: `1.0_f64`
8692

8793
error: default numeric fallback might occur
88-
--> $DIR/default_numeric_fallback_f64.rs:75:27
94+
--> $DIR/default_numeric_fallback_f64.rs:84:27
8995
|
9096
LL | let f = || -> _ { 1. };
9197
| ^^ help: consider adding suffix: `1.0_f64`
9298

9399
error: default numeric fallback might occur
94-
--> $DIR/default_numeric_fallback_f64.rs:79:29
100+
--> $DIR/default_numeric_fallback_f64.rs:88:29
95101
|
96102
LL | let f = || -> f64 { 1. };
97103
| ^^ help: consider adding suffix: `1.0_f64`
98104

99105
error: default numeric fallback might occur
100-
--> $DIR/default_numeric_fallback_f64.rs:93:21
106+
--> $DIR/default_numeric_fallback_f64.rs:102:21
101107
|
102108
LL | generic_arg(1.);
103109
| ^^ help: consider adding suffix: `1.0_f64`
104110

105111
error: default numeric fallback might occur
106-
--> $DIR/default_numeric_fallback_f64.rs:96:32
112+
--> $DIR/default_numeric_fallback_f64.rs:105:32
107113
|
108114
LL | let x: _ = generic_arg(1.);
109115
| ^^ help: consider adding suffix: `1.0_f64`
110116

111117
error: default numeric fallback might occur
112-
--> $DIR/default_numeric_fallback_f64.rs:114:28
118+
--> $DIR/default_numeric_fallback_f64.rs:123:28
113119
|
114120
LL | GenericStruct { x: 1. };
115121
| ^^ help: consider adding suffix: `1.0_f64`
116122

117123
error: default numeric fallback might occur
118-
--> $DIR/default_numeric_fallback_f64.rs:117:36
124+
--> $DIR/default_numeric_fallback_f64.rs:126:36
119125
|
120126
LL | let _ = GenericStruct { x: 1. };
121127
| ^^ help: consider adding suffix: `1.0_f64`
122128

123129
error: default numeric fallback might occur
124-
--> $DIR/default_numeric_fallback_f64.rs:135:24
130+
--> $DIR/default_numeric_fallback_f64.rs:144:24
125131
|
126132
LL | GenericEnum::X(1.);
127133
| ^^ help: consider adding suffix: `1.0_f64`
128134

129135
error: default numeric fallback might occur
130-
--> $DIR/default_numeric_fallback_f64.rs:155:23
136+
--> $DIR/default_numeric_fallback_f64.rs:164:23
131137
|
132138
LL | s.generic_arg(1.);
133139
| ^^ help: consider adding suffix: `1.0_f64`
134140

135141
error: default numeric fallback might occur
136-
--> $DIR/default_numeric_fallback_f64.rs:162:21
142+
--> $DIR/default_numeric_fallback_f64.rs:171:21
137143
|
138144
LL | let x = 22.;
139145
| ^^^ help: consider adding suffix: `22.0_f64`
@@ -143,5 +149,5 @@ LL | internal_macro!();
143149
|
144150
= note: this error originates in the macro `internal_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
145151

146-
error: aborting due to 23 previous errors
152+
error: aborting due to 24 previous errors
147153

tests/ui/default_numeric_fallback_i32.fixed

+10
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ mod basic_expr {
3333
let x: [i32; 3] = [1, 2, 3];
3434
let x: (i32, i32) = if true { (1, 2) } else { (3, 4) };
3535
let x: _ = 1;
36+
let x: u64 = 1;
37+
const CONST_X: i8 = 1;
3638
}
3739
}
3840

@@ -59,6 +61,14 @@ mod nested_local {
5961
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
6062
2
6163
};
64+
65+
const CONST_X: i32 = {
66+
// Should lint this because this literal is not bound to any types.
67+
let y = 1_i32;
68+
69+
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
70+
1
71+
};
6272
}
6373
}
6474

tests/ui/default_numeric_fallback_i32.rs

+10
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ mod basic_expr {
3333
let x: [i32; 3] = [1, 2, 3];
3434
let x: (i32, i32) = if true { (1, 2) } else { (3, 4) };
3535
let x: _ = 1;
36+
let x: u64 = 1;
37+
const CONST_X: i8 = 1;
3638
}
3739
}
3840

@@ -59,6 +61,14 @@ mod nested_local {
5961
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
6062
2
6163
};
64+
65+
const CONST_X: i32 = {
66+
// Should lint this because this literal is not bound to any types.
67+
let y = 1;
68+
69+
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
70+
1
71+
};
6272
}
6373
}
6474

0 commit comments

Comments
 (0)