@@ -91,8 +91,40 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
9191 E0204 ,
9292 "the trait `Copy` may not be implemented for this type"
9393 ) ;
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+ } ) ;
96128 }
97129 err. emit ( ) ;
98130 }
0 commit comments