use rustc_hir::{self as hir, intravisit, HirIdSet};
use rustc_lint::LateContext;
-use rustc_middle::{hir::map::Map, ty};
+use rustc_middle::ty;
+use rustc_span::def_id::LocalDefId;
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::type_is_unsafe_function;
use super::NOT_UNSAFE_PTR_ARG_DEREF;
-pub(super) fn check_fn(
+pub(super) fn check_fn<'tcx>(
cx: &LateContext<'tcx>,
kind: intravisit::FnKind<'tcx>,
decl: &'tcx hir::FnDecl<'tcx>,
hir_id: hir::HirId,
) {
let unsafety = match kind {
- intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _) => unsafety,
- intravisit::FnKind::Method(_, sig, _) => sig.header.unsafety,
+ intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }) => unsafety,
+ intravisit::FnKind::Method(_, sig) => sig.header.unsafety,
intravisit::FnKind::Closure => return,
};
- check_raw_ptr(cx, unsafety, decl, body, hir_id);
+ check_raw_ptr(cx, unsafety, decl, body, cx.tcx.hir().local_def_id(hir_id));
}
-pub(super) fn check_trait_item(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
+pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
if let hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(eid)) = item.kind {
let body = cx.tcx.hir().body(eid);
- check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.hir_id());
+ check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.def_id);
}
}
-fn check_raw_ptr(
+fn check_raw_ptr<'tcx>(
cx: &LateContext<'tcx>,
unsafety: hir::Unsafety,
decl: &'tcx hir::FnDecl<'tcx>,
body: &'tcx hir::Body<'tcx>,
- hir_id: hir::HirId,
+ def_id: LocalDefId,
) {
let expr = &body.value;
- if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(hir_id) {
+ if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(def_id) {
let raw_ptrs = iter_input_pats(decl, body)
- .zip(decl.inputs.iter())
- .filter_map(|(arg, ty)| raw_ptr_arg(arg, ty))
+ .filter_map(|arg| raw_ptr_arg(cx, arg))
.collect::<HirIdSet>();
if !raw_ptrs.is_empty() {
}
}
-fn raw_ptr_arg(arg: &hir::Param<'_>, ty: &hir::Ty<'_>) -> Option<hir::HirId> {
- if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyKind::Ptr(_)) = (&arg.pat.kind, &ty.kind) {
+fn raw_ptr_arg(cx: &LateContext<'_>, arg: &hir::Param<'_>) -> Option<hir::HirId> {
+ if let (&hir::PatKind::Binding(_, id, _, _), Some(&ty::RawPtr(_))) = (
+ &arg.pat.kind,
+ cx.maybe_typeck_results()
+ .map(|typeck_results| typeck_results.pat_ty(arg.pat).kind()),
+ ) {
Some(id)
} else {
None
}
impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
- type Map = Map<'tcx>;
-
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
match expr.kind {
hir::ExprKind::Call(f, args) => {
}
}
},
- hir::ExprKind::MethodCall(_, _, args, _) => {
+ hir::ExprKind::MethodCall(_, receiver, args, _) => {
let def_id = self.typeck_results.type_dependent_def_id(expr.hir_id).unwrap();
let base_type = self.cx.tcx.type_of(def_id);
if type_is_unsafe_function(self.cx, base_type) {
+ self.check_arg(receiver);
for arg in args {
self.check_arg(arg);
}
intravisit::walk_expr(self, expr);
}
-
- fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
- intravisit::NestedVisitorMap::None
- }
}
impl<'a, 'tcx> DerefVisitor<'a, 'tcx> {
self.cx,
NOT_UNSAFE_PTR_ARG_DEREF,
ptr.span,
- "this public function dereferences a raw pointer but is not marked `unsafe`",
+ "this public function might dereference a raw pointer but is not marked `unsafe`",
);
}
}