1
- use clippy_utils:: { diagnostics:: span_lint_and_sugg, get_parent_node, last_path_segment, ty:: implements_trait} ;
1
+ use clippy_utils:: {
2
+ diagnostics:: span_lint_and_sugg,
3
+ get_parent_node, last_path_segment,
4
+ ty:: { implements_trait, is_type_lang_item} ,
5
+ } ;
2
6
use rustc_errors:: Applicability ;
3
- use rustc_hir:: { ExprKind , ImplItem , ImplItemKind , ItemKind , Node , UnOp } ;
7
+ use rustc_hir:: { ExprKind , ImplItem , ImplItemKind , ItemKind , LangItem , Node , UnOp } ;
4
8
use rustc_hir_analysis:: hir_ty_to_ty;
5
9
use rustc_lint:: { LateContext , LateLintPass } ;
6
- use rustc_middle:: ty:: EarlyBinder ;
10
+ use rustc_middle:: ty:: { self , EarlyBinder } ;
7
11
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
8
12
use rustc_span:: { sym, symbol} ;
9
13
@@ -15,6 +19,14 @@ declare_clippy_lint! {
15
19
/// If both `Clone` and `Copy` are implemented, they must agree. This is done by dereferencing
16
20
/// `self` in `Clone`'s implementation. Anything else is incorrect.
17
21
///
22
+ /// ### Known issues
23
+ /// While anything other than `*self` is *technically* incorrect, it can often be done as an
24
+ /// optimization, like in the case of `MaybeUninit` for example. Returning a new `MaybeUninit`
25
+ /// is both faster and as correct as `memcpy`ing the original. If this is not the case however,
26
+ /// the lint's advice should almost always be applied.
27
+ ///
28
+ /// Note: This lint ignores `Clone` implementations on types that are just `MaybeUninit`.
29
+ ///
18
30
/// ### Example
19
31
/// ```rust,ignore
20
32
/// #[derive(Eq, PartialEq)]
@@ -43,7 +55,7 @@ declare_clippy_lint! {
43
55
/// ```
44
56
#[ clippy:: version = "1.72.0" ]
45
57
pub INCORRECT_CLONE_IMPL_ON_COPY_TYPE ,
46
- correctness ,
58
+ complexity ,
47
59
"manual implementation of `Clone` on a `Copy` type"
48
60
}
49
61
declare_lint_pass ! ( IncorrectImpls => [ INCORRECT_CLONE_IMPL_ON_COPY_TYPE ] ) ;
@@ -84,6 +96,10 @@ impl LateLintPass<'_> for IncorrectImpls {
84
96
copy_def_id,
85
97
trait_impl. substs ,
86
98
)
99
+ && let ty:: Adt ( def, substs) = hir_ty_to_ty ( cx. tcx , imp. self_ty ) . kind ( )
100
+ && def
101
+ . all_fields ( )
102
+ . all ( |field| is_type_lang_item ( cx, field. ty ( cx. tcx , substs) , LangItem :: MaybeUninit ) )
87
103
{
88
104
if impl_item. ident . name == sym:: clone {
89
105
if block. stmts . is_empty ( )
0 commit comments