[default_numeric_fallback
]: don't lint on return and macro calls with stated type
This commit is contained in:
parent
2793e8d103
commit
60c059114c
@ -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();
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user