Auto merge of #95576 - DrMeepster:box_erasure, r=oli-obk
Remove dereferencing of Box from codegen Through #94043, #94414, #94873, and #95328, I've been fixing issues caused by Box being treated like a pointer when it is not a pointer. However, these PRs just introduced special cases for Box. This PR removes those special cases and instead transforms a deref of Box into a deref of the pointer it contains. Hopefully, this is the end of the Box<T, A> ICEs.
This commit is contained in:
commit
a25b1315ee
18 changed files with 477 additions and 162 deletions
|
@ -313,6 +313,11 @@ where
|
|||
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
|
||||
let val = self.read_immediate(src)?;
|
||||
trace!("deref to {} on {:?}", val.layout.ty, *val);
|
||||
|
||||
if val.layout.ty.is_box() {
|
||||
bug!("dereferencing {:?}", val.layout.ty);
|
||||
}
|
||||
|
||||
let mplace = self.ref_to_mplace(&val)?;
|
||||
self.check_mplace_access(mplace, CheckInAllocMsg::DerefTest)?;
|
||||
Ok(mplace)
|
||||
|
|
|
@ -240,65 +240,79 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
context: PlaceContext,
|
||||
location: Location,
|
||||
) {
|
||||
if let ProjectionElem::Index(index) = elem {
|
||||
let index_ty = self.body.local_decls[index].ty;
|
||||
if index_ty != self.tcx.types.usize {
|
||||
self.fail(location, format!("bad index ({:?} != usize)", index_ty))
|
||||
match elem {
|
||||
ProjectionElem::Index(index) => {
|
||||
let index_ty = self.body.local_decls[index].ty;
|
||||
if index_ty != self.tcx.types.usize {
|
||||
self.fail(location, format!("bad index ({:?} != usize)", index_ty))
|
||||
}
|
||||
}
|
||||
}
|
||||
if let ProjectionElem::Field(f, ty) = elem {
|
||||
let parent = Place { local, projection: self.tcx.intern_place_elems(proj_base) };
|
||||
let parent_ty = parent.ty(&self.body.local_decls, self.tcx);
|
||||
let fail_out_of_bounds = |this: &Self, location| {
|
||||
this.fail(location, format!("Out of bounds field {:?} for {:?}", f, parent_ty));
|
||||
};
|
||||
let check_equal = |this: &Self, location, f_ty| {
|
||||
if !this.mir_assign_valid_types(ty, f_ty) {
|
||||
this.fail(
|
||||
ProjectionElem::Deref if self.mir_phase >= MirPhase::GeneratorsLowered => {
|
||||
let base_ty = Place::ty_from(local, proj_base, &self.body.local_decls, self.tcx).ty;
|
||||
|
||||
if base_ty.is_box() {
|
||||
self.fail(
|
||||
location,
|
||||
format!("{:?} dereferenced after ElaborateBoxDerefs", base_ty),
|
||||
)
|
||||
}
|
||||
}
|
||||
ProjectionElem::Field(f, ty) => {
|
||||
let parent = Place { local, projection: self.tcx.intern_place_elems(proj_base) };
|
||||
let parent_ty = parent.ty(&self.body.local_decls, self.tcx);
|
||||
let fail_out_of_bounds = |this: &Self, location| {
|
||||
this.fail(location, format!("Out of bounds field {:?} for {:?}", f, parent_ty));
|
||||
};
|
||||
let check_equal = |this: &Self, location, f_ty| {
|
||||
if !this.mir_assign_valid_types(ty, f_ty) {
|
||||
this.fail(
|
||||
location,
|
||||
format!(
|
||||
"Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is {:?}",
|
||||
parent, f, ty, f_ty
|
||||
)
|
||||
)
|
||||
}
|
||||
};
|
||||
match parent_ty.ty.kind() {
|
||||
ty::Tuple(fields) => {
|
||||
let Some(f_ty) = fields.get(f.as_usize()) else {
|
||||
fail_out_of_bounds(self, location);
|
||||
return;
|
||||
};
|
||||
check_equal(self, location, *f_ty);
|
||||
}
|
||||
ty::Adt(adt_def, substs) => {
|
||||
let var = parent_ty.variant_index.unwrap_or(VariantIdx::from_u32(0));
|
||||
let Some(field) = adt_def.variant(var).fields.get(f.as_usize()) else {
|
||||
fail_out_of_bounds(self, location);
|
||||
return;
|
||||
};
|
||||
check_equal(self, location, field.ty(self.tcx, substs));
|
||||
}
|
||||
ty::Closure(_, substs) => {
|
||||
let substs = substs.as_closure();
|
||||
let Some(f_ty) = substs.upvar_tys().nth(f.as_usize()) else {
|
||||
fail_out_of_bounds(self, location);
|
||||
return;
|
||||
};
|
||||
check_equal(self, location, f_ty);
|
||||
}
|
||||
ty::Generator(_, substs, _) => {
|
||||
let substs = substs.as_generator();
|
||||
let Some(f_ty) = substs.upvar_tys().nth(f.as_usize()) else {
|
||||
fail_out_of_bounds(self, location);
|
||||
return;
|
||||
};
|
||||
check_equal(self, location, f_ty);
|
||||
}
|
||||
_ => {
|
||||
self.fail(location, format!("{:?} does not have fields", parent_ty.ty));
|
||||
}
|
||||
};
|
||||
|
||||
match parent_ty.ty.kind() {
|
||||
ty::Tuple(fields) => {
|
||||
let Some(f_ty) = fields.get(f.as_usize()) else {
|
||||
fail_out_of_bounds(self, location);
|
||||
return;
|
||||
};
|
||||
check_equal(self, location, *f_ty);
|
||||
}
|
||||
ty::Adt(adt_def, substs) => {
|
||||
let var = parent_ty.variant_index.unwrap_or(VariantIdx::from_u32(0));
|
||||
let Some(field) = adt_def.variant(var).fields.get(f.as_usize()) else {
|
||||
fail_out_of_bounds(self, location);
|
||||
return;
|
||||
};
|
||||
check_equal(self, location, field.ty(self.tcx, substs));
|
||||
}
|
||||
ty::Closure(_, substs) => {
|
||||
let substs = substs.as_closure();
|
||||
let Some(f_ty) = substs.upvar_tys().nth(f.as_usize()) else {
|
||||
fail_out_of_bounds(self, location);
|
||||
return;
|
||||
};
|
||||
check_equal(self, location, f_ty);
|
||||
}
|
||||
ty::Generator(_, substs, _) => {
|
||||
let substs = substs.as_generator();
|
||||
let Some(f_ty) = substs.upvar_tys().nth(f.as_usize()) else {
|
||||
fail_out_of_bounds(self, location);
|
||||
return;
|
||||
};
|
||||
check_equal(self, location, f_ty);
|
||||
}
|
||||
_ => {
|
||||
self.fail(location, format!("{:?} does not have fields", parent_ty.ty));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
self.super_projection_elem(local, proj_base, elem, context, location);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue