@@ -7,7 +7,7 @@ use rustc_attr as attr;
7
7
use rustc_errors:: { Applicability , ErrorReported } ;
8
8
use rustc_hir as hir;
9
9
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
10
- use rustc_hir:: intravisit:: Visitor ;
10
+ use rustc_hir:: intravisit:: { self , Visitor } ;
11
11
use rustc_hir:: lang_items:: LangItem ;
12
12
use rustc_hir:: { def:: DefKind , def:: Res , ItemKind , Node , PathSegment } ;
13
13
use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
@@ -437,40 +437,82 @@ fn check_fields_for_opaque_types(
437
437
def_id : LocalDefId ,
438
438
span : Span ,
439
439
) {
440
- fn find_span_of_field_def_and_ty_alias (
440
+ struct TyAliasFinder < ' tcx > {
441
+ tcx : TyCtxt < ' tcx > ,
442
+ ty_alias_span : Option < Span > ,
443
+ ty_alias_ident : Option < Ident > ,
444
+ field_ty_span : Option < Span > ,
445
+ }
446
+
447
+ impl TyAliasFinder < ' _ > {
448
+ fn new ( tcx : TyCtxt < ' tcx > ) -> TyAliasFinder < ' _ > {
449
+ TyAliasFinder { tcx, ty_alias_span : None , ty_alias_ident : None , field_ty_span : None }
450
+ }
451
+
452
+ fn get_collected_information ( & self ) -> ( Option < Span > , Option < Ident > , Option < Span > ) {
453
+ ( self . field_ty_span , self . ty_alias_ident , self . ty_alias_span )
454
+ }
455
+ }
456
+
457
+ impl < ' tcx > intravisit:: Visitor < ' tcx > for TyAliasFinder < ' tcx > {
458
+ type Map = intravisit:: ErasedMap < ' tcx > ;
459
+
460
+ fn nested_visit_map ( & mut self ) -> intravisit:: NestedVisitorMap < Self :: Map > {
461
+ intravisit:: NestedVisitorMap :: None
462
+ }
463
+
464
+ fn visit_ty ( & mut self , t : & ' tcx hir:: Ty < ' _ > ) {
465
+ if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( _, path) ) = t. kind {
466
+ if let Res :: Def ( DefKind :: TyAlias , ty_alias_def_id) = path. res {
467
+ let span = path. span ;
468
+ if let Some ( ty_alias_local_id) = ty_alias_def_id. as_local ( ) {
469
+ let ty_alias_hir_id =
470
+ self . tcx . hir ( ) . local_def_id_to_hir_id ( ty_alias_local_id) ;
471
+ let node = self . tcx . hir ( ) . get ( ty_alias_hir_id) ;
472
+ match node {
473
+ hir:: Node :: Item ( hir:: Item {
474
+ ident, kind, span : ty_alias_span, ..
475
+ } ) => match kind {
476
+ hir:: ItemKind :: TyAlias ( _, _) => {
477
+ self . ty_alias_span = Some ( * ty_alias_span) ;
478
+ self . ty_alias_ident = Some ( * ident) ;
479
+ self . field_ty_span = Some ( span) ;
480
+ return ;
481
+ }
482
+ _ => bug ! ( "expected an item of kind TyAlias" ) ,
483
+ } ,
484
+ _ => {
485
+ self . field_ty_span = Some ( span) ;
486
+ return ;
487
+ }
488
+ }
489
+ }
490
+ }
491
+ }
492
+ intravisit:: walk_ty ( self , t) ;
493
+ }
494
+ }
495
+
496
+ fn find_ty_alias_information (
441
497
tcx : TyCtxt < ' tcx > ,
442
498
field_def : & ty:: FieldDef ,
443
- ) -> ( Option < Span > , Option < Span > ) {
499
+ ) -> ( Option < Span > , Option < Span > , Option < Ident > , Option < Span > ) {
444
500
let field_def_def_id = field_def. did ;
445
501
if let Some ( field_def_local_id) = field_def_def_id. as_local ( ) {
446
502
let field_def_hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( field_def_local_id) ;
447
503
if let hir:: Node :: Field ( hir:: FieldDef {
448
504
span : field_def_span, ty : field_def_ty, ..
449
505
} ) = tcx. hir ( ) . get ( field_def_hir_id)
450
506
{
451
- if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( _, path) ) = field_def_ty. kind {
452
- if let Res :: Def ( DefKind :: TyAlias , ty_alias_def_id) = path. res {
453
- if let Some ( ty_alias_local_id) = ty_alias_def_id. as_local ( ) {
454
- let ty_alias_hir_id =
455
- tcx. hir ( ) . local_def_id_to_hir_id ( ty_alias_local_id) ;
456
- let node = tcx. hir ( ) . get ( ty_alias_hir_id) ;
457
- match node {
458
- hir:: Node :: Item ( hir:: Item {
459
- kind, span : ty_alias_span, ..
460
- } ) => match kind {
461
- hir:: ItemKind :: TyAlias ( _, _) => {
462
- return ( Some ( * field_def_span) , Some ( * ty_alias_span) ) ;
463
- }
464
- _ => bug ! ( "expected an item of kind TyAlias" ) ,
465
- } ,
466
- _ => return ( Some ( * field_def_span) , None ) ,
467
- }
468
- }
469
- }
470
- }
507
+ let mut type_alias_finder = TyAliasFinder :: new ( tcx) ;
508
+ type_alias_finder. visit_ty ( field_def_ty) ;
509
+
510
+ let ( field_ty_span, ty_alias_ident, ty_alias_span) =
511
+ type_alias_finder. get_collected_information ( ) ;
512
+ return ( Some ( * field_def_span) , field_ty_span, ty_alias_ident, ty_alias_span) ;
471
513
}
472
514
}
473
- ( None , None )
515
+ ( None , None , None , None )
474
516
}
475
517
476
518
debug ! ( "check_fields_of_opaque_types(adt_def: {:?}, span: {:?})" , adt_def, span) ;
@@ -484,59 +526,68 @@ fn check_fields_for_opaque_types(
484
526
debug ! ( "field_def: {:?}" , field_def) ;
485
527
486
528
let field_ty = field_def. ty ( tcx, substs) ;
487
- match field_ty. kind ( ) {
488
- ty:: Opaque ( ..) => {
489
- use ty:: AdtKind :: * ;
490
- let adt_kind = match adt_def. adt_kind ( ) {
491
- Struct => "struct" ,
492
- Enum => "enum" ,
493
- Union => "union" ,
494
- } ;
495
-
496
- let mut diag;
497
- match find_span_of_field_def_and_ty_alias ( tcx, field_def) {
498
- ( Some ( field_def_span) , Some ( ty_alias_span) ) => {
499
- diag = tcx. sess . struct_span_err (
500
- span,
501
- & format ! (
502
- "type alias impl traits are not allowed as field types in {}s" ,
503
- adt_kind
504
- ) ,
505
- ) ;
506
- diag. span_label (
507
- field_def_span,
508
- "this field contains a type alias impl trait" ,
509
- ) ;
510
- diag. span_label ( ty_alias_span, "type alias defined here" ) ;
511
- }
512
- ( Some ( field_def_span) , None ) => {
513
- diag = tcx. sess . struct_span_err (
514
- span,
515
- & format ! (
516
- "type alias impl traits are not allowed as field types in {}s" ,
517
- adt_kind
518
- ) ,
519
- ) ;
529
+ if field_ty. has_opaque_types ( ) {
530
+ use ty:: AdtKind :: * ;
531
+ let adt_kind = match adt_def. adt_kind ( ) {
532
+ Struct => "struct" ,
533
+ Enum => "enum" ,
534
+ Union => "union" ,
535
+ } ;
520
536
521
- diag. span_label (
522
- field_def_span,
523
- "this field contains a type alias impl trait" ,
524
- ) ;
525
- }
526
- _ => {
527
- diag = tcx. sess . struct_span_err (
528
- span,
529
- & format ! (
530
- "type alias impl traits are not allowed as field types in {}s" ,
531
- adt_kind
532
- ) ,
533
- ) ;
534
- }
537
+ let mut diag;
538
+ match find_ty_alias_information ( tcx, field_def) {
539
+ (
540
+ Some ( field_def_span) ,
541
+ Some ( field_ty_span) ,
542
+ Some ( ty_alias_ident) ,
543
+ Some ( ty_alias_span) ,
544
+ ) => {
545
+ diag = tcx. sess . struct_span_err (
546
+ span,
547
+ & format ! (
548
+ "type aliases of `impl Trait` are not allowed as field types in {}s" ,
549
+ adt_kind
550
+ ) ,
551
+ ) ;
552
+ let field_def_span_msg = format ! (
553
+ "this field contains a type alias `{}` of an `impl Trait`" ,
554
+ ty_alias_ident
555
+ ) ;
556
+
557
+ let field_ty_span_msg =
558
+ "this type is a type alias of an `impl Trait`" . to_string ( ) ;
559
+
560
+ diag. span_label ( field_def_span, field_def_span_msg) ;
561
+ diag. span_label ( field_ty_span, field_ty_span_msg) ;
562
+ diag. span_label ( ty_alias_span, "type alias defined here" ) ;
535
563
}
564
+ ( Some ( field_def_span) , Some ( field_ty_span) , None , None ) => {
565
+ diag = tcx. sess . struct_span_err (
566
+ span,
567
+ & format ! (
568
+ "type aliases of `impl Trait` are not allowed as field types in {}s" ,
569
+ adt_kind
570
+ ) ,
571
+ ) ;
536
572
537
- diag. emit ( ) ;
573
+ diag. span_label (
574
+ field_def_span,
575
+ "this field contains a type alias of an `impl trait`" ,
576
+ ) ;
577
+ diag. span_label ( field_ty_span, "this type is a type alias of an `impl trait`" ) ;
578
+ }
579
+ _ => {
580
+ diag = tcx. sess . struct_span_err (
581
+ span,
582
+ & format ! (
583
+ "type alias impl traits are not allowed as field types in {}s" ,
584
+ adt_kind
585
+ ) ,
586
+ ) ;
587
+ }
538
588
}
539
- _ => { }
589
+
590
+ diag. emit ( ) ;
540
591
}
541
592
} ) ;
542
593
}
0 commit comments