3
3
4
4
use rustc_errors:: codes:: * ;
5
5
use rustc_errors:: struct_span_code_err;
6
- use rustc_hir:: Safety ;
6
+ use rustc_hir:: { LangItem , Safety } ;
7
7
use rustc_middle:: ty:: ImplPolarity :: * ;
8
8
use rustc_middle:: ty:: print:: PrintTraitRefExt as _;
9
9
use rustc_middle:: ty:: { ImplTraitHeader , TraitDef , TyCtxt } ;
@@ -20,7 +20,19 @@ pub(super) fn check_item(
20
20
tcx. generics_of ( def_id) . own_params . iter ( ) . find ( |p| p. pure_wrt_drop ) . map ( |_| "may_dangle" ) ;
21
21
let trait_ref = trait_header. trait_ref . instantiate_identity ( ) ;
22
22
23
- match ( trait_def. safety , unsafe_attr, trait_header. safety , trait_header. polarity ) {
23
+ let is_copy = tcx. is_lang_item ( trait_def. def_id , LangItem :: Copy ) ;
24
+ let trait_def_safety = if is_copy {
25
+ // If `Self` has unsafe fields, `Copy` is unsafe to implement.
26
+ if trait_header. trait_ref . skip_binder ( ) . self_ty ( ) . has_unsafe_fields ( ) {
27
+ rustc_hir:: Safety :: Unsafe
28
+ } else {
29
+ rustc_hir:: Safety :: Safe
30
+ }
31
+ } else {
32
+ trait_def. safety
33
+ } ;
34
+
35
+ match ( trait_def_safety, unsafe_attr, trait_header. safety , trait_header. polarity ) {
24
36
( Safety :: Safe , None , Safety :: Unsafe , Positive | Reservation ) => {
25
37
let span = tcx. def_span ( def_id) ;
26
38
return Err ( struct_span_code_err ! (
@@ -48,12 +60,22 @@ pub(super) fn check_item(
48
60
"the trait `{}` requires an `unsafe impl` declaration" ,
49
61
trait_ref. print_trait_sugared( )
50
62
)
51
- . with_note ( format ! (
52
- "the trait `{}` enforces invariants that the compiler can't check. \
53
- Review the trait documentation and make sure this implementation \
54
- upholds those invariants before adding the `unsafe` keyword",
55
- trait_ref. print_trait_sugared( )
56
- ) )
63
+ . with_note ( if is_copy {
64
+ format ! (
65
+ "the trait `{}` cannot be safely implemented for `{}` \
66
+ because it has unsafe fields. Review the invariants \
67
+ of those fields before adding an `unsafe impl`",
68
+ trait_ref. print_trait_sugared( ) ,
69
+ trait_ref. self_ty( ) ,
70
+ )
71
+ } else {
72
+ format ! (
73
+ "the trait `{}` enforces invariants that the compiler can't check. \
74
+ Review the trait documentation and make sure this implementation \
75
+ upholds those invariants before adding the `unsafe` keyword",
76
+ trait_ref. print_trait_sugared( )
77
+ )
78
+ } )
57
79
. with_span_suggestion_verbose (
58
80
span. shrink_to_lo ( ) ,
59
81
"add `unsafe` to this trait implementation" ,
0 commit comments