[inherent_to_string]: Don't lint unsafe or extern fns

This commit is contained in:
Catherine Flores 2023-07-21 06:45:30 -05:00
parent 7c5095c502
commit f3f7f63c16
3 changed files with 44 additions and 27 deletions

View file

@ -1,11 +1,11 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::{implements_trait, is_type_lang_item};
use clippy_utils::{return_ty, trait_ref_of_method};
use if_chain::if_chain;
use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind, LangItem};
use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind, LangItem, Unsafety};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
use rustc_target::spec::abi::Abi;
declare_clippy_lint! {
/// ### What it does
@ -95,24 +95,23 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString {
return;
}
if_chain! {
// Check if item is a method, called to_string and has a parameter 'self'
if let ImplItemKind::Fn(ref signature, _) = impl_item.kind;
if impl_item.ident.name == sym::to_string;
let decl = &signature.decl;
if decl.implicit_self.has_implicit_self();
if decl.inputs.len() == 1;
if impl_item.generics.params.iter().all(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }));
// Check if item is a method called `to_string` and has a parameter 'self'
if let ImplItemKind::Fn(ref signature, _) = impl_item.kind
// #11201
&& let header = signature.header
&& header.unsafety == Unsafety::Normal
&& header.abi == Abi::Rust
&& impl_item.ident.name == sym::to_string
&& let decl = signature.decl
&& decl.implicit_self.has_implicit_self()
&& decl.inputs.len() == 1
&& impl_item.generics.params.iter().all(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
// Check if return type is String
if is_type_lang_item(cx, return_ty(cx, impl_item.owner_id), LangItem::String);
&& is_type_lang_item(cx, return_ty(cx, impl_item.owner_id), LangItem::String)
// Filters instances of to_string which are required by a trait
if trait_ref_of_method(cx, impl_item.owner_id.def_id).is_none();
then {
show_lint(cx, impl_item);
}
&& trait_ref_of_method(cx, impl_item.owner_id.def_id).is_none()
{
show_lint(cx, impl_item);
}
}
}

View file

@ -1,5 +1,4 @@
#![warn(clippy::inherent_to_string)]
#![deny(clippy::inherent_to_string_shadow_display)]
#![allow(improper_ctypes_definitions)]
use std::fmt;
@ -14,6 +13,9 @@ struct D;
struct E;
struct F;
struct G;
struct H;
struct I;
struct J;
impl A {
// Should be detected; emit warning
@ -80,6 +82,26 @@ impl G {
}
}
// Issue #11201
impl H {
unsafe fn to_string(&self) -> String {
"G.to_string()".to_string()
}
}
impl I {
extern "C" fn to_string(&self) -> String {
"G.to_string()".to_string()
}
}
impl J {
unsafe extern "C" fn to_string(&self) -> String {
"G.to_string()".to_string()
}
}
fn main() {
let a = A;
a.to_string();

View file

@ -1,5 +1,5 @@
error: implementation of inherent method `to_string(&self) -> String` for type `A`
--> $DIR/inherent_to_string.rs:20:5
--> $DIR/inherent_to_string.rs:22:5
|
LL | / fn to_string(&self) -> String {
LL | | "A.to_string()".to_string()
@ -10,7 +10,7 @@ LL | | }
= note: `-D clippy::inherent-to-string` implied by `-D warnings`
error: type `C` implements inherent method `to_string(&self) -> String` which shadows the implementation of `Display`
--> $DIR/inherent_to_string.rs:44:5
--> $DIR/inherent_to_string.rs:46:5
|
LL | / fn to_string(&self) -> String {
LL | | "C.to_string()".to_string()
@ -18,11 +18,7 @@ LL | | }
| |_____^
|
= help: remove the inherent method from type `C`
note: the lint level is defined here
--> $DIR/inherent_to_string.rs:2:9
|
LL | #![deny(clippy::inherent_to_string_shadow_display)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: `#[deny(clippy::inherent_to_string_shadow_display)]` on by default
error: aborting due to 2 previous errors