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:: {
5
- ConstParamTyImplOnNonAdt , CopyImplOnNonAdt , CopyImplOnTypeWithDtor , DropImplOnWrongItem ,
6
- } ;
4
+ use crate :: errors;
5
+
7
6
use rustc_data_structures:: fx:: FxHashSet ;
8
- use rustc_errors:: { struct_span_err , ErrorGuaranteed , MultiSpan } ;
7
+ use rustc_errors:: { ErrorGuaranteed , MultiSpan } ;
9
8
use rustc_hir as hir;
10
9
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
11
10
use rustc_hir:: lang_items:: LangItem ;
@@ -65,7 +64,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
65
64
66
65
let impl_ = tcx. hir ( ) . expect_item ( impl_did) . expect_impl ( ) ;
67
66
68
- tcx. sess . emit_err ( DropImplOnWrongItem { span : impl_. self_ty . span } ) ;
67
+ tcx. sess . emit_err ( errors :: DropImplOnWrongItem { span : impl_. self_ty . span } ) ;
69
68
}
70
69
71
70
fn visit_implementation_of_copy ( tcx : TyCtxt < ' _ > , impl_did : LocalDefId ) {
@@ -91,10 +90,10 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
91
90
infringing_fields_error ( tcx, fields, LangItem :: Copy , impl_did, span) ;
92
91
}
93
92
Err ( CopyImplementationError :: NotAnAdt ) => {
94
- tcx. sess . emit_err ( CopyImplOnNonAdt { span } ) ;
93
+ tcx. sess . emit_err ( errors :: CopyImplOnNonAdt { span } ) ;
95
94
}
96
95
Err ( CopyImplementationError :: HasDestructor ) => {
97
- tcx. sess . emit_err ( CopyImplOnTypeWithDtor { span } ) ;
96
+ tcx. sess . emit_err ( errors :: CopyImplOnTypeWithDtor { span } ) ;
98
97
}
99
98
}
100
99
}
@@ -117,7 +116,7 @@ fn visit_implementation_of_const_param_ty(tcx: TyCtxt<'_>, impl_did: LocalDefId)
117
116
infringing_fields_error ( tcx, fields, LangItem :: ConstParamTy , impl_did, span) ;
118
117
}
119
118
Err ( ConstParamTyImplementationError :: NotAnAdtOrBuiltinAllowed ) => {
120
- tcx. sess . emit_err ( ConstParamTyImplOnNonAdt { span } ) ;
119
+ tcx. sess . emit_err ( errors :: ConstParamTyImplOnNonAdt { span } ) ;
121
120
}
122
121
}
123
122
}
@@ -152,8 +151,6 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
152
151
153
152
let param_env = tcx. param_env ( impl_did) ;
154
153
155
- let create_err = |msg : & str | struct_span_err ! ( tcx. sess, span, E0378 , "{}" , msg) ;
156
-
157
154
let infcx = tcx. infer_ctxt ( ) . build ( ) ;
158
155
let cause = ObligationCause :: misc ( span, impl_did) ;
159
156
@@ -176,22 +173,19 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
176
173
let source_path = tcx. def_path_str ( def_a. did ( ) ) ;
177
174
let target_path = tcx. def_path_str ( def_b. did ( ) ) ;
178
175
179
- create_err ( & format ! (
180
- "the trait `DispatchFromDyn` may only be implemented \
181
- for a coercion between structures with the same \
182
- definition; expected `{source_path}`, found `{target_path}`",
183
- ) )
184
- . emit ( ) ;
176
+ tcx. sess . emit_err ( errors:: DispatchFromDynCoercion {
177
+ span,
178
+ trait_name : "DispatchFromDyn" ,
179
+ note : true ,
180
+ source_path,
181
+ target_path,
182
+ } ) ;
185
183
186
184
return ;
187
185
}
188
186
189
187
if def_a. repr ( ) . c ( ) || def_a. repr ( ) . packed ( ) {
190
- create_err (
191
- "structs implementing `DispatchFromDyn` may not have \
192
- `#[repr(packed)]` or `#[repr(C)]`",
193
- )
194
- . emit ( ) ;
188
+ tcx. sess . emit_err ( errors:: DispatchFromDynRepr { span } ) ;
195
189
}
196
190
197
191
let fields = & def_a. non_enum_variant ( ) . fields ;
@@ -213,16 +207,11 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
213
207
infcx. at ( & cause, param_env) . eq ( DefineOpaqueTypes :: No , ty_a, ty_b)
214
208
{
215
209
if ok. obligations . is_empty ( ) {
216
- create_err (
217
- "the trait `DispatchFromDyn` may only be implemented \
218
- for structs containing the field being coerced, \
219
- ZST fields with 1 byte alignment, and nothing else",
220
- )
221
- . note ( format ! (
222
- "extra field `{}` of type `{}` is not allowed" ,
223
- field. name, ty_a,
224
- ) )
225
- . emit ( ) ;
210
+ tcx. sess . emit_err ( errors:: DispatchFromDynZST {
211
+ span,
212
+ name : field. name ,
213
+ ty : ty_a,
214
+ } ) ;
226
215
227
216
return false ;
228
217
}
@@ -233,36 +222,29 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
233
222
. collect :: < Vec < _ > > ( ) ;
234
223
235
224
if coerced_fields. is_empty ( ) {
236
- create_err (
237
- "the trait `DispatchFromDyn` may only be implemented \
238
- for a coercion between structures with a single field \
239
- being coerced, none found",
240
- )
241
- . emit ( ) ;
225
+ tcx. sess . emit_err ( errors:: DispatchFromDynSingle {
226
+ span,
227
+ trait_name : "DispatchFromDyn" ,
228
+ note : true ,
229
+ } ) ;
242
230
} else if coerced_fields. len ( ) > 1 {
243
- create_err ( "implementing the `DispatchFromDyn` trait requires multiple coercions" )
244
- . note (
245
- "the trait `DispatchFromDyn` may only be implemented \
246
- for a coercion between structures with a single field \
247
- being coerced",
248
- )
249
- . note ( format ! (
250
- "currently, {} fields need coercions: {}" ,
251
- coerced_fields. len( ) ,
252
- coerced_fields
253
- . iter( )
254
- . map( |field| {
255
- format!(
256
- "`{}` (`{}` to `{}`)" ,
257
- field. name,
258
- field. ty( tcx, args_a) ,
259
- field. ty( tcx, args_b) ,
260
- )
261
- } )
262
- . collect:: <Vec <_>>( )
263
- . join( ", " )
264
- ) )
265
- . emit ( ) ;
231
+ tcx. sess . emit_err ( errors:: DispatchFromDynMulti {
232
+ span,
233
+ coercions_note : true ,
234
+ number : coerced_fields. len ( ) ,
235
+ coercions : coerced_fields
236
+ . iter ( )
237
+ . map ( |field| {
238
+ format ! (
239
+ "`{}` (`{}` to `{}`)" ,
240
+ field. name,
241
+ field. ty( tcx, args_a) ,
242
+ field. ty( tcx, args_b) ,
243
+ )
244
+ } )
245
+ . collect :: < Vec < _ > > ( )
246
+ . join ( ", " ) ,
247
+ } ) ;
266
248
} else {
267
249
let ocx = ObligationCtxt :: new ( & infcx) ;
268
250
for field in coerced_fields {
@@ -288,11 +270,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
288
270
}
289
271
}
290
272
_ => {
291
- create_err (
292
- "the trait `DispatchFromDyn` may only be implemented \
293
- for a coercion between structures",
294
- )
295
- . emit ( ) ;
273
+ tcx. sess . emit_err ( errors:: CoerceUnsizedMay { span, trait_name : "DispatchFromDyn" } ) ;
296
274
}
297
275
}
298
276
}
@@ -359,17 +337,13 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
359
337
if def_a != def_b {
360
338
let source_path = tcx. def_path_str ( def_a. did ( ) ) ;
361
339
let target_path = tcx. def_path_str ( def_b. did ( ) ) ;
362
- struct_span_err ! (
363
- tcx. sess,
340
+ tcx. sess . emit_err ( errors:: DispatchFromDynSame {
364
341
span,
365
- E0377 ,
366
- "the trait `CoerceUnsized` may only be implemented \
367
- for a coercion between structures with the same \
368
- definition; expected `{}`, found `{}`",
342
+ trait_name : "CoerceUnsized" ,
343
+ note : true ,
369
344
source_path,
370
- target_path
371
- )
372
- . emit ( ) ;
345
+ target_path,
346
+ } ) ;
373
347
return err_info;
374
348
}
375
349
@@ -445,15 +419,11 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
445
419
. collect :: < Vec < _ > > ( ) ;
446
420
447
421
if diff_fields. is_empty ( ) {
448
- struct_span_err ! (
449
- tcx. sess,
422
+ tcx. sess . emit_err ( errors:: CoerceUnsizedOneField {
450
423
span,
451
- E0374 ,
452
- "the trait `CoerceUnsized` may only be implemented \
453
- for a coercion between structures with one field \
454
- being coerced, none found"
455
- )
456
- . emit ( ) ;
424
+ trait_name : "CoerceUnsized" ,
425
+ note : true ,
426
+ } ) ;
457
427
return err_info;
458
428
} else if diff_fields. len ( ) > 1 {
459
429
let item = tcx. hir ( ) . expect_item ( impl_did) ;
@@ -463,29 +433,17 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
463
433
tcx. def_span ( impl_did)
464
434
} ;
465
435
466
- struct_span_err ! (
467
- tcx. sess,
436
+ tcx. sess . emit_err ( errors:: CoerceUnsizedMulti {
468
437
span,
469
- E0375 ,
470
- "implementing the trait \
471
- `CoerceUnsized` requires multiple \
472
- coercions"
473
- )
474
- . note (
475
- "`CoerceUnsized` may only be implemented for \
476
- a coercion between structures with one field being coerced",
477
- )
478
- . note ( format ! (
479
- "currently, {} fields need coercions: {}" ,
480
- diff_fields. len( ) ,
481
- diff_fields
438
+ coercions_note : true ,
439
+ number : diff_fields. len ( ) ,
440
+ coercions : diff_fields
482
441
. iter ( )
483
- . map( |& ( i, a, b) | { format!( "`{}` (`{}` to `{}`)" , fields[ i] . name, a, b) } )
442
+ . map ( |& ( i, a, b) | format ! ( "`{}` (`{}` to `{}`)" , fields[ i] . name, a, b) )
484
443
. collect :: < Vec < _ > > ( )
485
- . join( ", " )
486
- ) )
487
- . span_label ( span, "requires multiple coercions" )
488
- . emit ( ) ;
444
+ . join ( ", " ) ,
445
+ } ) ;
446
+
489
447
return err_info;
490
448
}
491
449
@@ -495,14 +453,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
495
453
}
496
454
497
455
_ => {
498
- struct_span_err ! (
499
- tcx. sess,
500
- span,
501
- E0376 ,
502
- "the trait `CoerceUnsized` may only be implemented \
503
- for a coercion between structures"
504
- )
505
- . emit ( ) ;
456
+ tcx. sess . emit_err ( errors:: DispatchFromDynStruct { span, trait_name : "CoerceUnsized" } ) ;
506
457
return err_info;
507
458
}
508
459
} ;
@@ -540,28 +491,22 @@ fn infringing_fields_error(
540
491
541
492
let trait_name = tcx. def_path_str ( trait_did) ;
542
493
543
- let mut err = struct_span_err ! (
544
- tcx. sess,
545
- impl_span,
546
- E0204 ,
547
- "the trait `{trait_name}` cannot be implemented for this type"
548
- ) ;
549
-
550
494
// We'll try to suggest constraining type parameters to fulfill the requirements of
551
495
// their `Copy` implementation.
552
496
let mut errors: BTreeMap < _ , Vec < _ > > = Default :: default ( ) ;
553
497
let mut bounds = vec ! [ ] ;
554
498
555
499
let mut seen_tys = FxHashSet :: default ( ) ;
556
500
501
+ let mut label_spans = Vec :: new ( ) ;
502
+
557
503
for ( field, ty, reason) in fields {
558
504
// Only report an error once per type.
559
505
if !seen_tys. insert ( ty) {
560
506
continue ;
561
507
}
562
508
563
- let field_span = tcx. def_span ( field. did ) ;
564
- err. span_label ( field_span, format ! ( "this field does not implement `{trait_name}`" ) ) ;
509
+ label_spans. push ( tcx. def_span ( field. did ) ) ;
565
510
566
511
match reason {
567
512
InfringingFieldsReason :: Fulfill ( fulfillment_errors) => {
@@ -625,13 +570,24 @@ fn infringing_fields_error(
625
570
}
626
571
}
627
572
}
573
+ let mut notes = Vec :: new ( ) ;
628
574
for ( ( ty, error_predicate) , spans) in errors {
629
575
let span: MultiSpan = spans. into ( ) ;
630
- err . span_note (
576
+ notes . push ( errors :: ImplForTyRequires {
631
577
span,
632
- format ! ( "the `{trait_name}` impl for `{ty}` requires that `{error_predicate}`" ) ,
633
- ) ;
578
+ error_predicate,
579
+ trait_name : trait_name. clone ( ) ,
580
+ ty,
581
+ } ) ;
634
582
}
583
+
584
+ let mut err = tcx. sess . create_err ( errors:: TraitCannotImplForTy {
585
+ span : impl_span,
586
+ trait_name,
587
+ label_spans,
588
+ notes,
589
+ } ) ;
590
+
635
591
suggest_constraining_type_params (
636
592
tcx,
637
593
tcx. hir ( ) . get_generics ( impl_did) . expect ( "impls always have generics" ) ,
0 commit comments