11//! Check properties that are required by built-in traits and set 
22//! up data structures required by type-checking/codegen. 
33
4- use  crate :: errors:: { CopyImplOnNonAdt ,  CopyImplOnTypeWithDtor ,  DropImplOnWrongItem } ; 
4+ use  crate :: errors:: { 
5+     ConstParamTyImplOnNonAdt ,  CopyImplOnNonAdt ,  CopyImplOnTypeWithDtor ,  DropImplOnWrongItem , 
6+ } ; 
57use  rustc_data_structures:: fx:: FxHashSet ; 
6- use  rustc_errors:: { struct_span_err,  MultiSpan } ; 
8+ use  rustc_errors:: { struct_span_err,  ErrorGuaranteed ,   MultiSpan } ; 
79use  rustc_hir as  hir; 
810use  rustc_hir:: def_id:: { DefId ,  LocalDefId } ; 
911use  rustc_hir:: lang_items:: LangItem ; 
@@ -14,9 +16,11 @@ use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt};
1416use  rustc_infer:: traits:: Obligation ; 
1517use  rustc_middle:: ty:: adjustment:: CoerceUnsizedInfo ; 
1618use  rustc_middle:: ty:: { self ,  suggest_constraining_type_params,  Ty ,  TyCtxt ,  TypeVisitableExt } ; 
19+ use  rustc_span:: Span ; 
1720use  rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt ; 
1821use  rustc_trait_selection:: traits:: misc:: { 
19-     type_allowed_to_implement_copy,  CopyImplementationError ,  InfringingFieldsReason , 
22+     type_allowed_to_implement_const_param_ty,  type_allowed_to_implement_copy, 
23+     ConstParamTyImplementationError ,  CopyImplementationError ,  InfringingFieldsReason , 
2024} ; 
2125use  rustc_trait_selection:: traits:: ObligationCtxt ; 
2226use  rustc_trait_selection:: traits:: { self ,  ObligationCause } ; 
@@ -27,6 +31,7 @@ pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
2731    Checker  {  tcx,  trait_def_id } 
2832        . check ( lang_items. drop_trait ( ) ,  visit_implementation_of_drop) 
2933        . check ( lang_items. copy_trait ( ) ,  visit_implementation_of_copy) 
34+         . check ( lang_items. const_param_ty_trait ( ) ,  visit_implementation_of_const_param_ty) 
3035        . check ( lang_items. coerce_unsized_trait ( ) ,  visit_implementation_of_coerce_unsized) 
3136        . check ( lang_items. dispatch_from_dyn_trait ( ) ,  visit_implementation_of_dispatch_from_dyn) ; 
3237} 
@@ -83,110 +88,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
8388    match  type_allowed_to_implement_copy ( tcx,  param_env,  self_type,  cause)  { 
8489        Ok ( ( ) )  => { } 
8590        Err ( CopyImplementationError :: InfringingFields ( fields) )  => { 
86-             let  mut  err = struct_span_err ! ( 
87-                 tcx. sess, 
88-                 span, 
89-                 E0204 , 
90-                 "the trait `Copy` cannot be implemented for this type" 
91-             ) ; 
92- 
93-             // We'll try to suggest constraining type parameters to fulfill the requirements of 
94-             // their `Copy` implementation. 
95-             let  mut  errors:  BTreeMap < _ ,  Vec < _ > >  = Default :: default ( ) ; 
96-             let  mut  bounds = vec ! [ ] ; 
97- 
98-             let  mut  seen_tys = FxHashSet :: default ( ) ; 
99- 
100-             for  ( field,  ty,  reason)  in  fields { 
101-                 // Only report an error once per type. 
102-                 if  !seen_tys. insert ( ty)  { 
103-                     continue ; 
104-                 } 
105- 
106-                 let  field_span = tcx. def_span ( field. did ) ; 
107-                 err. span_label ( field_span,  "this field does not implement `Copy`" ) ; 
108- 
109-                 match  reason { 
110-                     InfringingFieldsReason :: Fulfill ( fulfillment_errors)  => { 
111-                         for  error in  fulfillment_errors { 
112-                             let  error_predicate = error. obligation . predicate ; 
113-                             // Only note if it's not the root obligation, otherwise it's trivial and 
114-                             // should be self-explanatory (i.e. a field literally doesn't implement Copy). 
115- 
116-                             // FIXME: This error could be more descriptive, especially if the error_predicate 
117-                             // contains a foreign type or if it's a deeply nested type... 
118-                             if  error_predicate != error. root_obligation . predicate  { 
119-                                 errors
120-                                     . entry ( ( ty. to_string ( ) ,  error_predicate. to_string ( ) ) ) 
121-                                     . or_default ( ) 
122-                                     . push ( error. obligation . cause . span ) ; 
123-                             } 
124-                             if  let  ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( 
125-                                 ty:: TraitPredicate  { 
126-                                     trait_ref, 
127-                                     polarity :  ty:: ImplPolarity :: Positive , 
128-                                     ..
129-                                 } , 
130-                             ) )  = error_predicate. kind ( ) . skip_binder ( ) 
131-                             { 
132-                                 let  ty = trait_ref. self_ty ( ) ; 
133-                                 if  let  ty:: Param ( _)  = ty. kind ( )  { 
134-                                     bounds. push ( ( 
135-                                         format ! ( "{ty}" ) , 
136-                                         trait_ref. print_only_trait_path ( ) . to_string ( ) , 
137-                                         Some ( trait_ref. def_id ) , 
138-                                     ) ) ; 
139-                                 } 
140-                             } 
141-                         } 
142-                     } 
143-                     InfringingFieldsReason :: Regions ( region_errors)  => { 
144-                         for  error in  region_errors { 
145-                             let  ty = ty. to_string ( ) ; 
146-                             match  error { 
147-                                 RegionResolutionError :: ConcreteFailure ( origin,  a,  b)  => { 
148-                                     let  predicate = format ! ( "{b}: {a}" ) ; 
149-                                     errors
150-                                         . entry ( ( ty. clone ( ) ,  predicate. clone ( ) ) ) 
151-                                         . or_default ( ) 
152-                                         . push ( origin. span ( ) ) ; 
153-                                     if  let  ty:: RegionKind :: ReEarlyBound ( ebr)  = * b && ebr. has_name ( )  { 
154-                                         bounds. push ( ( b. to_string ( ) ,  a. to_string ( ) ,  None ) ) ; 
155-                                     } 
156-                                 } 
157-                                 RegionResolutionError :: GenericBoundFailure ( origin,  a,  b)  => { 
158-                                     let  predicate = format ! ( "{a}: {b}" ) ; 
159-                                     errors
160-                                         . entry ( ( ty. clone ( ) ,  predicate. clone ( ) ) ) 
161-                                         . or_default ( ) 
162-                                         . push ( origin. span ( ) ) ; 
163-                                     if  let  infer:: region_constraints:: GenericKind :: Param ( _)  = a { 
164-                                         bounds. push ( ( a. to_string ( ) ,  b. to_string ( ) ,  None ) ) ; 
165-                                     } 
166-                                 } 
167-                                 _ => continue , 
168-                             } 
169-                         } 
170-                     } 
171-                 } 
172-             } 
173-             for  ( ( ty,  error_predicate) ,  spans)  in  errors { 
174-                 let  span:  MultiSpan  = spans. into ( ) ; 
175-                 err. span_note ( 
176-                     span, 
177-                     & format ! ( "the `Copy` impl for `{}` requires that `{}`" ,  ty,  error_predicate) , 
178-                 ) ; 
179-             } 
180-             suggest_constraining_type_params ( 
181-                 tcx, 
182-                 tcx. hir ( ) . get_generics ( impl_did) . expect ( "impls always have generics" ) , 
183-                 & mut  err, 
184-                 bounds. iter ( ) . map ( |( param,  constraint,  def_id) | { 
185-                     ( param. as_str ( ) ,  constraint. as_str ( ) ,  * def_id) 
186-                 } ) , 
187-                 None , 
188-             ) ; 
189-             err. emit ( ) ; 
91+             infringing_fields_error ( tcx,  fields,  LangItem :: Copy ,  impl_did,  span) ; 
19092        } 
19193        Err ( CopyImplementationError :: NotAnAdt )  => { 
19294            tcx. sess . emit_err ( CopyImplOnNonAdt  {  span } ) ; 
@@ -197,6 +99,29 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
19799    } 
198100} 
199101
102+ fn  visit_implementation_of_const_param_ty ( tcx :  TyCtxt < ' _ > ,  impl_did :  LocalDefId )  { 
103+     let  self_type = tcx. type_of ( impl_did) . subst_identity ( ) ; 
104+     assert ! ( !self_type. has_escaping_bound_vars( ) ) ; 
105+ 
106+     let  param_env = tcx. param_env ( impl_did) ; 
107+ 
108+     let  span = match  tcx. hir ( ) . expect_item ( impl_did) . expect_impl ( )  { 
109+         hir:: Impl  {  polarity :  hir:: ImplPolarity :: Negative ( _) ,  .. }  => return , 
110+         impl_ => impl_. self_ty . span , 
111+     } ; 
112+ 
113+     let  cause = traits:: ObligationCause :: misc ( span,  impl_did) ; 
114+     match  type_allowed_to_implement_const_param_ty ( tcx,  param_env,  self_type,  cause)  { 
115+         Ok ( ( ) )  => { } 
116+         Err ( ConstParamTyImplementationError :: InfrigingFields ( fields) )  => { 
117+             infringing_fields_error ( tcx,  fields,  LangItem :: ConstParamTy ,  impl_did,  span) ; 
118+         } 
119+         Err ( ConstParamTyImplementationError :: NotAnAdtOrBuiltinAllowed )  => { 
120+             tcx. sess . emit_err ( ConstParamTyImplOnNonAdt  {  span } ) ; 
121+         } 
122+     } 
123+ } 
124+ 
200125fn  visit_implementation_of_coerce_unsized ( tcx :  TyCtxt < ' _ > ,  impl_did :  LocalDefId )  { 
201126    debug ! ( "visit_implementation_of_coerce_unsized: impl_did={:?}" ,  impl_did) ; 
202127
@@ -593,3 +518,119 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
593518
594519    CoerceUnsizedInfo  {  custom_kind :  kind } 
595520} 
521+ 
522+ fn  infringing_fields_error ( 
523+     tcx :  TyCtxt < ' _ > , 
524+     fields :  Vec < ( & ty:: FieldDef ,  Ty < ' _ > ,  InfringingFieldsReason < ' _ > ) > , 
525+     lang_item :  LangItem , 
526+     impl_did :  LocalDefId , 
527+     impl_span :  Span , 
528+ )  -> ErrorGuaranteed  { 
529+     let  trait_did = tcx. require_lang_item ( lang_item,  Some ( impl_span) ) ; 
530+ 
531+     let  trait_name = tcx. def_path_str ( trait_did) ; 
532+ 
533+     let  mut  err = struct_span_err ! ( 
534+         tcx. sess, 
535+         impl_span, 
536+         E0204 , 
537+         "the trait `{trait_name}` cannot be implemented for this type" 
538+     ) ; 
539+ 
540+     // We'll try to suggest constraining type parameters to fulfill the requirements of 
541+     // their `Copy` implementation. 
542+     let  mut  errors:  BTreeMap < _ ,  Vec < _ > >  = Default :: default ( ) ; 
543+     let  mut  bounds = vec ! [ ] ; 
544+ 
545+     let  mut  seen_tys = FxHashSet :: default ( ) ; 
546+ 
547+     for  ( field,  ty,  reason)  in  fields { 
548+         // Only report an error once per type. 
549+         if  !seen_tys. insert ( ty)  { 
550+             continue ; 
551+         } 
552+ 
553+         let  field_span = tcx. def_span ( field. did ) ; 
554+         err. span_label ( field_span,  format ! ( "this field does not implement `{trait_name}`" ) ) ; 
555+ 
556+         match  reason { 
557+             InfringingFieldsReason :: Fulfill ( fulfillment_errors)  => { 
558+                 for  error in  fulfillment_errors { 
559+                     let  error_predicate = error. obligation . predicate ; 
560+                     // Only note if it's not the root obligation, otherwise it's trivial and 
561+                     // should be self-explanatory (i.e. a field literally doesn't implement Copy). 
562+ 
563+                     // FIXME: This error could be more descriptive, especially if the error_predicate 
564+                     // contains a foreign type or if it's a deeply nested type... 
565+                     if  error_predicate != error. root_obligation . predicate  { 
566+                         errors
567+                             . entry ( ( ty. to_string ( ) ,  error_predicate. to_string ( ) ) ) 
568+                             . or_default ( ) 
569+                             . push ( error. obligation . cause . span ) ; 
570+                     } 
571+                     if  let  ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( ty:: TraitPredicate  { 
572+                         trait_ref, 
573+                         polarity :  ty:: ImplPolarity :: Positive , 
574+                         ..
575+                     } ) )  = error_predicate. kind ( ) . skip_binder ( ) 
576+                     { 
577+                         let  ty = trait_ref. self_ty ( ) ; 
578+                         if  let  ty:: Param ( _)  = ty. kind ( )  { 
579+                             bounds. push ( ( 
580+                                 format ! ( "{ty}" ) , 
581+                                 trait_ref. print_only_trait_path ( ) . to_string ( ) , 
582+                                 Some ( trait_ref. def_id ) , 
583+                             ) ) ; 
584+                         } 
585+                     } 
586+                 } 
587+             } 
588+             InfringingFieldsReason :: Regions ( region_errors)  => { 
589+                 for  error in  region_errors { 
590+                     let  ty = ty. to_string ( ) ; 
591+                     match  error { 
592+                         RegionResolutionError :: ConcreteFailure ( origin,  a,  b)  => { 
593+                             let  predicate = format ! ( "{b}: {a}" ) ; 
594+                             errors
595+                                 . entry ( ( ty. clone ( ) ,  predicate. clone ( ) ) ) 
596+                                 . or_default ( ) 
597+                                 . push ( origin. span ( ) ) ; 
598+                             if  let  ty:: RegionKind :: ReEarlyBound ( ebr)  = * b && ebr. has_name ( )  { 
599+                                         bounds. push ( ( b. to_string ( ) ,  a. to_string ( ) ,  None ) ) ; 
600+                                     } 
601+                         } 
602+                         RegionResolutionError :: GenericBoundFailure ( origin,  a,  b)  => { 
603+                             let  predicate = format ! ( "{a}: {b}" ) ; 
604+                             errors
605+                                 . entry ( ( ty. clone ( ) ,  predicate. clone ( ) ) ) 
606+                                 . or_default ( ) 
607+                                 . push ( origin. span ( ) ) ; 
608+                             if  let  infer:: region_constraints:: GenericKind :: Param ( _)  = a { 
609+                                 bounds. push ( ( a. to_string ( ) ,  b. to_string ( ) ,  None ) ) ; 
610+                             } 
611+                         } 
612+                         _ => continue , 
613+                     } 
614+                 } 
615+             } 
616+         } 
617+     } 
618+     for  ( ( ty,  error_predicate) ,  spans)  in  errors { 
619+         let  span:  MultiSpan  = spans. into ( ) ; 
620+         err. span_note ( 
621+             span, 
622+             format ! ( "the `{trait_name}` impl for `{ty}` requires that `{error_predicate}`" ) , 
623+         ) ; 
624+     } 
625+     suggest_constraining_type_params ( 
626+         tcx, 
627+         tcx. hir ( ) . get_generics ( impl_did) . expect ( "impls always have generics" ) , 
628+         & mut  err, 
629+         bounds
630+             . iter ( ) 
631+             . map ( |( param,  constraint,  def_id) | ( param. as_str ( ) ,  constraint. as_str ( ) ,  * def_id) ) , 
632+         None , 
633+     ) ; 
634+ 
635+     err. emit ( ) 
636+ } 
0 commit comments