@@ -576,15 +576,20 @@ fn check_for_field_shadowing(tcx: &ty::ctxt,
576
576
}
577
577
578
578
fn check_fields_sized ( tcx : & ty:: ctxt ,
579
- struct_def : @ ast:: StructDef ) {
579
+ struct_def : & ast:: StructDef ) {
580
580
let len = struct_def. fields . len ( ) ;
581
- for i in range ( 0 , len) {
582
- let f = struct_def. fields . get ( i) ;
581
+ if len == 0 {
582
+ return ;
583
+ }
584
+ for f in struct_def. fields . slice_to ( len - 1 ) . iter ( ) {
583
585
let t = ty:: node_id_to_type ( tcx, f. node . id ) ;
584
- if !ty:: type_is_sized ( tcx, t) && i < ( len - 1 ) {
586
+ if !ty:: type_is_sized ( tcx, t) {
585
587
match f. node . kind {
586
588
ast:: NamedField ( ident, _) => {
587
- tcx. sess . span_err ( f. span , format ! ( "type of field {} is dynamically sized" ,
589
+ tcx. sess . span_err ( f. span , format ! ( "type `{}` is dynamically sized. \
590
+ dynamically sized types may only \
591
+ appear as the type of the final \
592
+ field in a struct",
588
593
token:: get_ident( ident) ) ) ;
589
594
}
590
595
ast:: UnnamedField ( _) => {
@@ -3519,16 +3524,18 @@ pub fn check_representable(tcx: &ty::ctxt,
3519
3524
/// is representable, but not instantiable.
3520
3525
pub fn check_instantiable ( tcx : & ty:: ctxt ,
3521
3526
sp : Span ,
3522
- item_id : ast:: NodeId ) -> bool {
3527
+ item_id : ast:: NodeId )
3528
+ -> bool {
3523
3529
let item_ty = ty:: node_id_to_type ( tcx, item_id) ;
3524
3530
if !ty:: is_instantiable ( tcx, item_ty) {
3525
3531
tcx. sess . span_err ( sp, format ! ( "this type cannot be instantiated \
3526
3532
without an instance of itself; \
3527
3533
consider using `Option<{}>`",
3528
3534
ppaux:: ty_to_str( tcx, item_ty) ) ) ;
3529
- return false
3535
+ false
3536
+ } else {
3537
+ true
3530
3538
}
3531
- true
3532
3539
}
3533
3540
3534
3541
pub fn check_simd ( tcx : & ty:: ctxt , sp : Span , id : ast:: NodeId ) {
@@ -3567,12 +3574,20 @@ pub fn check_enum_variants_sized(ccx: &CrateCtxt,
3567
3574
ast:: TupleVariantKind ( ref args) if args. len ( ) > 0 => {
3568
3575
let ctor_ty = ty:: node_id_to_type ( ccx. tcx , v. node . id ) ;
3569
3576
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) ;
3577
+ let len = arg_tys. len ( ) ;
3578
+ if len == 0 {
3579
+ return ;
3580
+ }
3581
+ for ( i, t) in arg_tys. slice_to ( len - 1 ) . iter ( ) . enumerate ( ) {
3572
3582
// Allow the last field in an enum to be unsized.
3573
- if !ty:: type_is_sized ( ccx. tcx , * t) && i < args. len ( ) -1 {
3583
+ // We want to do this so that we can support smart pointers.
3584
+ // A struct value with an unsized final field is itself
3585
+ // unsized and we must track this in the type system.
3586
+ if !ty:: type_is_sized ( ccx. tcx , * t) {
3574
3587
ccx. tcx . sess . span_err ( args. get ( i) . ty . span ,
3575
- format ! ( "type {} is dynamically sized" ,
3588
+ format ! ( "type `{}` is dynamically sized. \
3589
+ dynamically sized types may only \
3590
+ appear as the final type in a variant",
3576
3591
ppaux:: ty_to_str( ccx. tcx, * t) ) ) ;
3577
3592
}
3578
3593
}
0 commit comments