@@ -317,9 +317,23 @@ impl<'a> Visitor<()> for CheckItemTypesVisitor<'a> {
317
317
}
318
318
}
319
319
320
+ struct CheckItemSizedTypesVisitor < ' a > { ccx : & ' a CrateCtxt < ' a > }
321
+
322
+ impl < ' a > Visitor < ( ) > for CheckItemSizedTypesVisitor < ' a > {
323
+ fn visit_item ( & mut self , i : & ast:: Item , _: ( ) ) {
324
+ check_item_sized ( self . ccx , i) ;
325
+ visit:: walk_item ( self , i, ( ) ) ;
326
+ }
327
+ }
328
+
320
329
pub fn check_item_types ( ccx : & CrateCtxt , krate : & ast:: Crate ) {
321
330
let mut visit = CheckItemTypesVisitor { ccx : ccx } ;
322
331
visit:: walk_crate ( & mut visit, krate, ( ) ) ;
332
+
333
+ ccx. tcx . sess . abort_if_errors ( ) ;
334
+
335
+ let mut visit = CheckItemSizedTypesVisitor { ccx : ccx } ;
336
+ visit:: walk_crate ( & mut visit, krate, ( ) ) ;
323
337
}
324
338
325
339
fn check_bare_fn ( ccx : & CrateCtxt ,
@@ -562,19 +576,19 @@ fn check_for_field_shadowing(tcx: &ty::ctxt,
562
576
}
563
577
564
578
fn check_fields_sized ( tcx : & ty:: ctxt ,
565
- id : ast:: NodeId ) {
566
- let struct_def = tcx . map . expect_struct ( id ) ;
567
- // FIXME(#13121) allow the last field to be DST
568
- for f in struct_def. fields . iter ( ) {
579
+ struct_def : @ ast:: StructDef ) {
580
+ let len = struct_def . fields . len ( ) ;
581
+ for i in range ( 0 , len ) {
582
+ let f = struct_def. fields . get ( i ) ;
569
583
let t = ty:: node_id_to_type ( tcx, f. node . id ) ;
570
- if !ty:: type_is_sized ( tcx, t) {
584
+ if !ty:: type_is_sized ( tcx, t) && i < ( len - 1 ) {
571
585
match f. node . kind {
572
586
ast:: NamedField ( ident, _) => {
573
- tcx. sess . span_err ( f. span , format ! ( "Dynamically sized type in field {}" ,
587
+ tcx. sess . span_err ( f. span , format ! ( "type of field {} is dynamically sized " ,
574
588
token:: get_ident( ident) ) ) ;
575
589
}
576
590
ast:: UnnamedField ( _) => {
577
- tcx. sess . span_err ( f. span , "Dynamically sized type in field" ) ;
591
+ tcx. sess . span_err ( f. span , "dynamically sized type in field" ) ;
578
592
}
579
593
}
580
594
}
@@ -584,14 +598,8 @@ fn check_fields_sized(tcx: &ty::ctxt,
584
598
pub fn check_struct ( ccx : & CrateCtxt , id : ast:: NodeId , span : Span ) {
585
599
let tcx = ccx. tcx ;
586
600
587
- // Check that the struct is representable
588
601
check_representable ( tcx, span, id, "struct" ) ;
589
-
590
- // Check that the struct is instantiable
591
- if check_instantiable ( tcx, span, id) {
592
- // This might cause stack overflow if id is not instantiable.
593
- check_fields_sized ( tcx, id) ;
594
- }
602
+ check_instantiable ( tcx, span, id) ;
595
603
596
604
// Check there are no overlapping fields in super-structs
597
605
check_for_field_shadowing ( tcx, local_def ( id) ) ;
@@ -601,6 +609,24 @@ pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
601
609
}
602
610
}
603
611
612
+ pub fn check_item_sized ( ccx : & CrateCtxt , it : & ast:: Item ) {
613
+ debug ! ( "check_item(it.id={}, it.ident={})" ,
614
+ it. id,
615
+ ty:: item_path_str( ccx. tcx, local_def( it. id) ) ) ;
616
+ let _indenter = indenter ( ) ;
617
+
618
+ match it. node {
619
+ ast:: ItemEnum ( ref enum_definition, _) => {
620
+ check_enum_variants_sized ( ccx,
621
+ enum_definition. variants . as_slice ( ) ) ;
622
+ }
623
+ ast:: ItemStruct ( ..) => {
624
+ check_fields_sized ( ccx. tcx , ccx. tcx . map . expect_struct ( it. id ) ) ;
625
+ }
626
+ _ => { }
627
+ }
628
+ }
629
+
604
630
pub fn check_item ( ccx : & CrateCtxt , it : & ast:: Item ) {
605
631
debug ! ( "check_item(it.id={}, it.ident={})" ,
606
632
it. id,
@@ -3459,7 +3485,7 @@ pub fn check_const_with_ty(fcx: &FnCtxt,
3459
3485
pub fn check_representable ( tcx : & ty:: ctxt ,
3460
3486
sp : Span ,
3461
3487
item_id : ast:: NodeId ,
3462
- designation : & str ) {
3488
+ designation : & str ) -> bool {
3463
3489
let rty = ty:: node_id_to_type ( tcx, item_id) ;
3464
3490
3465
3491
// Check that it is possible to represent this type. This call identifies
@@ -3473,9 +3499,11 @@ pub fn check_representable(tcx: &ty::ctxt,
3473
3499
sp, format ! ( "illegal recursive {} type; \
3474
3500
wrap the inner value in a box to make it representable",
3475
3501
designation) ) ;
3502
+ return false
3476
3503
}
3477
3504
ty:: Representable | ty:: ContainsRecursive => ( ) ,
3478
3505
}
3506
+ return true
3479
3507
}
3480
3508
3481
3509
/// Checks whether a type can be created without an instance of itself.
@@ -3532,6 +3560,29 @@ pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
3532
3560
}
3533
3561
}
3534
3562
3563
+ pub fn check_enum_variants_sized ( ccx : & CrateCtxt ,
3564
+ vs : & [ ast:: P < ast:: Variant > ] ) {
3565
+ for & v in vs. iter ( ) {
3566
+ match v. node . kind {
3567
+ ast:: TupleVariantKind ( ref args) if args. len ( ) > 0 => {
3568
+ let ctor_ty = ty:: node_id_to_type ( ccx. tcx , v. node . id ) ;
3569
+ let arg_tys: Vec < ty:: t > = ty:: ty_fn_args ( ctor_ty) . iter ( ) . map ( |a| * a) . collect ( ) ;
3570
+ for i in range ( 0 , args. len ( ) ) {
3571
+ let t = arg_tys. get ( i) ;
3572
+ // Allow the last field in an enum to be unsized.
3573
+ if !ty:: type_is_sized ( ccx. tcx , * t) && i < args. len ( ) -1 {
3574
+ ccx. tcx . sess . span_err ( args. get ( i) . ty . span ,
3575
+ format ! ( "type {} is dynamically sized" ,
3576
+ ppaux:: ty_to_str( ccx. tcx, * t) ) ) ;
3577
+ }
3578
+ }
3579
+ } ,
3580
+ ast:: StructVariantKind ( struct_def) => check_fields_sized ( ccx. tcx , struct_def) ,
3581
+ _ => { }
3582
+ }
3583
+ }
3584
+ }
3585
+
3535
3586
pub fn check_enum_variants ( ccx : & CrateCtxt ,
3536
3587
sp : Span ,
3537
3588
vs : & [ ast:: P < ast:: Variant > ] ,
@@ -3652,7 +3703,6 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
3652
3703
// cache so that ty::enum_variants won't repeat this work
3653
3704
ccx. tcx . enum_var_cache . borrow_mut ( ) . insert ( local_def ( id) , Rc :: new ( variants) ) ;
3654
3705
3655
- // Check that it is possible to represent this enum.
3656
3706
check_representable ( ccx. tcx , sp, id, "enum" ) ;
3657
3707
3658
3708
// Check that it is possible to instantiate this enum:
0 commit comments