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:: {
5- ConstParamTyImplOnNonAdt , CopyImplOnNonAdt , CopyImplOnTypeWithDtor , DropImplOnWrongItem ,
6- } ;
4+ use crate :: errors;
5+
76use rustc_data_structures:: fx:: FxHashSet ;
8- use rustc_errors:: { struct_span_err , ErrorGuaranteed , MultiSpan } ;
7+ use rustc_errors:: { ErrorGuaranteed , MultiSpan } ;
98use rustc_hir as hir;
109use rustc_hir:: def_id:: { DefId , LocalDefId } ;
1110use rustc_hir:: lang_items:: LangItem ;
@@ -65,7 +64,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
6564
6665 let impl_ = tcx. hir ( ) . expect_item ( impl_did) . expect_impl ( ) ;
6766
68- tcx. sess . emit_err ( DropImplOnWrongItem { span : impl_. self_ty . span } ) ;
67+ tcx. sess . emit_err ( errors :: DropImplOnWrongItem { span : impl_. self_ty . span } ) ;
6968}
7069
7170fn visit_implementation_of_copy ( tcx : TyCtxt < ' _ > , impl_did : LocalDefId ) {
@@ -91,10 +90,10 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
9190 infringing_fields_error ( tcx, fields, LangItem :: Copy , impl_did, span) ;
9291 }
9392 Err ( CopyImplementationError :: NotAnAdt ) => {
94- tcx. sess . emit_err ( CopyImplOnNonAdt { span } ) ;
93+ tcx. sess . emit_err ( errors :: CopyImplOnNonAdt { span } ) ;
9594 }
9695 Err ( CopyImplementationError :: HasDestructor ) => {
97- tcx. sess . emit_err ( CopyImplOnTypeWithDtor { span } ) ;
96+ tcx. sess . emit_err ( errors :: CopyImplOnTypeWithDtor { span } ) ;
9897 }
9998 }
10099}
@@ -117,7 +116,7 @@ fn visit_implementation_of_const_param_ty(tcx: TyCtxt<'_>, impl_did: LocalDefId)
117116 infringing_fields_error ( tcx, fields, LangItem :: ConstParamTy , impl_did, span) ;
118117 }
119118 Err ( ConstParamTyImplementationError :: NotAnAdtOrBuiltinAllowed ) => {
120- tcx. sess . emit_err ( ConstParamTyImplOnNonAdt { span } ) ;
119+ tcx. sess . emit_err ( errors :: ConstParamTyImplOnNonAdt { span } ) ;
121120 }
122121 }
123122}
@@ -152,8 +151,6 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
152151
153152 let param_env = tcx. param_env ( impl_did) ;
154153
155- let create_err = |msg : & str | struct_span_err ! ( tcx. sess, span, E0378 , "{}" , msg) ;
156-
157154 let infcx = tcx. infer_ctxt ( ) . build ( ) ;
158155 let cause = ObligationCause :: misc ( span, impl_did) ;
159156
@@ -176,22 +173,19 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
176173 let source_path = tcx. def_path_str ( def_a. did ( ) ) ;
177174 let target_path = tcx. def_path_str ( def_b. did ( ) ) ;
178175
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+ } ) ;
185183
186184 return ;
187185 }
188186
189187 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 } ) ;
195189 }
196190
197191 let fields = & def_a. non_enum_variant ( ) . fields ;
@@ -213,16 +207,11 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
213207 infcx. at ( & cause, param_env) . eq ( DefineOpaqueTypes :: No , ty_a, ty_b)
214208 {
215209 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+ } ) ;
226215
227216 return false ;
228217 }
@@ -233,36 +222,29 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
233222 . collect :: < Vec < _ > > ( ) ;
234223
235224 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+ } ) ;
242230 } 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+ } ) ;
266248 } else {
267249 let ocx = ObligationCtxt :: new ( & infcx) ;
268250 for field in coerced_fields {
@@ -288,11 +270,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
288270 }
289271 }
290272 _ => {
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" } ) ;
296274 }
297275 }
298276}
@@ -359,17 +337,13 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
359337 if def_a != def_b {
360338 let source_path = tcx. def_path_str ( def_a. did ( ) ) ;
361339 let target_path = tcx. def_path_str ( def_b. did ( ) ) ;
362- struct_span_err ! (
363- tcx. sess,
340+ tcx. sess . emit_err ( errors:: DispatchFromDynSame {
364341 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 ,
369344 source_path,
370- target_path
371- )
372- . emit ( ) ;
345+ target_path,
346+ } ) ;
373347 return err_info;
374348 }
375349
@@ -445,15 +419,11 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
445419 . collect :: < Vec < _ > > ( ) ;
446420
447421 if diff_fields. is_empty ( ) {
448- struct_span_err ! (
449- tcx. sess,
422+ tcx. sess . emit_err ( errors:: CoerceUnsizedOneField {
450423 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+ } ) ;
457427 return err_info;
458428 } else if diff_fields. len ( ) > 1 {
459429 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
463433 tcx. def_span ( impl_did)
464434 } ;
465435
466- struct_span_err ! (
467- tcx. sess,
436+ tcx. sess . emit_err ( errors:: CoerceUnsizedMulti {
468437 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
482441 . 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) )
484443 . collect :: < Vec < _ > > ( )
485- . join( ", " )
486- ) )
487- . span_label ( span, "requires multiple coercions" )
488- . emit ( ) ;
444+ . join ( ", " ) ,
445+ } ) ;
446+
489447 return err_info;
490448 }
491449
@@ -495,14 +453,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
495453 }
496454
497455 _ => {
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" } ) ;
506457 return err_info;
507458 }
508459 } ;
@@ -540,28 +491,22 @@ fn infringing_fields_error(
540491
541492 let trait_name = tcx. def_path_str ( trait_did) ;
542493
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-
550494 // We'll try to suggest constraining type parameters to fulfill the requirements of
551495 // their `Copy` implementation.
552496 let mut errors: BTreeMap < _ , Vec < _ > > = Default :: default ( ) ;
553497 let mut bounds = vec ! [ ] ;
554498
555499 let mut seen_tys = FxHashSet :: default ( ) ;
556500
501+ let mut label_spans = Vec :: new ( ) ;
502+
557503 for ( field, ty, reason) in fields {
558504 // Only report an error once per type.
559505 if !seen_tys. insert ( ty) {
560506 continue ;
561507 }
562508
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 ) ) ;
565510
566511 match reason {
567512 InfringingFieldsReason :: Fulfill ( fulfillment_errors) => {
@@ -625,13 +570,24 @@ fn infringing_fields_error(
625570 }
626571 }
627572 }
573+ let mut notes = Vec :: new ( ) ;
628574 for ( ( ty, error_predicate) , spans) in errors {
629575 let span: MultiSpan = spans. into ( ) ;
630- err . span_note (
576+ notes . push ( errors :: ImplForTyRequires {
631577 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+ } ) ;
634582 }
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+
635591 suggest_constraining_type_params (
636592 tcx,
637593 tcx. hir ( ) . get_generics ( impl_did) . expect ( "impls always have generics" ) ,
0 commit comments