Skip to content

Commit 8fb7a49

Browse files
oslfmtsmoelius
authored andcommitted
fix requested changes and upgrade dylint
1 parent f385169 commit 8fb7a49

File tree

1 file changed

+49
-52
lines changed

1 file changed

+49
-52
lines changed

lints/type_cosplay/src/lib.rs

Lines changed: 49 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ extern crate rustc_middle;
99
extern crate rustc_span;
1010

1111
use clippy_utils::{
12-
diagnostics::span_lint_and_help, get_trait_def_id, match_def_path, ty::implements_trait,
12+
diagnostics::span_lint_and_help, get_trait_def_id, match_def_path, ty::{match_type, implements_trait},
1313
};
1414
use rustc_data_structures::fx::FxHashMap;
1515
use rustc_hir::{def::Res, Expr, ExprKind, QPath, TyKind};
1616
use rustc_index::vec::Idx;
1717
use rustc_lint::{LateContext, LateLintPass};
1818
use rustc_middle::ty::{AdtDef, AdtKind, TyKind as MiddleTyKind};
1919
use rustc_span::{def_id::DefId, Span};
20-
use solana_lints::paths;
20+
use solana_lints::{paths, utils::visit_expr_no_bodies};
2121

2222
use if_chain::if_chain;
2323

@@ -74,51 +74,48 @@ impl<'tcx> LateLintPass<'tcx> for TypeCosplay {
7474
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
7575
if_chain! {
7676
if !expr.span.from_expansion();
77-
if let ExprKind::Call(fnc_expr, _args_exprs) = expr.kind;
78-
// TODO: is the following if statement really needed?? don't think it's ever used.
79-
// all it does is check if AccountInfo.data is referenced...but what bytes we deser
80-
// from shouldn't impact if this is a type-cosplay issue or not.
81-
// walk each argument expression and see if the data field is referenced
82-
// TODO: maybe just check arg is a byte array
83-
// if args_exprs.iter().any(|arg| {
84-
// visit_expr_no_bodies(arg, |expr| contains_data_field_reference(cx, expr))
85-
// });
77+
if let ExprKind::Call(fnc_expr, args_exprs) = expr.kind;
78+
// TODO: recommended case will exit early since it contains a reference to AccountInfo.data,
79+
// not a direct argument. In general, any references will fail
80+
if args_exprs.iter().any(|arg| {
81+
visit_expr_no_bodies(arg, |expr| contains_data_field_reference(cx, expr))
82+
});
8683
// get the type that the function was called on, ie X in X::call()
8784
if let ExprKind::Path(qpath) = &fnc_expr.kind;
8885
if let QPath::TypeRelative(ty, _) = qpath;
8986
if let TyKind::Path(ty_qpath) = &ty.kind;
9087
let res = cx.typeck_results().qpath_res(ty_qpath, ty.hir_id);
9188
if let Res::Def(_, def_id) = res;
9289
let middle_ty = cx.tcx.type_of(def_id);
93-
if let Some(trait_did) = get_trait_def_id(cx, &paths::ANCHOR_DISCRIMINATOR_TRAIT);
9490
then {
95-
if implements_trait(cx, middle_ty, trait_did, &[]) {
96-
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(fnc_expr.hir_id)
97-
{
98-
if !match_def_path(cx, def_id, &paths::ANCHOR_TRY_DESERIALIZE) {
99-
span_lint_and_help(
100-
cx,
101-
TYPE_COSPLAY,
102-
fnc_expr.span,
103-
&format!("`{}` type implements the `Discriminator` trait. If you are attempting to deserialize\n here and `{}` is annotated with #[account] use try_deserialize() instead.",
104-
middle_ty,
105-
middle_ty
106-
),
107-
None,
108-
"otherwise, make sure you are accounting for this type's discriminator in your deserialization function"
109-
);
110-
}
111-
}
112-
} else {
113-
// currently only checks borsh::try_from_slice()
114-
if is_deserialize_function(cx, fnc_expr) {
115-
if let MiddleTyKind::Adt(adt_def, _) = middle_ty.kind() {
116-
let adt_kind = adt_def.adt_kind();
117-
let def_id = adt_def.did();
118-
if let Some(vec) = self.deser_types.get_mut(&adt_kind) {
119-
vec.push((def_id, ty.span));
120-
} else {
121-
self.deser_types.insert(adt_kind, vec![(def_id, ty.span)]);
91+
if_chain! {
92+
if let Some(trait_did) = get_trait_def_id(cx, &paths::ANCHOR_DISCRIMINATOR_TRAIT);
93+
if implements_trait(cx, middle_ty, trait_did, &[]);
94+
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(fnc_expr.hir_id);
95+
if !match_def_path(cx, def_id, &paths::ANCHOR_TRY_DESERIALIZE);
96+
then {
97+
span_lint_and_help(
98+
cx,
99+
TYPE_COSPLAY,
100+
fnc_expr.span,
101+
&format!("`{}` type implements the `Discriminator` trait. If you are attempting to deserialize\n here and `{}` is annotated with #[account] use try_deserialize() instead.",
102+
middle_ty,
103+
middle_ty
104+
),
105+
None,
106+
"otherwise, make sure you are accounting for this type's discriminator in your deserialization function"
107+
);
108+
} else {
109+
// currently only checks borsh::try_from_slice()
110+
if is_deserialize_function(cx, fnc_expr) {
111+
if let MiddleTyKind::Adt(adt_def, _) = middle_ty.kind() {
112+
let adt_kind = adt_def.adt_kind();
113+
let def_id = adt_def.did();
114+
if let Some(vec) = self.deser_types.get_mut(&adt_kind) {
115+
vec.push((def_id, ty.span));
116+
} else {
117+
self.deser_types.insert(adt_kind, vec![(def_id, ty.span)]);
118+
}
122119
}
123120
}
124121
}
@@ -161,19 +158,19 @@ fn is_deserialize_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
161158
}
162159
}
163160

164-
// fn contains_data_field_reference(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
165-
// if_chain! {
166-
// if let ExprKind::Field(obj_expr, ident) = expr.kind;
167-
// if ident.as_str() == "data";
168-
// let ty = cx.typeck_results().expr_ty(obj_expr);
169-
// if match_type(cx, ty, &paths::SOLANA_PROGRAM_ACCOUNT_INFO);
170-
// then {
171-
// true
172-
// } else {
173-
// false
174-
// }
175-
// }
176-
// }
161+
fn contains_data_field_reference(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
162+
if_chain! {
163+
if let ExprKind::Field(obj_expr, ident) = expr.kind;
164+
if ident.as_str() == "data";
165+
let ty = cx.typeck_results().expr_ty(obj_expr);
166+
if match_type(cx, ty, &paths::SOLANA_PROGRAM_ACCOUNT_INFO);
167+
then {
168+
true
169+
} else {
170+
false
171+
}
172+
}
173+
}
177174

178175
fn check_enums(cx: &LateContext<'_>, enums: &Vec<(DefId, Span)>) {
179176
#[allow(clippy::comparison_chain)]

0 commit comments

Comments
 (0)