mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
Be cautious of calling upvar_tys before mir
This commit is contained in:
parent
5da2bf197d
commit
e35e46c113
@ -2105,118 +2105,148 @@ where
|
||||
}
|
||||
|
||||
fn field(this: TyAndLayout<'tcx>, cx: &C, i: usize) -> C::TyAndLayout {
|
||||
let tcx = cx.tcx();
|
||||
let tag_layout = |tag: &Scalar| -> C::TyAndLayout {
|
||||
let layout = Layout::scalar(cx, tag.clone());
|
||||
MaybeResult::from(Ok(TyAndLayout {
|
||||
layout: tcx.intern_layout(layout),
|
||||
ty: tag.value.to_ty(tcx),
|
||||
}))
|
||||
};
|
||||
enum TyMaybeWithLayout<C: LayoutOf> {
|
||||
Ty(C::Ty),
|
||||
TyAndLayout(C::TyAndLayout),
|
||||
}
|
||||
|
||||
cx.layout_of(match *this.ty.kind() {
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
| ty::Int(_)
|
||||
| ty::Uint(_)
|
||||
| ty::Float(_)
|
||||
| ty::FnPtr(_)
|
||||
| ty::Never
|
||||
| ty::FnDef(..)
|
||||
| ty::GeneratorWitness(..)
|
||||
| ty::Foreign(..)
|
||||
| ty::Dynamic(..) => bug!("TyAndLayout::field_type({:?}): not applicable", this),
|
||||
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());
|
||||
MaybeResult::from(Ok(TyAndLayout {
|
||||
layout: tcx.intern_layout(layout),
|
||||
ty: tag.value.to_ty(tcx),
|
||||
}))
|
||||
};
|
||||
|
||||
// Potentially-fat pointers.
|
||||
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
|
||||
assert!(i < this.fields.count());
|
||||
match *ty.kind() {
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
| ty::Int(_)
|
||||
| ty::Uint(_)
|
||||
| ty::Float(_)
|
||||
| ty::FnPtr(_)
|
||||
| ty::Never
|
||||
| ty::FnDef(..)
|
||||
| ty::GeneratorWitness(..)
|
||||
| ty::Foreign(..)
|
||||
| ty::Dynamic(..) => bug!("TyAndLayout::field_type({:?}): not applicable", this),
|
||||
|
||||
// Reuse the fat `*T` type as its own thin pointer data field.
|
||||
// This provides information about, e.g., DST struct pointees
|
||||
// (which may have no non-DST form), and will work as long
|
||||
// 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() {
|
||||
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;
|
||||
ptr_layout
|
||||
},
|
||||
));
|
||||
}
|
||||
// Potentially-fat pointers.
|
||||
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
|
||||
assert!(i < this.fields.count());
|
||||
|
||||
match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
|
||||
ty::Slice(_) | ty::Str => tcx.types.usize,
|
||||
ty::Dynamic(_, _) => {
|
||||
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
|
||||
all parent traits does not work, because some methods can
|
||||
be not object safe and thus excluded from the vtable.
|
||||
Increase this counter if you tried to implement this but
|
||||
failed to do it without duplicating a lot of code from
|
||||
other places in the compiler: 2
|
||||
tcx.mk_tup(&[
|
||||
tcx.mk_array(tcx.types.usize, 3),
|
||||
tcx.mk_array(Option<fn()>),
|
||||
])
|
||||
*/
|
||||
// Reuse the fat `*T` type as its own thin pointer data field.
|
||||
// This provides information about, e.g., DST struct pointees
|
||||
// (which may have no non-DST form), and will work as long
|
||||
// as the `Abi` or `FieldsShape` is checked by users.
|
||||
if i == 0 {
|
||||
let nil = tcx.mk_unit();
|
||||
let ptr_ty = if ty.is_unsafe_ptr() {
|
||||
tcx.mk_mut_ptr(nil)
|
||||
} else {
|
||||
tcx.mk_mut_ref(tcx.lifetimes.re_static, nil)
|
||||
};
|
||||
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 => TyMaybeWithLayout::Ty(tcx.types.usize),
|
||||
ty::Dynamic(_, _) => {
|
||||
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
|
||||
all parent traits does not work, because some methods can
|
||||
be not object safe and thus excluded from the vtable.
|
||||
Increase this counter if you tried to implement this but
|
||||
failed to do it without duplicating a lot of code from
|
||||
other places in the compiler: 2
|
||||
tcx.mk_tup(&[
|
||||
tcx.mk_array(tcx.types.usize, 3),
|
||||
tcx.mk_array(Option<fn()>),
|
||||
])
|
||||
*/
|
||||
}
|
||||
_ => bug!("TyAndLayout::field_type({:?}): not applicable", this),
|
||||
}
|
||||
_ => bug!("TyAndLayout::field_type({:?}): not applicable", this),
|
||||
}
|
||||
|
||||
// Arrays and slices.
|
||||
ty::Array(element, _) | ty::Slice(element) => TyMaybeWithLayout::Ty(element),
|
||||
ty::Str => TyMaybeWithLayout::Ty(tcx.types.u8),
|
||||
|
||||
// Tuples, generators and closures.
|
||||
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 } => 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 TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
|
||||
}
|
||||
TyMaybeWithLayout::Ty(substs.as_generator().prefix_tys().nth(i).unwrap())
|
||||
}
|
||||
},
|
||||
|
||||
ty::Tuple(tys) => TyMaybeWithLayout::Ty(tys[i].expect_ty()),
|
||||
|
||||
// ADTs.
|
||||
ty::Adt(def, substs) => {
|
||||
match this.variants {
|
||||
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 TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ty::Projection(_)
|
||||
| ty::Bound(..)
|
||||
| ty::Placeholder(..)
|
||||
| ty::Opaque(..)
|
||||
| ty::Param(_)
|
||||
| ty::Infer(_)
|
||||
| ty::Error(_) => bug!("TyAndLayout::field_type: unexpected type `{}`", this.ty),
|
||||
}
|
||||
}
|
||||
|
||||
// Arrays and slices.
|
||||
ty::Array(element, _) | ty::Slice(element) => element,
|
||||
ty::Str => tcx.types.u8,
|
||||
|
||||
// Tuples, generators and closures.
|
||||
ty::Closure(_, ref substs) => substs.as_closure().upvar_tys().nth(i).unwrap(),
|
||||
|
||||
ty::Generator(def_id, ref substs, _) => match this.variants {
|
||||
Variants::Single { index } => 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);
|
||||
}
|
||||
substs.as_generator().prefix_tys().nth(i).unwrap()
|
||||
}
|
||||
},
|
||||
|
||||
ty::Tuple(tys) => tys[i].expect_ty(),
|
||||
|
||||
// ADTs.
|
||||
ty::Adt(def, substs) => {
|
||||
match this.variants {
|
||||
Variants::Single { index } => 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ty::Projection(_)
|
||||
| ty::Bound(..)
|
||||
| ty::Placeholder(..)
|
||||
| ty::Opaque(..)
|
||||
| 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,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user