Skip to content

Commit ab26dbb

Browse files
committed
rustc: always normalize projections in ty::layout regardless where they appear.
1 parent d1d16c9 commit ab26dbb

File tree

3 files changed

+65
-25
lines changed

3 files changed

+65
-25
lines changed

src/librustc/ty/layout.rs

+42-24
Original file line numberDiff line numberDiff line change
@@ -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>,
762769
impl<'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
}

src/librustc/ty/util.rs

-1
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,6 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
626626
}
627627

628628
let layout = Layout::compute_uncached(self, infcx)?;
629-
let layout = tcx.intern_layout(layout);
630629
if can_cache {
631630
tcx.layout_cache.borrow_mut().insert(self, layout);
632631
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(specialization)]
12+
13+
trait Specializable { type Output; }
14+
15+
impl<T> Specializable for T {
16+
default type Output = u16;
17+
}
18+
19+
fn main() {
20+
unsafe {
21+
std::mem::transmute::<u16, <() as Specializable>::Output>(0);
22+
}
23+
}

0 commit comments

Comments
 (0)