Skip to content

Commit 9782fc4

Browse files
committed
move not_unsafe_ptr_arg_deref to its own module
1 parent 7c028de commit 9782fc4

File tree

2 files changed

+131
-110
lines changed

2 files changed

+131
-110
lines changed

clippy_lints/src/functions/mod.rs

Lines changed: 6 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1+
mod not_unsafe_ptr_arg_deref;
12
mod too_many_arguments;
23
mod too_many_lines;
34

4-
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then};
5+
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
56
use clippy_utils::source::snippet_opt;
6-
use clippy_utils::ty::{is_must_use_ty, is_type_diagnostic_item, type_is_unsafe_function};
7-
use clippy_utils::{
8-
attr_by_name, attrs::is_proc_macro, iter_input_pats, match_def_path, must_use_attr, path_to_local, return_ty,
9-
trait_ref_of_method,
10-
};
7+
use clippy_utils::ty::{is_must_use_ty, is_type_diagnostic_item};
8+
use clippy_utils::{attr_by_name, attrs::is_proc_macro, match_def_path, must_use_attr, return_ty, trait_ref_of_method};
119
use if_chain::if_chain;
1210
use rustc_ast::ast::Attribute;
1311
use rustc_data_structures::fx::FxHashSet;
@@ -258,14 +256,7 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
258256
) {
259257
too_many_arguments::check_fn(cx, kind, decl, span, hir_id, self.too_many_arguments_threshold);
260258
too_many_lines::check(cx, span, body, self.too_many_lines_threshold);
261-
262-
let unsafety = match kind {
263-
intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _) => unsafety,
264-
intravisit::FnKind::Method(_, sig, _) => sig.header.unsafety,
265-
intravisit::FnKind::Closure => return,
266-
};
267-
268-
Self::check_raw_ptr(cx, unsafety, decl, body, hir_id);
259+
not_unsafe_ptr_arg_deref::check_fn(cx, kind, decl, body, hir_id);
269260
}
270261

271262
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
@@ -323,6 +314,7 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
323314

324315
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
325316
too_many_arguments::check_trait_item(cx, item, self.too_many_arguments_threshold);
317+
not_unsafe_ptr_arg_deref::check_trait_item(cx, item);
326318

327319
if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind {
328320
let is_public = cx.access_levels.is_exported(item.hir_id());
@@ -338,8 +330,6 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
338330
}
339331
if let hir::TraitFn::Provided(eid) = *eid {
340332
let body = cx.tcx.hir().body(eid);
341-
Self::check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.hir_id());
342-
343333
if attr.is_none() && is_public && !is_proc_macro(cx.sess(), attrs) {
344334
check_must_use_candidate(
345335
cx,
@@ -356,35 +346,6 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
356346
}
357347
}
358348

359-
impl<'tcx> Functions {
360-
fn check_raw_ptr(
361-
cx: &LateContext<'tcx>,
362-
unsafety: hir::Unsafety,
363-
decl: &'tcx hir::FnDecl<'_>,
364-
body: &'tcx hir::Body<'_>,
365-
hir_id: hir::HirId,
366-
) {
367-
let expr = &body.value;
368-
if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(hir_id) {
369-
let raw_ptrs = iter_input_pats(decl, body)
370-
.zip(decl.inputs.iter())
371-
.filter_map(|(arg, ty)| raw_ptr_arg(arg, ty))
372-
.collect::<FxHashSet<_>>();
373-
374-
if !raw_ptrs.is_empty() {
375-
let typeck_results = cx.tcx.typeck_body(body.id());
376-
let mut v = DerefVisitor {
377-
cx,
378-
ptrs: raw_ptrs,
379-
typeck_results,
380-
};
381-
382-
intravisit::walk_expr(&mut v, expr);
383-
}
384-
}
385-
}
386-
}
387-
388349
fn check_result_unit_err(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, item_span: Span, fn_header_span: Span) {
389350
if_chain! {
390351
if !in_external_macro(cx.sess(), item_span);
@@ -524,71 +485,6 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &m
524485
}
525486
}
526487

