Handle struct ctor case
This commit is contained in:
@@ -64,7 +64,7 @@ struct NumericFallbackVisitor<'a, 'tcx> {
|
|||||||
impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
|
||||||
fn new(cx: &'a LateContext<'tcx>) -> Self {
|
fn new(cx: &'a LateContext<'tcx>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
ty_bounds: Vec::new(),
|
ty_bounds: vec![TyBound::Nothing],
|
||||||
cx,
|
cx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,6 +121,42 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
ExprKind::Struct(qpath, fields, base) => {
|
||||||
|
if_chain! {
|
||||||
|
if let Some(def_id) = self.cx.qpath_res(qpath, expr.hir_id).opt_def_id();
|
||||||
|
let ty = self.cx.tcx.type_of(def_id);
|
||||||
|
if let Some(adt_def) = ty.ty_adt_def();
|
||||||
|
if adt_def.is_struct();
|
||||||
|
if let Some(variant) = adt_def.variants.iter().next();
|
||||||
|
then {
|
||||||
|
let fields_def = &variant.fields;
|
||||||
|
|
||||||
|
// Push field type then visit each field expr.
|
||||||
|
for field in fields.iter() {
|
||||||
|
let bound =
|
||||||
|
fields_def
|
||||||
|
.iter()
|
||||||
|
.find_map(|f_def| {
|
||||||
|
if f_def.ident == field.ident
|
||||||
|
{ Some(self.cx.tcx.type_of(f_def.did)) }
|
||||||
|
else { None }
|
||||||
|
});
|
||||||
|
self.ty_bounds.push(bound.into());
|
||||||
|
self.visit_expr(field.expr);
|
||||||
|
self.ty_bounds.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visit base with no bound.
|
||||||
|
if let Some(base) = base {
|
||||||
|
self.ty_bounds.push(TyBound::Nothing);
|
||||||
|
self.visit_expr(base);
|
||||||
|
self.ty_bounds.pop();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
ExprKind::Lit(lit) => {
|
ExprKind::Lit(lit) => {
|
||||||
let ty = self.cx.typeck_results().expr_ty(expr);
|
let ty = self.cx.typeck_results().expr_ty(expr);
|
||||||
self.check_lit(lit, ty);
|
self.check_lit(lit, ty);
|
||||||
@@ -166,13 +202,13 @@ fn fn_sig_opt<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<PolyFnSig<'
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
enum TyBound<'ctx> {
|
enum TyBound<'tcx> {
|
||||||
Any,
|
Any,
|
||||||
Ty(Ty<'ctx>),
|
Ty(Ty<'tcx>),
|
||||||
Nothing,
|
Nothing,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> TyBound<'ctx> {
|
impl<'tcx> TyBound<'tcx> {
|
||||||
fn is_integral(self) -> bool {
|
fn is_integral(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
TyBound::Any => true,
|
TyBound::Any => true,
|
||||||
@@ -181,3 +217,12 @@ impl<'ctx> TyBound<'ctx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> From<Option<Ty<'tcx>>> for TyBound<'tcx> {
|
||||||
|
fn from(v: Option<Ty<'tcx>>) -> Self {
|
||||||
|
match v {
|
||||||
|
Some(t) => TyBound::Ty(t),
|
||||||
|
None => TyBound::Nothing,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,6 +39,20 @@ mod nested_local {
|
|||||||
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
|
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
|
||||||
1
|
1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let x: _ = if true {
|
||||||
|
// Should lint this because this literal is not bound to any types.
|
||||||
|
let y = 1;
|
||||||
|
|
||||||
|
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
// Should lint this because this literal is not bound to any types.
|
||||||
|
let y = 1;
|
||||||
|
|
||||||
|
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
|
||||||
|
2
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +60,7 @@ mod function_def {
|
|||||||
fn ret_i32() -> i32 {
|
fn ret_i32() -> i32 {
|
||||||
// Even though the output type is specified,
|
// Even though the output type is specified,
|
||||||
// this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
|
// this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
|
||||||
23
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test() {
|
fn test() {
|
||||||
@@ -77,6 +91,27 @@ mod function_calls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod struct_ctor {
|
||||||
|
struct ConcreteStruct {
|
||||||
|
x: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GenericStruct<T> {
|
||||||
|
x: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test() {
|
||||||
|
// Should NOT lint this because the field type is bound to a concrete type.
|
||||||
|
ConcreteStruct { x: 1 };
|
||||||
|
|
||||||
|
// Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type.
|
||||||
|
GenericStruct { x: 1 };
|
||||||
|
|
||||||
|
// Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type.
|
||||||
|
let _ = GenericStruct { x: 1 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod method_calls {
|
mod method_calls {
|
||||||
struct StructForMethodCallTest {}
|
struct StructForMethodCallTest {}
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,47 @@ LL | let y = 1;
|
|||||||
= help: consider adding suffix to avoid default numeric fallback
|
= help: consider adding suffix to avoid default numeric fallback
|
||||||
|
|
||||||
error: default numeric fallback might occur
|
error: default numeric fallback might occur
|
||||||
--> $DIR/default_numeric_fallback.rs:73:21
|
--> $DIR/default_numeric_fallback.rs:45:21
|
||||||
|
|
|
||||||
|
LL | let y = 1;
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= help: consider adding suffix to avoid default numeric fallback
|
||||||
|
|
||||||
|
error: default numeric fallback might occur
|
||||||
|
--> $DIR/default_numeric_fallback.rs:51:21
|
||||||
|
|
|
||||||
|
LL | let y = 1;
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= help: consider adding suffix to avoid default numeric fallback
|
||||||
|
|
||||||
|
error: default numeric fallback might occur
|
||||||
|
--> $DIR/default_numeric_fallback.rs:63:9
|
||||||
|
|
|
||||||
|
LL | 1
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= help: consider adding suffix to avoid default numeric fallback
|
||||||
|
|
||||||
|
error: default numeric fallback might occur
|
||||||
|
--> $DIR/default_numeric_fallback.rs:69:27
|
||||||
|
|
|
||||||
|
LL | let f = || -> _ { 1 };
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= help: consider adding suffix to avoid default numeric fallback
|
||||||
|
|
||||||
|
error: default numeric fallback might occur
|
||||||
|
--> $DIR/default_numeric_fallback.rs:73:29
|
||||||
|
|
|
||||||
|
LL | let f = || -> i32 { 1 };
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= help: consider adding suffix to avoid default numeric fallback
|
||||||
|
|
||||||
|
error: default numeric fallback might occur
|
||||||
|
--> $DIR/default_numeric_fallback.rs:87:21
|
||||||
|
|
|
|
||||||
LL | generic_arg(1);
|
LL | generic_arg(1);
|
||||||
| ^
|
| ^
|
||||||
@@ -120,7 +160,7 @@ LL | generic_arg(1);
|
|||||||
= help: consider adding suffix to avoid default numeric fallback
|
= help: consider adding suffix to avoid default numeric fallback
|
||||||
|
|
||||||
error: default numeric fallback might occur
|
error: default numeric fallback might occur
|
||||||
--> $DIR/default_numeric_fallback.rs:76:32
|
--> $DIR/default_numeric_fallback.rs:90:32
|
||||||
|
|
|
|
||||||
LL | let x: _ = generic_arg(1);
|
LL | let x: _ = generic_arg(1);
|
||||||
| ^
|
| ^
|
||||||
@@ -128,12 +168,28 @@ LL | let x: _ = generic_arg(1);
|
|||||||
= help: consider adding suffix to avoid default numeric fallback
|
= help: consider adding suffix to avoid default numeric fallback
|
||||||
|
|
||||||
error: default numeric fallback might occur
|
error: default numeric fallback might occur
|
||||||
--> $DIR/default_numeric_fallback.rs:96:23
|
--> $DIR/default_numeric_fallback.rs:108:28
|
||||||
|
|
|
||||||
|
LL | GenericStruct { x: 1 };
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= help: consider adding suffix to avoid default numeric fallback
|
||||||
|
|
||||||
|
error: default numeric fallback might occur
|
||||||
|
--> $DIR/default_numeric_fallback.rs:111:36
|
||||||
|
|
|
||||||
|
LL | let _ = GenericStruct { x: 1 };
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= help: consider adding suffix to avoid default numeric fallback
|
||||||
|
|
||||||
|
error: default numeric fallback might occur
|
||||||
|
--> $DIR/default_numeric_fallback.rs:131:23
|
||||||
|
|
|
|
||||||
LL | s.generic_arg(1);
|
LL | s.generic_arg(1);
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
= help: consider adding suffix to avoid default numeric fallback
|
= help: consider adding suffix to avoid default numeric fallback
|
||||||
|
|
||||||
error: aborting due to 17 previous errors
|
error: aborting due to 24 previous errors
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user