@@ -7,14 +7,14 @@ use rustc_hir as hir;
77use rustc_hir:: def_id:: { DefId , LocalDefId } ;
88use rustc_hir:: lang_items:: LangItem ;
99use rustc_hir:: ItemKind ;
10- use rustc_infer:: infer;
1110use rustc_infer:: infer:: outlives:: env:: OutlivesEnvironment ;
1211use rustc_infer:: infer:: TyCtxtInferExt ;
12+ use rustc_infer:: infer:: { self , RegionResolutionError } ;
1313use rustc_middle:: ty:: adjustment:: CoerceUnsizedInfo ;
1414use rustc_middle:: ty:: { self , suggest_constraining_type_params, Ty , TyCtxt , TypeVisitable } ;
1515use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt ;
1616use rustc_trait_selection:: traits:: misc:: {
17- type_allowed_to_implement_copy, CopyImplementationError ,
17+ type_allowed_to_implement_copy, CopyImplementationError , InfringingFieldsReason ,
1818} ;
1919use rustc_trait_selection:: traits:: predicate_for_trait_def;
2020use rustc_trait_selection:: traits:: { self , ObligationCause } ;
@@ -99,50 +99,70 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
9999 let mut errors: BTreeMap < _ , Vec < _ > > = Default :: default ( ) ;
100100 let mut bounds = vec ! [ ] ;
101101
102- for ( field, ty) in fields {
102+ for ( field, ty, reason ) in fields {
103103 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- } ;
108104 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+ }
132139 }
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+ }
146166 }
147167 }
148168 }
0 commit comments