[default_numeric_fallback]: don't lint on return and macro calls with stated type

This commit is contained in:
J-ZhengLi 2023-12-13 11:09:08 +08:00
parent 2793e8d103
commit 60c059114c
6 changed files with 121 additions and 22 deletions

View File

@ -4,7 +4,7 @@
use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, walk_stmt, Visitor};
use rustc_hir::{Body, Expr, ExprKind, HirId, ItemKind, Lit, Node, Stmt, StmtKind};
use rustc_hir::{Block, Body, Expr, ExprKind, FnRetTy, HirId, ItemKind, Lit, Node, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, FloatTy, IntTy, PolyFnSig, Ty};
@ -122,13 +122,42 @@ fn check_lit(&self, lit: &Lit, lit_ty: Ty<'tcx>, emit_hir_id: HirId) {
impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
match &expr.kind {
ExprKind::Block(
Block {
stmts, expr: Some(_), ..
},
_,
) => {
if let Some(parent) = self.cx.tcx.hir().find_parent(expr.hir_id)
&& let Some(fn_sig) = parent.fn_sig()
&& let FnRetTy::Return(_ty) = fn_sig.decl.output
{
// We cannot check the exact type since it's a `hir::Ty`` which does not implement `is_numeric`
self.ty_bounds.push(ExplicitTyBound(true));
for stmt in *stmts {
self.visit_stmt(stmt);
}
self.ty_bounds.pop();
// Ignore return expr since we know its type was inferred from return ty
return;
}
},
// Ignore return expr since we know its type was inferred from return ty
ExprKind::Ret(_) => return,
ExprKind::Call(func, args) => {
if let Some(fn_sig) = fn_sig_opt(self.cx, func.hir_id) {
for (expr, bound) in iter::zip(*args, fn_sig.skip_binder().inputs()) {
// Push found arg type, then visit arg.
self.ty_bounds.push((*bound).into());
self.visit_expr(expr);
self.ty_bounds.pop();
// If is from macro, try to use last bound type (typically pushed when visiting stmt),
// otherwise push found arg type, then visit arg,
if expr.span.from_expansion() {
self.visit_expr(expr);
} else {
self.ty_bounds.push((*bound).into());
self.visit_expr(expr);
self.ty_bounds.pop();
}
}
return;
}
@ -137,7 +166,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
ExprKind::MethodCall(_, receiver, args, _) => {
if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(expr.hir_id) {
let fn_sig = self.cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder();
for (expr, bound) in iter::zip(std::iter::once(*receiver).chain(args.iter()), fn_sig.inputs()) {
for (expr, bound) in iter::zip(iter::once(*receiver).chain(args.iter()), fn_sig.inputs()) {
self.ty_bounds.push((*bound).into());
self.visit_expr(expr);
self.ty_bounds.pop();

View File

@ -75,7 +75,7 @@ mod function_def {
fn ret_f64() -> f64 {
// Even though the output type is specified,
// this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
1.0_f64
1.
}
fn test() {

View File

@ -85,12 +85,6 @@ error: default numeric fallback might occur
LL | let y = 1.;
| ^^ help: consider adding suffix: `1.0_f64`
error: default numeric fallback might occur
--> $DIR/default_numeric_fallback_f64.rs:78:9
|
LL | 1.
| ^^ help: consider adding suffix: `1.0_f64`
error: default numeric fallback might occur
--> $DIR/default_numeric_fallback_f64.rs:84:27
|
@ -147,5 +141,5 @@ LL | inline!(let x = 22.;);
|
= note: this error originates in the macro `__inline_mac_fn_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 24 previous errors
error: aborting due to 23 previous errors

View File

@ -76,7 +76,7 @@ mod function_def {
fn ret_i32() -> i32 {
// Even though the output type is specified,
// this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
1_i32
1
}
fn test() {
@ -186,4 +186,36 @@ fn check_expect_suppression() {
let x = 21;
}
mod type_already_infered {
// Should NOT lint if bound to return type
fn ret_i32() -> i32 {
1
}
// Should NOT lint if bound to return type
fn ret_if_i32(b: bool) -> i32 {
if b { 100 } else { 0 }
}
// Should NOT lint if bound to return type
fn ret_i32_tuple() -> (i32, i32) {
(0, 1)
}
// Should NOT lint if bound to return type
fn ret_stmt(b: bool) -> (i32, i32) {
if b {
return (0, 1);
}
(0, 0)
}
#[allow(clippy::useless_vec)]
fn vec_macro() {
// Should NOT lint in `vec!` call if the type was already stated
let data_i32: Vec<i32> = vec![1, 2, 3];
let data_i32 = vec![1_i32, 2_i32, 3_i32];
}
}
fn main() {}

View File

@ -186,4 +186,36 @@ fn check_expect_suppression() {
let x = 21;
}
mod type_already_infered {
// Should NOT lint if bound to return type
fn ret_i32() -> i32 {
1
}
// Should NOT lint if bound to return type
fn ret_if_i32(b: bool) -> i32 {
if b { 100 } else { 0 }
}
// Should NOT lint if bound to return type
fn ret_i32_tuple() -> (i32, i32) {
(0, 1)
}
// Should NOT lint if bound to return type
fn ret_stmt(b: bool) -> (i32, i32) {
if b {
return (0, 1);
}
(0, 0)
}
#[allow(clippy::useless_vec)]
fn vec_macro() {
// Should NOT lint in `vec!` call if the type was already stated
let data_i32: Vec<i32> = vec![1, 2, 3];
let data_i32 = vec![1, 2, 3];
}
}
fn main() {}

View File

@ -97,12 +97,6 @@ error: default numeric fallback might occur
LL | let y = 1;
| ^ help: consider adding suffix: `1_i32`
error: default numeric fallback might occur
--> $DIR/default_numeric_fallback_i32.rs:79:9
|
LL | 1
| ^ help: consider adding suffix: `1_i32`
error: default numeric fallback might occur
--> $DIR/default_numeric_fallback_i32.rs:85:27
|
@ -159,5 +153,23 @@ LL | inline!(let x = 22;);
|
= note: this error originates in the macro `__inline_mac_fn_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 26 previous errors
error: default numeric fallback might occur
--> $DIR/default_numeric_fallback_i32.rs:217:29
|
LL | let data_i32 = vec![1, 2, 3];
| ^ help: consider adding suffix: `1_i32`
error: default numeric fallback might occur
--> $DIR/default_numeric_fallback_i32.rs:217:32
|
LL | let data_i32 = vec![1, 2, 3];
| ^ help: consider adding suffix: `2_i32`
error: default numeric fallback might occur
--> $DIR/default_numeric_fallback_i32.rs:217:35
|
LL | let data_i32 = vec![1, 2, 3];
| ^ help: consider adding suffix: `3_i32`
error: aborting due to 28 previous errors