1
1
//! Check properties that are required by built-in traits and set
2
2
//! up data structures required by type-checking/codegen.
3
3
4
- use crate :: errors:: { CopyImplOnNonAdt , CopyImplOnTypeWithDtor , DropImplOnWrongItem } ;
4
+ use crate :: errors:: {
5
+ ConstParamTyImplOnNonAdt , CopyImplOnNonAdt , CopyImplOnTypeWithDtor , DropImplOnWrongItem ,
6
+ } ;
5
7
use rustc_data_structures:: fx:: FxHashSet ;
6
- use rustc_errors:: { struct_span_err, MultiSpan } ;
8
+ use rustc_errors:: { struct_span_err, ErrorGuaranteed , MultiSpan } ;
7
9
use rustc_hir as hir;
8
10
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
9
11
use rustc_hir:: lang_items:: LangItem ;
@@ -14,9 +16,11 @@ use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt};
14
16
use rustc_infer:: traits:: Obligation ;
15
17
use rustc_middle:: ty:: adjustment:: CoerceUnsizedInfo ;
16
18
use rustc_middle:: ty:: { self , suggest_constraining_type_params, Ty , TyCtxt , TypeVisitableExt } ;
19
+ use rustc_span:: Span ;
17
20
use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt ;
18
21
use 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 ,
20
24
} ;
21
25
use rustc_trait_selection:: traits:: ObligationCtxt ;
22
26
use rustc_trait_selection:: traits:: { self , ObligationCause } ;
@@ -27,6 +31,7 @@ pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
27
31
Checker { tcx, trait_def_id }
28
32
. check ( lang_items. drop_trait ( ) , visit_implementation_of_drop)
29
33
. check ( lang_items. copy_trait ( ) , visit_implementation_of_copy)
34
+ . check ( lang_items. const_param_ty_trait ( ) , visit_implementation_of_const_param_ty)
30
35
. check ( lang_items. coerce_unsized_trait ( ) , visit_implementation_of_coerce_unsized)
31
36
. check ( lang_items. dispatch_from_dyn_trait ( ) , visit_implementation_of_dispatch_from_dyn) ;
32
37
}
@@ -83,110 +88,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
83
88
match type_allowed_to_implement_copy ( tcx, param_env, self_type, cause) {
84
89
Ok ( ( ) ) => { }
85
90
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) ;
190
92
}
191
93
Err ( CopyImplementationError :: NotAnAdt ) => {
192
94
tcx. sess . emit_err ( CopyImplOnNonAdt { span } ) ;
@@ -197,6 +99,29 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
197
99
}
198
100
}
199
101
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
+
200
125
fn visit_implementation_of_coerce_unsized ( tcx : TyCtxt < ' _ > , impl_did : LocalDefId ) {
201
126
debug ! ( "visit_implementation_of_coerce_unsized: impl_did={:?}" , impl_did) ;
202
127
@@ -593,3 +518,119 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
593
518
594
519
CoerceUnsizedInfo { custom_kind : kind }
595
520
}
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