1
Fork 0

Be cautious of calling upvar_tys before mir

This commit is contained in:
Aman Arora 2020-11-07 01:04:27 -05:00 committed by Roxane
parent 5da2bf197d
commit e35e46c113
2 changed files with 136 additions and 110 deletions

View file

@ -2105,6 +2105,21 @@ where
}
fn field(this: TyAndLayout<'tcx>, cx: &C, i: usize) -> C::TyAndLayout {
enum TyMaybeWithLayout<C: LayoutOf> {
Ty(C::Ty),
TyAndLayout(C::TyAndLayout),
}
fn ty_and_layout_kind<
C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout: MaybeResult<TyAndLayout<'tcx>>>
+ HasTyCtxt<'tcx>
+ HasParamEnv<'tcx>,
>(
this: TyAndLayout<'tcx>,
cx: &C,
i: usize,
ty: C::Ty,
) -> TyMaybeWithLayout<C> {
let tcx = cx.tcx();
let tag_layout = |tag: &Scalar| -> C::TyAndLayout {
let layout = Layout::scalar(cx, tag.clone());
@ -2114,7 +2129,7 @@ where
}))
};
cx.layout_of(match *this.ty.kind() {
match *ty.kind() {
ty::Bool
| ty::Char
| ty::Int(_)
@ -2137,23 +2152,26 @@ where
// as the `Abi` or `FieldsShape` is checked by users.
if i == 0 {
let nil = tcx.mk_unit();
let ptr_ty = if this.ty.is_unsafe_ptr() {
let ptr_ty = if ty.is_unsafe_ptr() {
tcx.mk_mut_ptr(nil)
} else {
tcx.mk_mut_ref(tcx.lifetimes.re_static, nil)
};
return MaybeResult::from(cx.layout_of(ptr_ty).to_result().map(
|mut ptr_layout| {
ptr_layout.ty = this.ty;
return TyMaybeWithLayout::TyAndLayout(MaybeResult::from(
cx.layout_of(ptr_ty).to_result().map(|mut ptr_layout| {
ptr_layout.ty = ty;
ptr_layout
},
}),
));
}
match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
ty::Slice(_) | ty::Str => tcx.types.usize,
ty::Slice(_) | ty::Str => TyMaybeWithLayout::Ty(tcx.types.usize),
ty::Dynamic(_, _) => {
tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.usize, 3))
TyMaybeWithLayout::Ty(tcx.mk_imm_ref(
tcx.lifetimes.re_static,
tcx.mk_array(tcx.types.usize, 3),
))
/* FIXME: use actual fn pointers
Warning: naively computing the number of entries in the
vtable by counting the methods on the trait + methods on
@ -2173,39 +2191,45 @@ where
}
// Arrays and slices.
ty::Array(element, _) | ty::Slice(element) => element,
ty::Str => tcx.types.u8,
ty::Array(element, _) | ty::Slice(element) => TyMaybeWithLayout::Ty(element),
ty::Str => TyMaybeWithLayout::Ty(tcx.types.u8),
// Tuples, generators and closures.
ty::Closure(_, ref substs) => substs.as_closure().upvar_tys().nth(i).unwrap(),
ty::Closure(_, ref substs) => {
ty_and_layout_kind(this, cx, i, substs.as_closure().tupled_upvars_ty())
}
ty::Generator(def_id, ref substs, _) => match this.variants {
Variants::Single { index } => substs
Variants::Single { index } => TyMaybeWithLayout::Ty(
substs
.as_generator()
.state_tys(def_id, tcx)
.nth(index.as_usize())
.unwrap()
.nth(i)
.unwrap(),
),
Variants::Multiple { ref tag, tag_field, .. } => {
if i == tag_field {
return tag_layout(tag);
return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
}
substs.as_generator().prefix_tys().nth(i).unwrap()
TyMaybeWithLayout::Ty(substs.as_generator().prefix_tys().nth(i).unwrap())
}
},
ty::Tuple(tys) => tys[i].expect_ty(),
ty::Tuple(tys) => TyMaybeWithLayout::Ty(tys[i].expect_ty()),
// ADTs.
ty::Adt(def, substs) => {
match this.variants {
Variants::Single { index } => def.variants[index].fields[i].ty(tcx, substs),
Variants::Single { index } => {
TyMaybeWithLayout::Ty(def.variants[index].fields[i].ty(tcx, substs))
}
// Discriminant field for enums (where applicable).
Variants::Multiple { ref tag, .. } => {
assert_eq!(i, 0);
return tag_layout(tag);
return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
}
}
}
@ -2217,6 +2241,12 @@ where
| ty::Param(_)
| ty::Infer(_)
| ty::Error(_) => bug!("TyAndLayout::field_type: unexpected type `{}`", this.ty),
}
}
cx.layout_of(match ty_and_layout_kind(this, cx, i, this.ty) {
TyMaybeWithLayout::Ty(result) => result,
TyMaybeWithLayout::TyAndLayout(result) => return result,
})
}

View file

@ -94,16 +94,12 @@ where
_ if component.is_copy_modulo_regions(tcx.at(DUMMY_SP), self.param_env) => (),
ty::Closure(_, substs) => {
for upvar_ty in substs.as_closure().upvar_tys() {
queue_type(self, upvar_ty);
}
queue_type(self, substs.as_closure().tupled_upvars_ty());
}
ty::Generator(def_id, substs, _) => {
let substs = substs.as_generator();
for upvar_ty in substs.upvar_tys() {
queue_type(self, upvar_ty);
}
queue_type(self, substs.tupled_upvars_ty());
let witness = substs.witness();
let interior_tys = match witness.kind() {