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