Skip to content

Commit d90cad2

Browse files
committed
Fix c_void false positive caused by libc refactoring
The path of `libc::c_void` has changes in rust-lang/libc@5c1a6b8 The DefId path is now always platform specific like `libc::windows::c_void`. This fixes our c_void detection to only check the first and last elements.
1 parent f13d23d commit d90cad2

File tree

3 files changed

+38
-25
lines changed

3 files changed

+38
-25
lines changed

Diff for: clippy_lints/src/types.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ use crate::syntax::source_map::Span;
2828
use crate::utils::paths;
2929
use crate::utils::{
3030
clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment,
31-
match_def_path, match_path, match_type, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt,
31+
match_def_path, match_path, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt,
3232
snippet_with_applicability, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext,
33+
AbsolutePathBuffer
3334
};
3435
use if_chain::if_chain;
3536
use std::borrow::Cow;
@@ -1023,6 +1024,21 @@ impl LintPass for CastPass {
10231024
}
10241025
}
10251026

1027+
// Check if the given type is either `core::ffi::c_void` or
1028+
// one of the platform specific `libc::<platform>::c_void` of libc.
1029+
fn is_c_void(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'_>) -> bool {
1030+
if let ty::Adt(adt, _) = ty.sty {
1031+
let mut apb = AbsolutePathBuffer { names: vec![] };
1032+
tcx.push_item_path(&mut apb, adt.did, false);
1033+
1034+
if apb.names.is_empty() { return false }
1035+
if apb.names[0] == "libc" || apb.names[0] == "core" && *apb.names.last().unwrap() == "c_void" {
1036+
return true
1037+
}
1038+
}
1039+
false
1040+
}
1041+
10261042
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass {
10271043
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
10281044
if let ExprKind::Cast(ref ex, _) = expr.node {
@@ -1114,10 +1130,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass {
11141130
if let Some(to_align) = cx.layout_of(to_ptr_ty.ty).ok().map(|a| a.align.abi);
11151131
if from_align < to_align;
11161132
// with c_void, we inherently need to trust the user
1117-
if ! (
1118-
match_type(cx, from_ptr_ty.ty, &paths::C_VOID)
1119-
|| match_type(cx, from_ptr_ty.ty, &paths::C_VOID_LIBC)
1120-
);
1133+
if !is_c_void(cx.tcx, from_ptr_ty.ty);
11211134
then {
11221135
span_lint(
11231136
cx,

Diff for: clippy_lints/src/utils/mod.rs

+20-18
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use crate::syntax::attr;
2929
use crate::syntax::errors::DiagnosticBuilder;
3030
use crate::syntax::source_map::{Span, DUMMY_SP};
3131
use crate::syntax::symbol::{keywords, Symbol};
32+
use crate::syntax::symbol;
3233
use if_chain::if_chain;
3334
use matches::matches;
3435
use std::borrow::Cow;
@@ -74,6 +75,25 @@ pub fn in_macro(span: Span) -> bool {
7475
span.ctxt().outer().expn_info().is_some()
7576
}
7677

78+
/// Used to store the absolute path to a type.
79+
///
80+
/// See `match_def_path` for usage.
81+
#[derive(Debug)]
82+
pub struct AbsolutePathBuffer {
83+
pub names: Vec<symbol::LocalInternedString>,
84+
}
85+
86+
impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
87+
fn root_mode(&self) -> &ty::item_path::RootMode {
88+
const ABSOLUTE: &ty::item_path::RootMode = &ty::item_path::RootMode::Absolute;
89+
ABSOLUTE
90+
}
91+
92+
fn push(&mut self, text: &str) {
93+
self.names.push(symbol::Symbol::intern(text).as_str());
94+
}
95+
}
96+
7797
/// Check if a `DefId`'s path matches the given absolute type path usage.
7898
///
7999
/// # Examples
@@ -83,24 +103,6 @@ pub fn in_macro(span: Span) -> bool {
83103
///
84104
/// See also the `paths` module.
85105
pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) -> bool {
86-
use crate::syntax::symbol;
87-
88-
#[derive(Debug)]
89-
struct AbsolutePathBuffer {
90-
names: Vec<symbol::LocalInternedString>,
91-
}
92-
93-
impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
94-
fn root_mode(&self) -> &ty::item_path::RootMode {
95-
const ABSOLUTE: &ty::item_path::RootMode = &ty::item_path::RootMode::Absolute;
96-
ABSOLUTE
97-
}
98-
99-
fn push(&mut self, text: &str) {
100-
self.names.push(symbol::Symbol::intern(text).as_str());
101-
}
102-
}
103-
104106
let mut apb = AbsolutePathBuffer { names: vec![] };
105107

106108
tcx.push_item_path(&mut apb, def_id, false);

Diff for: clippy_lints/src/utils/paths.rs

-2
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"];
2727
pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"];
2828
pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"];
2929
pub const CSTRING_NEW: [&str; 5] = ["std", "ffi", "c_str", "CString", "new"];
30-
pub const C_VOID: [&str; 3] = ["core", "ffi", "c_void"];
31-
pub const C_VOID_LIBC: [&str; 2] = ["libc", "c_void"];
3230
pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"];
3331
pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"];
3432
pub const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];

0 commit comments

Comments
 (0)