@@ -91,8 +91,40 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
91
91
E0204 ,
92
92
"the trait `Copy` may not be implemented for this type"
93
93
) ;
94
- for span in fields. iter ( ) . map ( |f| tcx. def_span ( f. did ) ) {
95
- err. span_label ( span, "this field does not implement `Copy`" ) ;
94
+ for ( field, ty) in fields {
95
+ let field_span = tcx. def_span ( field. did ) ;
96
+ err. span_label ( field_span, "this field does not implement `Copy`" ) ;
97
+ // Spin up a new FulfillmentContext, so we can get the _precise_ reason
98
+ // why this field does not implement Copy. This is useful because sometimes
99
+ // it is not immediately clear why Copy is not implemented for a field, since
100
+ // all we point at is the field itself.
101
+ tcx. infer_ctxt ( ) . enter ( |infcx| {
102
+ let mut fulfill_cx = traits:: FulfillmentContext :: new_ignoring_regions ( ) ;
103
+ fulfill_cx. register_bound (
104
+ & infcx,
105
+ param_env,
106
+ ty,
107
+ tcx. lang_items ( ) . copy_trait ( ) . unwrap ( ) ,
108
+ traits:: ObligationCause :: dummy_with_span ( field_span) ,
109
+ ) ;
110
+ for error in fulfill_cx. select_all_or_error ( & infcx) {
111
+ let error_predicate = error. obligation . predicate ;
112
+ // Only note if it's not the root obligation, otherwise it's trivial and
113
+ // should be self-explanatory (i.e. a field literally doesn't implement Copy).
114
+
115
+ // FIXME: This error could be more descriptive, especially if the error_predicate
116
+ // contains a foreign type or if it's a deeply nested type...
117
+ if error_predicate != error. root_obligation . predicate {
118
+ err. span_note (
119
+ error. obligation . cause . span ,
120
+ & format ! (
121
+ "the `Copy` impl for `{}` requires that `{}`" ,
122
+ ty, error_predicate
123
+ ) ,
124
+ ) ;
125
+ }
126
+ }
127
+ } ) ;
96
128
}
97
129
err. emit ( ) ;
98
130
}
0 commit comments