diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index fc5f1509931..f9a0d611429 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -28,8 +28,9 @@ use crate::utils::paths; use crate::utils::{ clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment, - match_def_path, match_path, match_type, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt, + match_def_path, match_path, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt, snippet_with_applicability, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, + AbsolutePathBuffer }; use if_chain::if_chain; use std::borrow::Cow; @@ -1023,6 +1024,21 @@ fn get_lints(&self) -> LintArray { } } +// Check if the given type is either `core::ffi::c_void` or +// one of the platform specific `libc::::c_void` of libc. +fn is_c_void(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'_>) -> bool { + if let ty::Adt(adt, _) = ty.sty { + let mut apb = AbsolutePathBuffer { names: vec![] }; + tcx.push_item_path(&mut apb, adt.did, false); + + if apb.names.is_empty() { return false } + if apb.names[0] == "libc" || apb.names[0] == "core" && *apb.names.last().unwrap() == "c_void" { + return true + } + } + false +} + impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::Cast(ref ex, _) = expr.node { @@ -1114,10 +1130,7 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let Some(to_align) = cx.layout_of(to_ptr_ty.ty).ok().map(|a| a.align.abi); if from_align < to_align; // with c_void, we inherently need to trust the user - if ! ( - match_type(cx, from_ptr_ty.ty, &paths::C_VOID) - || match_type(cx, from_ptr_ty.ty, &paths::C_VOID_LIBC) - ); + if !is_c_void(cx.tcx, from_ptr_ty.ty); then { span_lint( cx, diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index b9a95f340a7..68357b08d6c 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -29,6 +29,7 @@ use crate::syntax::errors::DiagnosticBuilder; use crate::syntax::source_map::{Span, DUMMY_SP}; use crate::syntax::symbol::{keywords, Symbol}; +use crate::syntax::symbol; use if_chain::if_chain; use matches::matches; use std::borrow::Cow; @@ -74,6 +75,25 @@ pub fn in_macro(span: Span) -> bool { span.ctxt().outer().expn_info().is_some() } +/// Used to store the absolute path to a type. +/// +/// See `match_def_path` for usage. +#[derive(Debug)] +pub struct AbsolutePathBuffer { + pub names: Vec, +} + +impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer { + fn root_mode(&self) -> &ty::item_path::RootMode { + const ABSOLUTE: &ty::item_path::RootMode = &ty::item_path::RootMode::Absolute; + ABSOLUTE + } + + fn push(&mut self, text: &str) { + self.names.push(symbol::Symbol::intern(text).as_str()); + } +} + /// Check if a `DefId`'s path matches the given absolute type path usage. /// /// # Examples @@ -83,24 +103,6 @@ pub fn in_macro(span: Span) -> bool { /// /// See also the `paths` module. pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) -> bool { - use crate::syntax::symbol; - - #[derive(Debug)] - struct AbsolutePathBuffer { - names: Vec, - } - - impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer { - fn root_mode(&self) -> &ty::item_path::RootMode { - const ABSOLUTE: &ty::item_path::RootMode = &ty::item_path::RootMode::Absolute; - ABSOLUTE - } - - fn push(&mut self, text: &str) { - self.names.push(symbol::Symbol::intern(text).as_str()); - } - } - let mut apb = AbsolutePathBuffer { names: vec![] }; tcx.push_item_path(&mut apb, def_id, false); diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 69a2500a1e1..0779d77936f 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -27,8 +27,6 @@ pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"]; pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"]; pub const CSTRING_NEW: [&str; 5] = ["std", "ffi", "c_str", "CString", "new"]; -pub const C_VOID: [&str; 3] = ["core", "ffi", "c_void"]; -pub const C_VOID_LIBC: [&str; 2] = ["libc", "c_void"]; pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"]; pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"]; pub const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];