@@ -9,7 +9,7 @@ use rustc_hir as hir;
9
9
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
10
10
use rustc_hir:: intravisit:: Visitor ;
11
11
use rustc_hir:: lang_items:: LangItem ;
12
- use rustc_hir:: { def:: Res , ItemKind , Node , PathSegment } ;
12
+ use rustc_hir:: { def:: DefKind , def :: Res , ItemKind , Node , PathSegment } ;
13
13
use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
14
14
use rustc_infer:: infer:: { RegionVariableOrigin , TyCtxtInferExt } ;
15
15
use rustc_middle:: ty:: fold:: TypeFoldable ;
@@ -414,7 +414,12 @@ pub(super) fn check_fn<'a, 'tcx>(
414
414
}
415
415
416
416
fn check_struct ( tcx : TyCtxt < ' _ > , def_id : LocalDefId , span : Span ) {
417
+ debug ! ( "check_struct(def_id: {:?}, span: {:?})" , def_id, span) ;
418
+
417
419
let def = tcx. adt_def ( def_id) ;
420
+
421
+ check_fields_for_opaque_types ( tcx, def, def_id, span) ;
422
+
418
423
def. destructor ( tcx) ; // force the destructor to be evaluated
419
424
check_representable ( tcx, span, def_id) ;
420
425
@@ -426,8 +431,119 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) {
426
431
check_packed ( tcx, span, def) ;
427
432
}
428
433
434
+ fn check_fields_for_opaque_types (
435
+ tcx : TyCtxt < ' tcx > ,
436
+ adt_def : & ty:: AdtDef ,
437
+ def_id : LocalDefId ,
438
+ span : Span ,
439
+ ) {
440
+ fn find_span_of_field_def_and_ty_alias (
441
+ tcx : TyCtxt < ' tcx > ,
442
+ field_def : & ty:: FieldDef ,
443
+ ) -> ( Option < Span > , Option < Span > ) {
444
+ let field_def_def_id = field_def. did ;
445
+ if let Some ( field_def_local_id) = field_def_def_id. as_local ( ) {
446
+ let field_def_hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( field_def_local_id) ;
447
+ if let hir:: Node :: Field ( hir:: FieldDef {
448
+ span : field_def_span, ty : field_def_ty, ..
449
+ } ) = tcx. hir ( ) . get ( field_def_hir_id)
450
+ {
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
+ }
471
+ }
472
+ }
473
+ ( None , None )
474
+ }
475
+
476
+ debug ! ( "check_fields_of_opaque_types(adt_def: {:?}, span: {:?})" , adt_def, span) ;
477
+
478
+ let item_type = tcx. type_of ( def_id) ;
479
+ let substs = match item_type. kind ( ) {
480
+ ty:: Adt ( _, substs) => substs,
481
+ _ => bug ! ( "check_fields_for_opaque_types should only be called on Adts" ) ,
482
+ } ;
483
+ adt_def. all_fields ( ) . for_each ( |field_def| {
484
+ debug ! ( "field_def: {:?}" , field_def) ;
485
+
486
+ 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
+ ) ;
520
+
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
+ }
535
+ }
536
+
537
+ diag. emit ( ) ;
538
+ }
539
+ _ => { }
540
+ }
541
+ } ) ;
542
+ }
543
+
429
544
fn check_union ( tcx : TyCtxt < ' _ > , def_id : LocalDefId , span : Span ) {
430
545
let def = tcx. adt_def ( def_id) ;
546
+ check_fields_for_opaque_types ( tcx, def, def_id, span) ;
431
547
def. destructor ( tcx) ; // force the destructor to be evaluated
432
548
check_representable ( tcx, span, def_id) ;
433
549
check_transparent ( tcx, span, def) ;
@@ -1408,6 +1524,7 @@ fn check_enum<'tcx>(
1408
1524
def_id : LocalDefId ,
1409
1525
) {
1410
1526
let def = tcx. adt_def ( def_id) ;
1527
+ check_fields_for_opaque_types ( tcx, def, def_id, sp) ;
1411
1528
def. destructor ( tcx) ; // force the destructor to be evaluated
1412
1529
1413
1530
if vs. is_empty ( ) {
0 commit comments