@@ -7,14 +7,14 @@ use rustc_hir as hir;
7
7
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
8
8
use rustc_hir:: lang_items:: LangItem ;
9
9
use rustc_hir:: ItemKind ;
10
- use rustc_infer:: infer;
11
10
use rustc_infer:: infer:: outlives:: env:: OutlivesEnvironment ;
12
11
use rustc_infer:: infer:: TyCtxtInferExt ;
12
+ use rustc_infer:: infer:: { self , RegionResolutionError } ;
13
13
use rustc_middle:: ty:: adjustment:: CoerceUnsizedInfo ;
14
14
use rustc_middle:: ty:: { self , suggest_constraining_type_params, Ty , TyCtxt , TypeVisitable } ;
15
15
use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt ;
16
16
use rustc_trait_selection:: traits:: misc:: {
17
- type_allowed_to_implement_copy, CopyImplementationError ,
17
+ type_allowed_to_implement_copy, CopyImplementationError , InfringingFieldsReason ,
18
18
} ;
19
19
use rustc_trait_selection:: traits:: predicate_for_trait_def;
20
20
use rustc_trait_selection:: traits:: { self , ObligationCause } ;
@@ -99,50 +99,70 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
99
99
let mut errors: BTreeMap < _ , Vec < _ > > = Default :: default ( ) ;
100
100
let mut bounds = vec ! [ ] ;
101
101
102
- for ( field, ty) in fields {
102
+ for ( field, ty, reason ) in fields {
103
103
let field_span = tcx. def_span ( field. did ) ;
104
- let field_ty_span = match tcx. hir ( ) . get_if_local ( field. did ) {
105
- Some ( hir:: Node :: Field ( field_def) ) => field_def. ty . span ,
106
- _ => field_span,
107
- } ;
108
104
err. span_label ( field_span, "this field does not implement `Copy`" ) ;
109
- // Spin up a new FulfillmentContext, so we can get the _precise_ reason
110
- // why this field does not implement Copy. This is useful because sometimes
111
- // it is not immediately clear why Copy is not implemented for a field, since
112
- // all we point at is the field itself.
113
- let infcx = tcx. infer_ctxt ( ) . ignoring_regions ( ) . build ( ) ;
114
- for error in traits:: fully_solve_bound (
115
- & infcx,
116
- traits:: ObligationCause :: dummy_with_span ( field_ty_span) ,
117
- param_env,
118
- ty,
119
- tcx. require_lang_item ( LangItem :: Copy , Some ( span) ) ,
120
- ) {
121
- let error_predicate = error. obligation . predicate ;
122
- // Only note if it's not the root obligation, otherwise it's trivial and
123
- // should be self-explanatory (i.e. a field literally doesn't implement Copy).
124
-
125
- // FIXME: This error could be more descriptive, especially if the error_predicate
126
- // contains a foreign type or if it's a deeply nested type...
127
- if error_predicate != error. root_obligation . predicate {
128
- errors
129
- . entry ( ( ty. to_string ( ) , error_predicate. to_string ( ) ) )
130
- . or_default ( )
131
- . push ( error. obligation . cause . span ) ;
105
+
106
+ match reason {
107
+ InfringingFieldsReason :: Fulfill ( fulfillment_errors) => {
108
+ for error in fulfillment_errors {
109
+ let error_predicate = error. obligation . predicate ;
110
+ // Only note if it's not the root obligation, otherwise it's trivial and
111
+ // should be self-explanatory (i.e. a field literally doesn't implement Copy).
112
+
113
+ // FIXME: This error could be more descriptive, especially if the error_predicate
114
+ // contains a foreign type or if it's a deeply nested type...
115
+ if error_predicate != error. root_obligation . predicate {
116
+ errors
117
+ . entry ( ( ty. to_string ( ) , error_predicate. to_string ( ) ) )
118
+ . or_default ( )
119
+ . push ( error. obligation . cause . span ) ;
120
+ }
121
+ if let ty:: PredicateKind :: Clause ( ty:: Clause :: Trait (
122
+ ty:: TraitPredicate {
123
+ trait_ref,
124
+ polarity : ty:: ImplPolarity :: Positive ,
125
+ ..
126
+ } ,
127
+ ) ) = error_predicate. kind ( ) . skip_binder ( )
128
+ {
129
+ let ty = trait_ref. self_ty ( ) ;
130
+ if let ty:: Param ( _) = ty. kind ( ) {
131
+ bounds. push ( (
132
+ format ! ( "{ty}" ) ,
133
+ trait_ref. print_only_trait_path ( ) . to_string ( ) ,
134
+ Some ( trait_ref. def_id ) ,
135
+ ) ) ;
136
+ }
137
+ }
138
+ }
132
139
}
133
- if let ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( ty:: TraitPredicate {
134
- trait_ref,
135
- polarity : ty:: ImplPolarity :: Positive ,
136
- ..
137
- } ) ) = error_predicate. kind ( ) . skip_binder ( )
138
- {
139
- let ty = trait_ref. self_ty ( ) ;
140
- if let ty:: Param ( _) = ty. kind ( ) {
141
- bounds. push ( (
142
- format ! ( "{ty}" ) ,
143
- trait_ref. print_only_trait_path ( ) . to_string ( ) ,
144
- Some ( trait_ref. def_id ) ,
145
- ) ) ;
140
+ InfringingFieldsReason :: Regions ( region_errors) => {
141
+ for error in region_errors {
142
+ let ty = ty. to_string ( ) ;
143
+ match error {
144
+ RegionResolutionError :: ConcreteFailure ( origin, a, b) => {
145
+ let predicate = format ! ( "{b}: {a}" ) ;
146
+ errors
147
+ . entry ( ( ty. clone ( ) , predicate. clone ( ) ) )
148
+ . or_default ( )
149
+ . push ( origin. span ( ) ) ;
150
+ if let ty:: RegionKind :: ReEarlyBound ( ebr) = * b && ebr. has_name ( ) {
151
+ bounds. push ( ( b. to_string ( ) , a. to_string ( ) , None ) ) ;
152
+ }
153
+ }
154
+ RegionResolutionError :: GenericBoundFailure ( origin, a, b) => {
155
+ let predicate = format ! ( "{a}: {b}" ) ;
156
+ errors
157
+ . entry ( ( ty. clone ( ) , predicate. clone ( ) ) )
158
+ . or_default ( )
159
+ . push ( origin. span ( ) ) ;
160
+ if let infer:: region_constraints:: GenericKind :: Param ( _) = a {
161
+ bounds. push ( ( a. to_string ( ) , b. to_string ( ) , None ) ) ;
162
+ }
163
+ }
164
+ _ => continue ,
165
+ }
146
166
}
147
167
}
148
168
}
0 commit comments