@@ -706,6 +706,40 @@ fn check_fields_sized(tcx: &ty::ctxt,
706
706
}
707
707
}
708
708
709
+ // Checks that the type ty can possibly be made sized. That means there exists
710
+ // some set of type parameters such that ty::type_is_sized is true.
711
+ // For enums, ty may be either the type of the enum itself, or the constructor
712
+ // type for any of its variants.
713
+ fn check_ty_may_be_sized ( tcx : & ty:: ctxt ,
714
+ ty : ty:: t ) -> bool {
715
+ let t = sized_ty ( ty, tcx) ;
716
+ return ty:: type_is_sized ( tcx, t) ;
717
+
718
+ // Finds a type to be tested for sizedness for a given input type. This will
719
+ // replaces any type parameters with sized ones, if given an enum variant's
720
+ // constructor, will return the type for the enum itself.
721
+ fn sized_ty ( ty : ty:: t , tcx : & ty:: ctxt ) -> ty:: t {
722
+ // For a given set Substs, returns a new Substs where all actual type
723
+ // parameters are sized.
724
+ fn sized_substs ( substs : & subst:: Substs ) -> subst:: Substs {
725
+ let mut substs = substs. clone ( ) ;
726
+ let tys = Vec :: from_fn ( substs. types . get_slice ( subst:: TypeSpace ) . len ( ) ,
727
+ |_| ty:: mk_bot ( ) ) ;
728
+ substs. types . replace ( subst:: TypeSpace , tys) ;
729
+ substs
730
+ }
731
+
732
+ match ty:: get ( ty) . sty {
733
+ ty:: ty_enum( id, ref substs) => ty:: mk_enum ( tcx, id, sized_substs ( substs) ) ,
734
+ ty:: ty_struct( id, ref substs) => ty:: mk_struct ( tcx, id, sized_substs ( substs) ) ,
735
+ ty:: ty_bare_fn( ref f) => sized_ty ( f. sig . output , tcx) ,
736
+ _ => tcx. sess . bug ( format ! ( "Unexpected type: {} in check_ty_may_be_sized" ,
737
+ ppaux:: ty_to_string( tcx, ty) ) . as_slice ( ) )
738
+ }
739
+ }
740
+
741
+ }
742
+
709
743
pub fn check_struct ( ccx : & CrateCtxt , id : ast:: NodeId , span : Span ) {
710
744
let tcx = ccx. tcx ;
711
745
@@ -793,11 +827,19 @@ pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) {
793
827
794
828
match it. node {
795
829
ast:: ItemEnum ( ref enum_definition, _) => {
796
- check_enum_variants_sized ( ccx,
797
- enum_definition. variants . as_slice ( ) ) ;
830
+ if !check_enum_variants_sized ( ccx, enum_definition. variants . as_slice ( ) ) {
831
+ span_err ! ( ccx. tcx. sess, it. span, E0162 ,
832
+ "enum cannot be instantiated since it can never have a statically known size" ) ;
833
+ }
798
834
}
799
835
ast:: ItemStruct ( ..) => {
800
- check_fields_sized ( ccx. tcx , & * ccx. tcx . map . expect_struct ( it. id ) ) ;
836
+ check_fields_sized ( ccx. tcx , & * ccx. tcx . map . expect_struct ( it. id ) , ) ;
837
+
838
+ if !check_ty_may_be_sized ( ccx. tcx , ty:: node_id_to_type ( ccx. tcx , it. id ) ) {
839
+ span_err ! ( ccx. tcx. sess, it. span, E0163 ,
840
+ "struct cannot be instantiated since \
841
+ it can never have a statically known size") ;
842
+ }
801
843
}
802
844
_ => { }
803
845
}
@@ -4538,15 +4580,16 @@ pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4538
4580
4539
4581
4540
4582
pub fn check_enum_variants_sized ( ccx : & CrateCtxt ,
4541
- vs : & [ ast:: P < ast:: Variant > ] ) {
4583
+ vs : & [ ast:: P < ast:: Variant > ] ) -> bool {
4584
+ let mut sized_ok = true ;
4542
4585
for & v in vs. iter ( ) {
4543
4586
match v. node . kind {
4544
4587
ast:: TupleVariantKind ( ref args) if args. len ( ) > 0 => {
4545
4588
let ctor_ty = ty:: node_id_to_type ( ccx. tcx , v. node . id ) ;
4546
4589
let arg_tys: Vec < ty:: t > = ty:: ty_fn_args ( ctor_ty) . iter ( ) . map ( |a| * a) . collect ( ) ;
4547
4590
let len = arg_tys. len ( ) ;
4548
4591
if len == 0 {
4549
- return ;
4592
+ continue ;
4550
4593
}
4551
4594
for ( i, t) in arg_tys. slice_to ( len - 1 ) . iter ( ) . enumerate ( ) {
4552
4595
// Allow the last field in an enum to be unsized.
@@ -4560,11 +4603,19 @@ pub fn check_enum_variants_sized(ccx: &CrateCtxt,
4560
4603
ppaux:: ty_to_string( ccx. tcx, * t) ) ;
4561
4604
}
4562
4605
}
4606
+
4607
+ sized_ok = sized_ok && check_ty_may_be_sized ( ccx. tcx , ctor_ty) ;
4563
4608
} ,
4564
- ast:: StructVariantKind ( struct_def) => check_fields_sized ( ccx. tcx , & * struct_def) ,
4609
+ ast:: StructVariantKind ( struct_def) => {
4610
+ check_fields_sized ( ccx. tcx , & * struct_def) ;
4611
+ sized_ok = sized_ok && check_ty_may_be_sized ( ccx. tcx ,
4612
+ ty:: node_id_to_type ( ccx. tcx ,
4613
+ v. node . id ) )
4614
+ }
4565
4615
_ => { }
4566
4616
}
4567
4617
}
4618
+ sized_ok
4568
4619
}
4569
4620
4570
4621
pub fn check_enum_variants ( ccx : & CrateCtxt ,
0 commit comments