@@ -558,8 +558,7 @@ impl<'a, 'gcx, 'tcx> Struct {
558558 ( & Univariant { non_zero : true , .. } , & ty:: TyStruct ( def, substs) ) => {
559559 let fields = & def. struct_variant ( ) . fields ;
560560 assert_eq ! ( fields. len( ) , 1 ) ;
561- let ty = normalize_associated_type ( infcx, fields[ 0 ] . ty ( tcx, substs) ) ;
562- match * ty. layout ( infcx) ? {
561+ match * fields[ 0 ] . ty ( tcx, substs) . layout ( infcx) ? {
563562 // FIXME(eddyb) also allow floating-point types here.
564563 Scalar { value : Int ( _) , non_zero : false } |
565564 Scalar { value : Pointer , non_zero : false } => {
@@ -577,7 +576,7 @@ impl<'a, 'gcx, 'tcx> Struct {
577576 ( _, & ty:: TyStruct ( def, substs) ) => {
578577 Struct :: non_zero_field_path ( infcx, def. struct_variant ( ) . fields
579578 . iter ( ) . map ( |field| {
580- normalize_associated_type ( infcx , field. ty ( tcx, substs) )
579+ field. ty ( tcx, substs)
581580 } ) )
582581 }
583582
@@ -595,6 +594,14 @@ impl<'a, 'gcx, 'tcx> Struct {
595594 Struct :: non_zero_field_path ( infcx, Some ( ety) . into_iter ( ) )
596595 }
597596
597+ ( _, & ty:: TyProjection ( _) ) => {
598+ let normalized = normalize_associated_type ( infcx, ty) ;
599+ if ty == normalized {
600+ return Ok ( None ) ;
601+ }
602+ return Struct :: non_zero_field_in_type ( infcx, normalized) ;
603+ }
604+
598605 // Anything else is not a non-zero type.
599606 _ => Ok ( None )
600607 }
@@ -762,8 +769,9 @@ fn normalize_associated_type<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
762769impl < ' a , ' gcx , ' tcx > Layout {
763770 pub fn compute_uncached ( ty : Ty < ' gcx > ,
764771 infcx : & InferCtxt < ' a , ' gcx , ' tcx > )
765- -> Result < Layout , LayoutError < ' gcx > > {
772+ -> Result < & ' gcx Layout , LayoutError < ' gcx > > {
766773 let tcx = infcx. tcx . global_tcx ( ) ;
774+ let success = |layout| Ok ( tcx. intern_layout ( layout) ) ;
767775 let dl = & tcx. data_layout ;
768776 assert ! ( !ty. has_infer_types( ) ) ;
769777
@@ -795,6 +803,7 @@ impl<'a, 'gcx, 'tcx> Layout {
795803 if pointee. is_sized ( tcx, & infcx. parameter_environment , DUMMY_SP ) {
796804 Scalar { value : Pointer , non_zero : non_zero }
797805 } else {
806+ let pointee = normalize_associated_type ( infcx, pointee) ;
798807 let unsized_part = tcx. struct_tail ( pointee) ;
799808 let meta = match unsized_part. sty {
800809 ty:: TySlice ( _) | ty:: TyStr => {
@@ -860,7 +869,7 @@ impl<'a, 'gcx, 'tcx> Layout {
860869 let element = ty. simd_type ( tcx) ;
861870 match * element. layout ( infcx) ? {
862871 Scalar { value, .. } => {
863- return Ok ( Vector {
872+ return success ( Vector {
864873 element : value,
865874 count : ty. simd_size ( tcx) as u64
866875 } ) ;
@@ -873,8 +882,7 @@ impl<'a, 'gcx, 'tcx> Layout {
873882 }
874883 }
875884 let fields = def. struct_variant ( ) . fields . iter ( ) . map ( |field| {
876- normalize_associated_type ( infcx, field. ty ( tcx, substs) )
877- . layout ( infcx)
885+ field. ty ( tcx, substs) . layout ( infcx)
878886 } ) ;
879887 let packed = tcx. lookup_packed ( def. did ) ;
880888 let mut st = Struct :: new ( dl, packed) ;
@@ -914,7 +922,7 @@ impl<'a, 'gcx, 'tcx> Layout {
914922
915923 let mut st = Struct :: new ( dl, false ) ;
916924 st. extend ( dl, drop_flag. iter ( ) . map ( Ok ) , ty) ?;
917- return Ok ( Univariant { variant : st, non_zero : false } ) ;
925+ return success ( Univariant { variant : st, non_zero : false } ) ;
918926 }
919927
920928 if !dtor && def. variants . iter ( ) . all ( |v| v. fields . is_empty ( ) ) {
@@ -927,7 +935,7 @@ impl<'a, 'gcx, 'tcx> Layout {
927935 }
928936
929937 let ( discr, signed) = Integer :: repr_discr ( tcx, hint, min, max) ;
930- return Ok ( CEnum {
938+ return success ( CEnum {
931939 discr : discr,
932940 signed : signed,
933941 min : min as u64 ,
@@ -950,19 +958,16 @@ impl<'a, 'gcx, 'tcx> Layout {
950958 // (Typechecking will reject discriminant-sizing attrs.)
951959 assert_eq ! ( hint, attr:: ReprAny ) ;
952960 let fields = def. variants [ 0 ] . fields . iter ( ) . map ( |field| {
953- normalize_associated_type ( infcx, field. ty ( tcx, substs) )
954- . layout ( infcx)
961+ field. ty ( tcx, substs) . layout ( infcx)
955962 } ) ;
956963 let mut st = Struct :: new ( dl, false ) ;
957964 st. extend ( dl, fields. chain ( drop_flag. iter ( ) . map ( Ok ) ) , ty) ?;
958- return Ok ( Univariant { variant : st, non_zero : false } ) ;
965+ return success ( Univariant { variant : st, non_zero : false } ) ;
959966 }
960967
961968 // Cache the substituted and normalized variant field types.
962969 let variants = def. variants . iter ( ) . map ( |v| {
963- v. fields . iter ( ) . map ( |field| {
964- normalize_associated_type ( infcx, field. ty ( tcx, substs) )
965- } ) . collect :: < Vec < _ > > ( )
970+ v. fields . iter ( ) . map ( |field| field. ty ( tcx, substs) ) . collect :: < Vec < _ > > ( )
966971 } ) . collect :: < Vec < _ > > ( ) ;
967972
968973 if !dtor && variants. len ( ) == 2 && hint == attr:: ReprAny {
@@ -982,7 +987,7 @@ impl<'a, 'gcx, 'tcx> Layout {
982987 if path == & [ 0 ] && variants[ discr] . len ( ) == 1 {
983988 match * variants[ discr] [ 0 ] . layout ( infcx) ? {
984989 Scalar { value, .. } => {
985- return Ok ( RawNullablePointer {
990+ return success ( RawNullablePointer {
986991 nndiscr : discr as u64 ,
987992 value : value
988993 } ) ;
@@ -998,10 +1003,8 @@ impl<'a, 'gcx, 'tcx> Layout {
9981003 path. push ( 0 ) ; // For GEP through a pointer.
9991004 path. reverse ( ) ;
10001005 let mut st = Struct :: new ( dl, false ) ;
1001- st. extend ( dl, variants[ discr] . iter ( ) . map ( |ty| {
1002- ty. layout ( infcx)
1003- } ) , ty) ?;
1004- return Ok ( StructWrappedNullablePointer {
1006+ st. extend ( dl, variants[ discr] . iter ( ) . map ( |ty| ty. layout ( infcx) ) , ty) ?;
1007+ return success ( StructWrappedNullablePointer {
10051008 nndiscr : discr as u64 ,
10061009 nonnull : st,
10071010 discrfield : path
@@ -1105,15 +1108,22 @@ impl<'a, 'gcx, 'tcx> Layout {
11051108 }
11061109
11071110 // Types with no meaningful known layout.
1108- ty:: TyProjection ( _) | ty:: TyParam ( _) => {
1111+ ty:: TyProjection ( _) => {
1112+ let normalized = normalize_associated_type ( infcx, ty) ;
1113+ if ty == normalized {
1114+ return Err ( LayoutError :: Unknown ( ty) ) ;
1115+ }
1116+ return normalized. layout ( infcx) ;
1117+ }
1118+ ty:: TyParam ( _) => {
11091119 return Err ( LayoutError :: Unknown ( ty) ) ;
11101120 }
11111121 ty:: TyInfer ( _) | ty:: TyError => {
11121122 bug ! ( "Layout::compute: unexpected type `{}`" , ty)
11131123 }
11141124 } ;
11151125
1116- Ok ( layout)
1126+ success ( layout)
11171127 }
11181128
11191129 /// Returns true if the layout corresponds to an unsized type.
@@ -1272,8 +1282,7 @@ impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> {
12721282 // Get a zero-sized variant or a pointer newtype.
12731283 let zero_or_ptr_variant = |i : usize | {
12741284 let fields = def. variants [ i] . fields . iter ( ) . map ( |field| {
1275- let ty = normalize_associated_type ( infcx, & field. ty ( tcx, substs) ) ;
1276- SizeSkeleton :: compute ( ty, infcx)
1285+ SizeSkeleton :: compute ( field. ty ( tcx, substs) , infcx)
12771286 } ) ;
12781287 let mut ptr = None ;
12791288 for field in fields {
@@ -1323,6 +1332,15 @@ impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> {
13231332 }
13241333 }
13251334
1335+ ty:: TyProjection ( _) => {
1336+ let normalized = normalize_associated_type ( infcx, ty) ;
1337+ if ty == normalized {
1338+ Err ( err)
1339+ } else {
1340+ SizeSkeleton :: compute ( normalized, infcx)
1341+ }
1342+ }
1343+
13261344 _ => Err ( err)
13271345 }
13281346 }
0 commit comments