33
44use rustc_errors:: codes:: * ;
55use rustc_errors:: struct_span_code_err;
6- use rustc_hir:: Safety ;
6+ use rustc_hir:: { LangItem , Safety } ;
77use rustc_middle:: ty:: ImplPolarity :: * ;
88use rustc_middle:: ty:: print:: PrintTraitRefExt as _;
99use rustc_middle:: ty:: { ImplTraitHeader , TraitDef , TyCtxt } ;
@@ -20,7 +20,19 @@ pub(super) fn check_item(
2020 tcx. generics_of ( def_id) . own_params . iter ( ) . find ( |p| p. pure_wrt_drop ) . map ( |_| "may_dangle" ) ;
2121 let trait_ref = trait_header. trait_ref . instantiate_identity ( ) ;
2222
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 ) {
2436 ( Safety :: Safe , None , Safety :: Unsafe , Positive | Reservation ) => {
2537 let span = tcx. def_span ( def_id) ;
2638 return Err ( struct_span_code_err ! (
@@ -48,12 +60,22 @@ pub(super) fn check_item(
4860 "the trait `{}` requires an `unsafe impl` declaration" ,
4961 trait_ref. print_trait_sugared( )
5062 )
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+ } )
5779 . with_span_suggestion_verbose (
5880 span. shrink_to_lo ( ) ,
5981 "add `unsafe` to this trait implementation" ,
0 commit comments