@@ -7,13 +7,15 @@ 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 ;
16- use rustc_trait_selection:: traits:: misc:: { can_type_implement_copy, CopyImplementationError } ;
16+ use rustc_trait_selection:: traits:: misc:: {
17+ type_allowed_to_implement_copy, CopyImplementationError , InfringingFieldsReason ,
18+ } ;
1719use rustc_trait_selection:: traits:: predicate_for_trait_def;
1820use rustc_trait_selection:: traits:: { self , ObligationCause } ;
1921use std:: collections:: BTreeMap ;
@@ -79,7 +81,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
7981 } ;
8082
8183 let cause = traits:: ObligationCause :: misc ( span, impl_hir_id) ;
82- match can_type_implement_copy ( tcx, param_env, self_type, cause) {
84+ match type_allowed_to_implement_copy ( tcx, param_env, self_type, cause) {
8385 Ok ( ( ) ) => { }
8486 Err ( CopyImplementationError :: InfrigingFields ( fields) ) => {
8587 let mut err = struct_span_err ! (
@@ -94,50 +96,70 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
9496 let mut errors: BTreeMap < _ , Vec < _ > > = Default :: default ( ) ;
9597 let mut bounds = vec ! [ ] ;
9698
97- for ( field, ty) in fields {
99+ for ( field, ty, reason ) in fields {
98100 let field_span = tcx. def_span ( field. did ) ;
99- let field_ty_span = match tcx. hir ( ) . get_if_local ( field. did ) {
100- Some ( hir:: Node :: Field ( field_def) ) => field_def. ty . span ,
101- _ => field_span,
102- } ;
103101 err. span_label ( field_span, "this field does not implement `Copy`" ) ;
104- // Spin up a new FulfillmentContext, so we can get the _precise_ reason
105- // why this field does not implement Copy. This is useful because sometimes
106- // it is not immediately clear why Copy is not implemented for a field, since
107- // all we point at is the field itself.
108- let infcx = tcx. infer_ctxt ( ) . ignoring_regions ( ) . build ( ) ;
109- for error in traits:: fully_solve_bound (
110- & infcx,
111- traits:: ObligationCause :: dummy_with_span ( field_ty_span) ,
112- param_env,
113- ty,
114- tcx. require_lang_item ( LangItem :: Copy , Some ( span) ) ,
115- ) {
116- let error_predicate = error. obligation . predicate ;
117- // Only note if it's not the root obligation, otherwise it's trivial and
118- // should be self-explanatory (i.e. a field literally doesn't implement Copy).
119-
120- // FIXME: This error could be more descriptive, especially if the error_predicate
121- // contains a foreign type or if it's a deeply nested type...
122- if error_predicate != error. root_obligation . predicate {
123- errors
124- . entry ( ( ty. to_string ( ) , error_predicate. to_string ( ) ) )
125- . or_default ( )
126- . push ( error. obligation . cause . span ) ;
102+
103+ match reason {
104+ InfringingFieldsReason :: Fulfill ( fulfillment_errors) => {
105+ for error in fulfillment_errors {
106+ let error_predicate = error. obligation . predicate ;
107+ // Only note if it's not the root obligation, otherwise it's trivial and
108+ // should be self-explanatory (i.e. a field literally doesn't implement Copy).
109+
110+ // FIXME: This error could be more descriptive, especially if the error_predicate
111+ // contains a foreign type or if it's a deeply nested type...
112+ if error_predicate != error. root_obligation . predicate {
113+ errors
114+ . entry ( ( ty. to_string ( ) , error_predicate. to_string ( ) ) )
115+ . or_default ( )
116+ . push ( error. obligation . cause . span ) ;
117+ }
118+ if let ty:: PredicateKind :: Clause ( ty:: Clause :: Trait (
119+ ty:: TraitPredicate {
120+ trait_ref,
121+ polarity : ty:: ImplPolarity :: Positive ,
122+ ..
123+ } ,
124+ ) ) = error_predicate. kind ( ) . skip_binder ( )
125+ {
126+ let ty = trait_ref. self_ty ( ) ;
127+ if let ty:: Param ( _) = ty. kind ( ) {
128+ bounds. push ( (
129+ format ! ( "{ty}" ) ,
130+ trait_ref. print_only_trait_path ( ) . to_string ( ) ,
131+ Some ( trait_ref. def_id ) ,
132+ ) ) ;
133+ }
134+ }
135+ }
127136 }
128- if let ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( ty:: TraitPredicate {
129- trait_ref,
130- polarity : ty:: ImplPolarity :: Positive ,
131- ..
132- } ) ) = error_predicate. kind ( ) . skip_binder ( )
133- {
134- let ty = trait_ref. self_ty ( ) ;
135- if let ty:: Param ( _) = ty. kind ( ) {
136- bounds. push ( (
137- format ! ( "{ty}" ) ,
138- trait_ref. print_only_trait_path ( ) . to_string ( ) ,
139- Some ( trait_ref. def_id ) ,
140- ) ) ;
137+ InfringingFieldsReason :: Regions ( region_errors) => {
138+ for error in region_errors {
139+ let ty = ty. to_string ( ) ;
140+ match error {
141+ RegionResolutionError :: ConcreteFailure ( origin, a, b) => {
142+ let predicate = format ! ( "{b}: {a}" ) ;
143+ errors
144+ . entry ( ( ty. clone ( ) , predicate. clone ( ) ) )
145+ . or_default ( )
146+ . push ( origin. span ( ) ) ;
147+ if let ty:: RegionKind :: ReEarlyBound ( ebr) = * b && ebr. has_name ( ) {
148+ bounds. push ( ( b. to_string ( ) , a. to_string ( ) , None ) ) ;
149+ }
150+ }
151+ RegionResolutionError :: GenericBoundFailure ( origin, a, b) => {
152+ let predicate = format ! ( "{a}: {b}" ) ;
153+ errors
154+ . entry ( ( ty. clone ( ) , predicate. clone ( ) ) )
155+ . or_default ( )
156+ . push ( origin. span ( ) ) ;
157+ if let infer:: region_constraints:: GenericKind :: Param ( _) = a {
158+ bounds. push ( ( a. to_string ( ) , b. to_string ( ) , None ) ) ;
159+ }
160+ }
161+ _ => continue ,
162+ }
141163 }
142164 }
143165 }
0 commit comments