527-
fn raw_ptr_arg(arg: &hir::Param<'_>, ty: &hir::Ty<'_>) -> Option<hir::HirId> {
528-
if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyKind::Ptr(_)) = (&arg.pat.kind, &ty.kind) {
529-
Some(id)
530-
} else {
531-
None
532-
}
533-
}
534-
535-
struct DerefVisitor<'a, 'tcx> {
536-
cx: &'a LateContext<'tcx>,
537-
ptrs: FxHashSet<hir::HirId>,
538-
typeck_results: &'a ty::TypeckResults<'tcx>,
539-
}
540-
541-
impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
542-
type Map = Map<'tcx>;
543-
544-
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
545-
match expr.kind {
546-
hir::ExprKind::Call(ref f, args) => {
547-
let ty = self.typeck_results.expr_ty(f);
548-
549-
if type_is_unsafe_function(self.cx, ty) {
550-
for arg in args {
551-
self.check_arg(arg);
552-
}
553-
}
554-
},
555-
hir::ExprKind::MethodCall(_, _, args, _) => {
556-
let def_id = self.typeck_results.type_dependent_def_id(expr.hir_id).unwrap();
557-
let base_type = self.cx.tcx.type_of(def_id);
558-
559-
if type_is_unsafe_function(self.cx, base_type) {
560-
for arg in args {
561-
self.check_arg(arg);
562-
}
563-
}
564-
},
565-
hir::ExprKind::Unary(hir::UnOp::Deref, ref ptr) => self.check_arg(ptr),
566-
_ => (),
567-
}
568-
569-
intravisit::walk_expr(self, expr);
570-
}
571-
572-
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
573-
intravisit::NestedVisitorMap::None
574-
}
575-
}
576-
577-
impl<'a, 'tcx> DerefVisitor<'a, 'tcx> {
578-
fn check_arg(&self, ptr: &hir::Expr<'_>) {
579-
if let Some(id) = path_to_local(ptr) {
580-
if self.ptrs.contains(&id) {
581-
span_lint(
582-
self.cx,
583-
NOT_UNSAFE_PTR_ARG_DEREF,
584-
ptr.span,
585-
"this public function dereferences a raw pointer but is not marked `unsafe`",
586-
);
587-
}
588-
}
589-
}
590-
}
591-
592488
struct StaticMutVisitor<'a, 'tcx> {
593489
cx: &'a LateContext<'tcx>,
594490
mutates_static: bool,
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
use rustc_data_structures::fx::FxHashSet;
2+
use rustc_hir::{self as hir, intravisit};
3+
use rustc_lint::LateContext;
4+
use rustc_middle::{hir::map::Map, ty};
5+
6+
use clippy_utils::diagnostics::span_lint;
7+
use clippy_utils::ty::type_is_unsafe_function;
8+
use clippy_utils::{iter_input_pats, path_to_local};
9+
10+
use super::NOT_UNSAFE_PTR_ARG_DEREF;
11+
12+
pub(super) fn check_fn(
13+
cx: &LateContext<'tcx>,
14+
kind: intravisit::FnKind<'tcx>,
15+
decl: &'tcx hir::FnDecl<'tcx>,
16+
body: &'tcx hir::Body<'tcx>,
17+
hir_id: hir::HirId,
18+
) {
19+
let unsafety = match kind {
20+
intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _) => unsafety,
21+
intravisit::FnKind::Method(_, sig, _) => sig.header.unsafety,
22+
intravisit::FnKind::Closure => return,
23+
};
24+
25+
check_raw_ptr(cx, unsafety, decl, body, hir_id);
26+
}
27+
28+
pub(super) fn check_trait_item(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
29+
if let hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(eid)) = item.kind {
30+
let body = cx.tcx.hir().body(eid);
31+
check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.hir_id());
32+
}
33+
}
34+
35+
fn check_raw_ptr(
36+
cx: &LateContext<'tcx>,
37+
unsafety: hir::Unsafety,
38+
decl: &'tcx hir::FnDecl<'tcx>,
39+
body: &'tcx hir::Body<'tcx>,
40+
hir_id: hir::HirId,
41+
) {
42+
let expr = &body.value;
43+
if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(hir_id) {
44+
let raw_ptrs = iter_input_pats(decl, body)
45+
.zip(decl.inputs.iter())
46+
.filter_map(|(arg, ty)| raw_ptr_arg(arg, ty))
47+
.collect::<FxHashSet<_>>();
48+
49+
if !raw_ptrs.is_empty() {
50+
let typeck_results = cx.tcx.typeck_body(body.id());
51+
let mut v = DerefVisitor {
52+
cx,
53+
ptrs: raw_ptrs,
54+
typeck_results,
55+
};
56+
57+
intravisit::walk_expr(&mut v, expr);
58+
}
59+
}
60+
}
61+
62+
fn raw_ptr_arg(arg: &hir::Param<'_>, ty: &hir::Ty<'_>) -> Option<hir::HirId> {
63+
if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyKind::Ptr(_)) = (&arg.pat.kind, &ty.kind) {
64+
Some(id)
65+
} else {
66+
None
67+
}
68+
}
69+
70+
struct DerefVisitor<'a, 'tcx> {
71+
cx: &'a LateContext<'tcx>,
72+
ptrs: FxHashSet<hir::HirId>,
73+
typeck_results: &'a ty::TypeckResults<'tcx>,
74+
}
75+
76+
impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
77+
type Map = Map<'tcx>;
78+
79+
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
80+
match expr.kind {
81+
hir::ExprKind::Call(ref f, args) => {
82+
let ty = self.typeck_results.expr_ty(f);
83+
84+
if type_is_unsafe_function(self.cx, ty) {
85+
for arg in args {
86+
self.check_arg(arg);
87+
}
88+
}
89+
},
90+
hir::ExprKind::MethodCall(_, _, args, _) => {
91+
let def_id = self.typeck_results.type_dependent_def_id(expr.hir_id).unwrap();
92+
let base_type = self.cx.tcx.type_of(def_id);
93+
94+
if type_is_unsafe_function(self.cx, base_type) {
95+
for arg in args {
96+
self.check_arg(arg);
97+
}
98+
}
99+
},
100+
hir::ExprKind::Unary(hir::UnOp::Deref, ref ptr) => self.check_arg(ptr),
101+
_ => (),
102+
}
103+
104+
intravisit::walk_expr(self, expr);
105+
}
106+
107+
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
108+
intravisit::NestedVisitorMap::None
109+
}
110+
}
111+
112+
impl<'a, 'tcx> DerefVisitor<'a, 'tcx> {
113+
fn check_arg(&self, ptr: &hir::Expr<'_>) {
114+
if let Some(id) = path_to_local(ptr) {
115+
if self.ptrs.contains(&id) {
116+
span_lint(
117+
self.cx,
118+
NOT_UNSAFE_PTR_ARG_DEREF,
119+
ptr.span,
120+
"this public function dereferences a raw pointer but is not marked `unsafe`",
121+
);
122+
}
123+
}
124+
}
125+
}

0 commit comments

Comments
 (0)