@@ -25,14 +25,21 @@ use rustc_trait_selection::traits::ObligationCtxt;
25
25
use rustc_trait_selection:: traits:: { self , ObligationCause } ;
26
26
use std:: collections:: BTreeMap ;
27
27
28
- pub fn check_trait ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) {
28
+ pub fn check_trait ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> Result < ( ) , ErrorGuaranteed > {
29
29
let lang_items = tcx. lang_items ( ) ;
30
- Checker { tcx, trait_def_id }
31
- . check ( lang_items. drop_trait ( ) , visit_implementation_of_drop)
32
- . check ( lang_items. copy_trait ( ) , visit_implementation_of_copy)
33
- . check ( lang_items. const_param_ty_trait ( ) , visit_implementation_of_const_param_ty)
34
- . check ( lang_items. coerce_unsized_trait ( ) , visit_implementation_of_coerce_unsized)
35
- . check ( lang_items. dispatch_from_dyn_trait ( ) , visit_implementation_of_dispatch_from_dyn) ;
30
+ let checker = Checker { tcx, trait_def_id } ;
31
+ let mut res = checker. check ( lang_items. drop_trait ( ) , visit_implementation_of_drop) ;
32
+ res = res. and ( checker. check ( lang_items. copy_trait ( ) , visit_implementation_of_copy) ) ;
33
+ res = res. and (
34
+ checker. check ( lang_items. const_param_ty_trait ( ) , visit_implementation_of_const_param_ty) ,
35
+ ) ;
36
+ res = res. and (
37
+ checker. check ( lang_items. coerce_unsized_trait ( ) , visit_implementation_of_coerce_unsized) ,
38
+ ) ;
39
+ res. and (
40
+ checker
41
+ . check ( lang_items. dispatch_from_dyn_trait ( ) , visit_implementation_of_dispatch_from_dyn) ,
42
+ )
36
43
}
37
44
38
45
struct Checker < ' tcx > {
@@ -41,33 +48,40 @@ struct Checker<'tcx> {
41
48
}
42
49
43
50
impl < ' tcx > Checker < ' tcx > {
44
- fn check < F > ( & self , trait_def_id : Option < DefId > , mut f : F ) -> & Self
51
+ fn check < F > ( & self , trait_def_id : Option < DefId > , mut f : F ) -> Result < ( ) , ErrorGuaranteed >
45
52
where
46
- F : FnMut ( TyCtxt < ' tcx > , LocalDefId ) ,
53
+ F : FnMut ( TyCtxt < ' tcx > , LocalDefId ) -> Result < ( ) , ErrorGuaranteed > ,
47
54
{
55
+ let mut res = Ok ( ( ) ) ;
48
56
if Some ( self . trait_def_id ) == trait_def_id {
49
57
for & impl_def_id in self . tcx . hir ( ) . trait_impls ( self . trait_def_id ) {
50
- f ( self . tcx , impl_def_id) ;
58
+ res = res . and ( f ( self . tcx , impl_def_id) ) ;
51
59
}
52
60
}
53
- self
61
+ res
54
62
}
55
63
}
56
64
57
- fn visit_implementation_of_drop ( tcx : TyCtxt < ' _ > , impl_did : LocalDefId ) {
65
+ fn visit_implementation_of_drop (
66
+ tcx : TyCtxt < ' _ > ,
67
+ impl_did : LocalDefId ,
68
+ ) -> Result < ( ) , ErrorGuaranteed > {
58
69
// Destructors only work on local ADT types.
59
70
match tcx. type_of ( impl_did) . instantiate_identity ( ) . kind ( ) {
60
- ty:: Adt ( def, _) if def. did ( ) . is_local ( ) => return ,
61
- ty:: Error ( _) => return ,
71
+ ty:: Adt ( def, _) if def. did ( ) . is_local ( ) => return Ok ( ( ) ) ,
72
+ ty:: Error ( _) => return Ok ( ( ) ) ,
62
73
_ => { }
63
74
}
64
75
65
76
let impl_ = tcx. hir ( ) . expect_item ( impl_did) . expect_impl ( ) ;
66
77
67
- tcx. dcx ( ) . emit_err ( errors:: DropImplOnWrongItem { span : impl_. self_ty . span } ) ;
78
+ Err ( tcx. dcx ( ) . emit_err ( errors:: DropImplOnWrongItem { span : impl_. self_ty . span } ) )
68
79
}
69
80
70
- fn visit_implementation_of_copy ( tcx : TyCtxt < ' _ > , impl_did : LocalDefId ) {
81
+ fn visit_implementation_of_copy (
82
+ tcx : TyCtxt < ' _ > ,
83
+ impl_did : LocalDefId ,
84
+ ) -> Result < ( ) , ErrorGuaranteed > {
71
85
debug ! ( "visit_implementation_of_copy: impl_did={:?}" , impl_did) ;
72
86
73
87
let self_type = tcx. type_of ( impl_did) . instantiate_identity ( ) ;
@@ -79,59 +93,68 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
79
93
debug ! ( "visit_implementation_of_copy: self_type={:?} (free)" , self_type) ;
80
94
81
95
let span = match tcx. hir ( ) . expect_item ( impl_did) . expect_impl ( ) {
82
- hir:: Impl { polarity : hir:: ImplPolarity :: Negative ( _) , .. } => return ,
96
+ hir:: Impl { polarity : hir:: ImplPolarity :: Negative ( _) , .. } => return Ok ( ( ) ) ,
83
97
hir:: Impl { self_ty, .. } => self_ty. span ,
84
98
} ;
85
99
86
100
let cause = traits:: ObligationCause :: misc ( span, impl_did) ;
87
101
match type_allowed_to_implement_copy ( tcx, param_env, self_type, cause) {
88
- Ok ( ( ) ) => { }
102
+ Ok ( ( ) ) => Ok ( ( ) ) ,
89
103
Err ( CopyImplementationError :: InfringingFields ( fields) ) => {
90
- infringing_fields_error ( tcx, fields, LangItem :: Copy , impl_did, span) ;
104
+ Err ( infringing_fields_error ( tcx, fields, LangItem :: Copy , impl_did, span) )
91
105
}
92
106
Err ( CopyImplementationError :: NotAnAdt ) => {
93
- tcx. dcx ( ) . emit_err ( errors:: CopyImplOnNonAdt { span } ) ;
107
+ Err ( tcx. dcx ( ) . emit_err ( errors:: CopyImplOnNonAdt { span } ) )
94
108
}
95
109
Err ( CopyImplementationError :: HasDestructor ) => {
96
- tcx. dcx ( ) . emit_err ( errors:: CopyImplOnTypeWithDtor { span } ) ;
110
+ Err ( tcx. dcx ( ) . emit_err ( errors:: CopyImplOnTypeWithDtor { span } ) )
97
111
}
98
112
}
99
113
}
100
114
101
- fn visit_implementation_of_const_param_ty ( tcx : TyCtxt < ' _ > , impl_did : LocalDefId ) {
115
+ fn visit_implementation_of_const_param_ty (
116
+ tcx : TyCtxt < ' _ > ,
117
+ impl_did : LocalDefId ,
118
+ ) -> Result < ( ) , ErrorGuaranteed > {
102
119
let self_type = tcx. type_of ( impl_did) . instantiate_identity ( ) ;
103
120
assert ! ( !self_type. has_escaping_bound_vars( ) ) ;
104
121
105
122
let param_env = tcx. param_env ( impl_did) ;
106
123
107
124
let span = match tcx. hir ( ) . expect_item ( impl_did) . expect_impl ( ) {
108
- hir:: Impl { polarity : hir:: ImplPolarity :: Negative ( _) , .. } => return ,
125
+ hir:: Impl { polarity : hir:: ImplPolarity :: Negative ( _) , .. } => return Ok ( ( ) ) ,
109
126
impl_ => impl_. self_ty . span ,
110
127
} ;
111
128
112
129
let cause = traits:: ObligationCause :: misc ( span, impl_did) ;
113
130
match type_allowed_to_implement_const_param_ty ( tcx, param_env, self_type, cause) {
114
- Ok ( ( ) ) => { }
131
+ Ok ( ( ) ) => Ok ( ( ) ) ,
115
132
Err ( ConstParamTyImplementationError :: InfrigingFields ( fields) ) => {
116
- infringing_fields_error ( tcx, fields, LangItem :: ConstParamTy , impl_did, span) ;
133
+ Err ( infringing_fields_error ( tcx, fields, LangItem :: ConstParamTy , impl_did, span) )
117
134
}
118
135
Err ( ConstParamTyImplementationError :: NotAnAdtOrBuiltinAllowed ) => {
119
- tcx. dcx ( ) . emit_err ( errors:: ConstParamTyImplOnNonAdt { span } ) ;
136
+ Err ( tcx. dcx ( ) . emit_err ( errors:: ConstParamTyImplOnNonAdt { span } ) )
120
137
}
121
138
}
122
139
}
123
140
124
- fn visit_implementation_of_coerce_unsized ( tcx : TyCtxt < ' _ > , impl_did : LocalDefId ) {
141
+ fn visit_implementation_of_coerce_unsized (
142
+ tcx : TyCtxt < ' _ > ,
143
+ impl_did : LocalDefId ,
144
+ ) -> Result < ( ) , ErrorGuaranteed > {
125
145
debug ! ( "visit_implementation_of_coerce_unsized: impl_did={:?}" , impl_did) ;
126
146
127
147
// Just compute this for the side-effects, in particular reporting
128
148
// errors; other parts of the code may demand it for the info of
129
149
// course.
130
150
let span = tcx. def_span ( impl_did) ;
131
- tcx. at ( span) . coerce_unsized_info ( impl_did) ;
151
+ tcx. at ( span) . ensure ( ) . coerce_unsized_info ( impl_did)
132
152
}
133
153
134
- fn visit_implementation_of_dispatch_from_dyn ( tcx : TyCtxt < ' _ > , impl_did : LocalDefId ) {
154
+ fn visit_implementation_of_dispatch_from_dyn (
155
+ tcx : TyCtxt < ' _ > ,
156
+ impl_did : LocalDefId ,
157
+ ) -> Result < ( ) , ErrorGuaranteed > {
135
158
debug ! ( "visit_implementation_of_dispatch_from_dyn: impl_did={:?}" , impl_did) ;
136
159
137
160
let span = tcx. def_span ( impl_did) ;
@@ -166,26 +189,28 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
166
189
match ( source. kind ( ) , target. kind ( ) ) {
167
190
( & Ref ( r_a, _, mutbl_a) , Ref ( r_b, _, mutbl_b) )
168
191
if infcx. at ( & cause, param_env) . eq ( DefineOpaqueTypes :: No , r_a, * r_b) . is_ok ( )
169
- && mutbl_a == * mutbl_b => { }
170
- ( & RawPtr ( tm_a) , & RawPtr ( tm_b) ) if tm_a. mutbl == tm_b. mutbl => ( ) ,
192
+ && mutbl_a == * mutbl_b =>
193
+ {
194
+ Ok ( ( ) )
195
+ }
196
+ ( & RawPtr ( tm_a) , & RawPtr ( tm_b) ) if tm_a. mutbl == tm_b. mutbl => Ok ( ( ) ) ,
171
197
( & Adt ( def_a, args_a) , & Adt ( def_b, args_b) ) if def_a. is_struct ( ) && def_b. is_struct ( ) => {
172
198
if def_a != def_b {
173
199
let source_path = tcx. def_path_str ( def_a. did ( ) ) ;
174
200
let target_path = tcx. def_path_str ( def_b. did ( ) ) ;
175
201
176
- tcx. dcx ( ) . emit_err ( errors:: DispatchFromDynCoercion {
202
+ return Err ( tcx. dcx ( ) . emit_err ( errors:: DispatchFromDynCoercion {
177
203
span,
178
204
trait_name : "DispatchFromDyn" ,
179
205
note : true ,
180
206
source_path,
181
207
target_path,
182
- } ) ;
183
-
184
- return ;
208
+ } ) ) ;
185
209
}
186
210
211
+ let mut res = Ok ( ( ) ) ;
187
212
if def_a. repr ( ) . c ( ) || def_a. repr ( ) . packed ( ) {
188
- tcx. dcx ( ) . emit_err ( errors:: DispatchFromDynRepr { span } ) ;
213
+ res = Err ( tcx. dcx ( ) . emit_err ( errors:: DispatchFromDynRepr { span } ) ) ;
189
214
}
190
215
191
216
let fields = & def_a. non_enum_variant ( ) . fields ;
@@ -207,11 +232,11 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
207
232
infcx. at ( & cause, param_env) . eq ( DefineOpaqueTypes :: No , ty_a, ty_b)
208
233
{
209
234
if ok. obligations . is_empty ( ) {
210
- tcx. dcx ( ) . emit_err ( errors:: DispatchFromDynZST {
235
+ res = Err ( tcx. dcx ( ) . emit_err ( errors:: DispatchFromDynZST {
211
236
span,
212
237
name : field. name ,
213
238
ty : ty_a,
214
- } ) ;
239
+ } ) ) ;
215
240
216
241
return false ;
217
242
}
@@ -222,13 +247,13 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
222
247
. collect :: < Vec < _ > > ( ) ;
223
248
224
249
if coerced_fields. is_empty ( ) {
225
- tcx. dcx ( ) . emit_err ( errors:: DispatchFromDynSingle {
250
+ res = Err ( tcx. dcx ( ) . emit_err ( errors:: DispatchFromDynSingle {
226
251
span,
227
252
trait_name : "DispatchFromDyn" ,
228
253
note : true ,
229
- } ) ;
254
+ } ) ) ;
230
255
} else if coerced_fields. len ( ) > 1 {
231
- tcx. dcx ( ) . emit_err ( errors:: DispatchFromDynMulti {
256
+ res = Err ( tcx. dcx ( ) . emit_err ( errors:: DispatchFromDynMulti {
232
257
span,
233
258
coercions_note : true ,
234
259
number : coerced_fields. len ( ) ,
@@ -244,7 +269,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
244
269
} )
245
270
. collect :: < Vec < _ > > ( )
246
271
. join ( ", " ) ,
247
- } ) ;
272
+ } ) ) ;
248
273
} else {
249
274
let ocx = ObligationCtxt :: new ( & infcx) ;
250
275
for field in coerced_fields {
@@ -261,21 +286,25 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
261
286
}
262
287
let errors = ocx. select_all_or_error ( ) ;
263
288
if !errors. is_empty ( ) {
264
- infcx. err_ctxt ( ) . report_fulfillment_errors ( errors) ;
289
+ res = Err ( infcx. err_ctxt ( ) . report_fulfillment_errors ( errors) ) ;
265
290
}
266
291
267
292
// Finally, resolve all regions.
268
293
let outlives_env = OutlivesEnvironment :: new ( param_env) ;
269
- let _ = ocx. resolve_regions_and_report_errors ( impl_did, & outlives_env) ;
294
+ res = res . and ( ocx. resolve_regions_and_report_errors ( impl_did, & outlives_env) ) ;
270
295
}
296
+ res
271
297
}
272
- _ => {
273
- tcx . dcx ( ) . emit_err ( errors :: CoerceUnsizedMay { span , trait_name : "DispatchFromDyn" } ) ;
274
- }
298
+ _ => Err ( tcx
299
+ . dcx ( )
300
+ . emit_err ( errors :: CoerceUnsizedMay { span , trait_name : "DispatchFromDyn" } ) ) ,
275
301
}
276
302
}
277
303
278
- pub fn coerce_unsized_info < ' tcx > ( tcx : TyCtxt < ' tcx > , impl_did : LocalDefId ) -> CoerceUnsizedInfo {
304
+ pub fn coerce_unsized_info < ' tcx > (
305
+ tcx : TyCtxt < ' tcx > ,
306
+ impl_did : LocalDefId ,
307
+ ) -> Result < CoerceUnsizedInfo , ErrorGuaranteed > {
279
308
debug ! ( "compute_coerce_unsized_info(impl_did={:?})" , impl_did) ;
280
309
let span = tcx. def_span ( impl_did) ;
281
310
@@ -292,8 +321,6 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
292
321
let param_env = tcx. param_env ( impl_did) ;
293
322
assert ! ( !source. has_escaping_bound_vars( ) ) ;
294
323
295
- let err_info = CoerceUnsizedInfo { custom_kind : None } ;
296
-
297
324
debug ! ( "visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)" , source, target) ;
298
325
299
326
let infcx = tcx. infer_ctxt ( ) . build ( ) ;
@@ -337,14 +364,13 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
337
364
if def_a != def_b {
338
365
let source_path = tcx. def_path_str ( def_a. did ( ) ) ;
339
366
let target_path = tcx. def_path_str ( def_b. did ( ) ) ;
340
- tcx. dcx ( ) . emit_err ( errors:: DispatchFromDynSame {
367
+ return Err ( tcx. dcx ( ) . emit_err ( errors:: DispatchFromDynSame {
341
368
span,
342
369
trait_name : "CoerceUnsized" ,
343
370
note : true ,
344
371
source_path,
345
372
target_path,
346
- } ) ;
347
- return err_info;
373
+ } ) ) ;
348
374
}
349
375
350
376
// Here we are considering a case of converting
@@ -419,12 +445,11 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
419
445
. collect :: < Vec < _ > > ( ) ;
420
446
421
447
if diff_fields. is_empty ( ) {
422
- tcx. dcx ( ) . emit_err ( errors:: CoerceUnsizedOneField {
448
+ return Err ( tcx. dcx ( ) . emit_err ( errors:: CoerceUnsizedOneField {
423
449
span,
424
450
trait_name : "CoerceUnsized" ,
425
451
note : true ,
426
- } ) ;
427
- return err_info;
452
+ } ) ) ;
428
453
} else if diff_fields. len ( ) > 1 {
429
454
let item = tcx. hir ( ) . expect_item ( impl_did) ;
430
455
let span = if let ItemKind :: Impl ( hir:: Impl { of_trait : Some ( t) , .. } ) = & item. kind {
@@ -433,7 +458,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
433
458
tcx. def_span ( impl_did)
434
459
} ;
435
460
436
- tcx. dcx ( ) . emit_err ( errors:: CoerceUnsizedMulti {
461
+ return Err ( tcx. dcx ( ) . emit_err ( errors:: CoerceUnsizedMulti {
437
462
span,
438
463
coercions_note : true ,
439
464
number : diff_fields. len ( ) ,
@@ -442,9 +467,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
442
467
. map ( |& ( i, a, b) | format ! ( "`{}` (`{}` to `{}`)" , fields[ i] . name, a, b) )
443
468
. collect :: < Vec < _ > > ( )
444
469
. join ( ", " ) ,
445
- } ) ;
446
-
447
- return err_info;
470
+ } ) ) ;
448
471
}
449
472
450
473
let ( i, a, b) = diff_fields[ 0 ] ;
@@ -453,8 +476,9 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
453
476
}
454
477
455
478
_ => {
456
- tcx. dcx ( ) . emit_err ( errors:: DispatchFromDynStruct { span, trait_name : "CoerceUnsized" } ) ;
457
- return err_info;
479
+ return Err ( tcx
480
+ . dcx ( )
481
+ . emit_err ( errors:: DispatchFromDynStruct { span, trait_name : "CoerceUnsized" } ) ) ;
458
482
}
459
483
} ;
460
484
@@ -469,15 +493,17 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
469
493
) ;
470
494
ocx. register_obligation ( obligation) ;
471
495
let errors = ocx. select_all_or_error ( ) ;
496
+ let mut res = Ok ( ( ) ) ;
472
497
if !errors. is_empty ( ) {
473
- infcx. err_ctxt ( ) . report_fulfillment_errors ( errors) ;
498
+ res = Err ( infcx. err_ctxt ( ) . report_fulfillment_errors ( errors) ) ;
474
499
}
475
500
476
501
// Finally, resolve all regions.
477
502
let outlives_env = OutlivesEnvironment :: new ( param_env) ;
478
- let _ = ocx. resolve_regions_and_report_errors ( impl_did, & outlives_env) ;
503
+ ocx. resolve_regions_and_report_errors ( impl_did, & outlives_env) ?;
504
+ res?;
479
505
480
- CoerceUnsizedInfo { custom_kind : kind }
506
+ Ok ( CoerceUnsizedInfo { custom_kind : kind } )
481
507
}
482
508
483
509
fn infringing_fields_error (
0 commit comments