Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 60c0591

Browse files
committed
[default_numeric_fallback]: don't lint on return and macro calls with stated type
1 parent 2793e8d commit 60c0591

6 files changed

+121
-22
lines changed

clippy_lints/src/default_numeric_fallback.rs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use clippy_utils::{get_parent_node, numeric_literal};
44
use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
55
use rustc_errors::Applicability;
66
use rustc_hir::intravisit::{walk_expr, walk_stmt, Visitor};
7-
use rustc_hir::{Body, Expr, ExprKind, HirId, ItemKind, Lit, Node, Stmt, StmtKind};
7+
use rustc_hir::{Block, Body, Expr, ExprKind, FnRetTy, HirId, ItemKind, Lit, Node, Stmt, StmtKind};
88
use rustc_lint::{LateContext, LateLintPass, LintContext};
99
use rustc_middle::lint::in_external_macro;
1010
use rustc_middle::ty::{self, FloatTy, IntTy, PolyFnSig, Ty};
@@ -122,13 +122,42 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
122122
impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
123123
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
124124
match &expr.kind {
125+
ExprKind::Block(
126+
Block {
127+
stmts, expr: Some(_), ..
128+
},
129+
_,
130+
) => {
131+
if let Some(parent) = self.cx.tcx.hir().find_parent(expr.hir_id)
132+
&& let Some(fn_sig) = parent.fn_sig()
133+
&& let FnRetTy::Return(_ty) = fn_sig.decl.output
134+
{
135+
// We cannot check the exact type since it's a `hir::Ty`` which does not implement `is_numeric`
136+
self.ty_bounds.push(ExplicitTyBound(true));
137+
for stmt in *stmts {
138+
self.visit_stmt(stmt);
139+
}
140+
self.ty_bounds.pop();
141+
// Ignore return expr since we know its type was inferred from return ty
142+
return;
143+
}
144+
},
145+
146+
// Ignore return expr since we know its type was inferred from return ty
147+
ExprKind::Ret(_) => return,
148+
125149
ExprKind::Call(func, args) => {
126150
if let Some(fn_sig) = fn_sig_opt(self.cx, func.hir_id) {
127151
for (expr, bound) in iter::zip(*args, fn_sig.skip_binder().inputs()) {
128-
// Push found arg type, then visit arg.
129-
self.ty_bounds.push((*bound).into());
130-
self.visit_expr(expr);
131-
self.ty_bounds.pop();
152+
// If is from macro, try to use last bound type (typically pushed when visiting stmt),
153+
// otherwise push found arg type, then visit arg,
154+
if expr.span.from_expansion() {
155+
self.visit_expr(expr);
156+
} else {
157+
self.ty_bounds.push((*bound).into());
158+
self.visit_expr(expr);
159+
self.ty_bounds.pop();
160+
}
132161
}
133162
return;
134163
}
@@ -137,7 +166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
137166
ExprKind::MethodCall(_, receiver, args, _) => {
138167
if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(expr.hir_id) {
139168
let fn_sig = self.cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder();
140-
for (expr, bound) in iter::zip(std::iter::once(*receiver).chain(args.iter()), fn_sig.inputs()) {
169+
for (expr, bound) in iter::zip(iter::once(*receiver).chain(args.iter()), fn_sig.inputs()) {
141170
self.ty_bounds.push((*bound).into());
142171
self.visit_expr(expr);
143172
self.ty_bounds.pop();

tests/ui/default_numeric_fallback_f64.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ mod function_def {
7575
fn ret_f64() -> f64 {
7676
// Even though the output type is specified,
7777
// this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
78-
1.0_f64
78+
1.
7979
}
8080

8181
fn test() {

tests/ui/default_numeric_fallback_f64.stderr

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,6 @@ error: default numeric fallback might occur
8585
LL | let y = 1.;
8686
| ^^ help: consider adding suffix: `1.0_f64`
8787

88-
error: default numeric fallback might occur
89-
--> $DIR/default_numeric_fallback_f64.rs:78:9
90-
|
91-
LL | 1.
92-
| ^^ help: consider adding suffix: `1.0_f64`
93-
9488
error: default numeric fallback might occur
9589
--> $DIR/default_numeric_fallback_f64.rs:84:27
9690
|
@@ -147,5 +141,5 @@ LL | inline!(let x = 22.;);
147141
|
148142
= note: this error originates in the macro `__inline_mac_fn_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
149143

150-
error: aborting due to 24 previous errors
144+
error: aborting due to 23 previous errors
151145

tests/ui/default_numeric_fallback_i32.fixed

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ mod function_def {
7676
fn ret_i32() -> i32 {
7777
// Even though the output type is specified,
7878
// this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
79-
1_i32
79+
1
8080
}
8181

8282
fn test() {
@@ -186,4 +186,36 @@ fn check_expect_suppression() {
186186
let x = 21;
187187
}
188188

189+
mod type_already_infered {
190+
// Should NOT lint if bound to return type
191+
fn ret_i32() -> i32 {
192+
1
193+
}
194+
195+
// Should NOT lint if bound to return type
196+
fn ret_if_i32(b: bool) -> i32 {
197+
if b { 100 } else { 0 }
198+
}
199+
200+
// Should NOT lint if bound to return type
201+
fn ret_i32_tuple() -> (i32, i32) {
202+
(0, 1)
203+
}
204+
205+
// Should NOT lint if bound to return type
206+
fn ret_stmt(b: bool) -> (i32, i32) {
207+
if b {
208+
return (0, 1);
209+
}
210+
(0, 0)
211+
}
212+
213+
#[allow(clippy::useless_vec)]
214+
fn vec_macro() {
215+
// Should NOT lint in `vec!` call if the type was already stated
216+
let data_i32: Vec<i32> = vec![1, 2, 3];
217+
let data_i32 = vec![1_i32, 2_i32, 3_i32];
218+
}
219+
}
220+
189221
fn main() {}

tests/ui/default_numeric_fallback_i32.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,4 +186,36 @@ fn check_expect_suppression() {
186186
let x = 21;
187187
}
188188

189+
mod type_already_infered {
190+
// Should NOT lint if bound to return type
191+
fn ret_i32() -> i32 {
192+
1
193+
}
194+
195+
// Should NOT lint if bound to return type
196+
fn ret_if_i32(b: bool) -> i32 {
197+
if b { 100 } else { 0 }
198+
}
199+
200+
// Should NOT lint if bound to return type
201+
fn ret_i32_tuple() -> (i32, i32) {
202+
(0, 1)
203+
}
204+
205+
// Should NOT lint if bound to return type
206+
fn ret_stmt(b: bool) -> (i32, i32) {
207+
if b {
208+
return (0, 1);
209+
}
210+
(0, 0)
211+
}
212+
213+
#[allow(clippy::useless_vec)]
214+
fn vec_macro() {
215+
// Should NOT lint in `vec!` call if the type was already stated
216+
let data_i32: Vec<i32> = vec![1, 2, 3];
217+
let data_i32 = vec![1, 2, 3];
218+
}
219+
}
220+
189221
fn main() {}

tests/ui/default_numeric_fallback_i32.stderr

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,6 @@ error: default numeric fallback might occur
9797
LL | let y = 1;
9898
| ^ help: consider adding suffix: `1_i32`
9999

100-
error: default numeric fallback might occur
101-
--> $DIR/default_numeric_fallback_i32.rs:79:9
102-
|
103-
LL | 1
104-
| ^ help: consider adding suffix: `1_i32`
105-
106100
error: default numeric fallback might occur
107101
--> $DIR/default_numeric_fallback_i32.rs:85:27
108102
|
@@ -159,5 +153,23 @@ LL | inline!(let x = 22;);
159153
|
160154
= note: this error originates in the macro `__inline_mac_fn_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
161155

162-
error: aborting due to 26 previous errors
156+
error: default numeric fallback might occur
157+
--> $DIR/default_numeric_fallback_i32.rs:217:29
158+
|
159+
LL | let data_i32 = vec![1, 2, 3];
160+
| ^ help: consider adding suffix: `1_i32`
161+
162+
error: default numeric fallback might occur
163+
--> $DIR/default_numeric_fallback_i32.rs:217:32
164+
|
165+
LL | let data_i32 = vec![1, 2, 3];
166+
| ^ help: consider adding suffix: `2_i32`
167+
168+
error: default numeric fallback might occur
169+
--> $DIR/default_numeric_fallback_i32.rs:217:35
170+
|
171+
LL | let data_i32 = vec![1, 2, 3];
172+
| ^ help: consider adding suffix: `3_i32`
173+
174+
error: aborting due to 28 previous errors
163175

0 commit comments

Comments
 (0)