subtyping_projections
This commit is contained in:
parent
177091258c
commit
3148e6a993
28 changed files with 431 additions and 5 deletions
|
@ -665,6 +665,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
let mut op = self.local_to_op(self.frame(), mir_place.local, layout)?;
|
||||
// Using `try_fold` turned out to be bad for performance, hence the loop.
|
||||
for elem in mir_place.projection.iter() {
|
||||
if elem.is_subtype() {
|
||||
continue;
|
||||
}
|
||||
op = self.project(&op, elem)?
|
||||
}
|
||||
|
||||
|
|
|
@ -332,6 +332,7 @@ where
|
|||
self.project_constant_index(base, offset, min_length, from_end)?
|
||||
}
|
||||
Subslice { from, to, from_end } => self.project_subslice(base, from, to, from_end)?,
|
||||
Subtype(ty) => base.transmute(self.layout_of(ty)?, self)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -664,6 +664,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
| ProjectionElem::Downcast(..)
|
||||
| ProjectionElem::OpaqueCast(..)
|
||||
| ProjectionElem::Subslice { .. }
|
||||
| ProjectionElem::Subtype(..)
|
||||
| ProjectionElem::Field(..)
|
||||
| ProjectionElem::Index(_) => {}
|
||||
}
|
||||
|
|
|
@ -306,6 +306,7 @@ where
|
|||
ProjectionElem::Index(index) if in_local(index) => return true,
|
||||
|
||||
ProjectionElem::Deref
|
||||
| ProjectionElem::Subtype(_)
|
||||
| ProjectionElem::Field(_, _)
|
||||
| ProjectionElem::OpaqueCast(_)
|
||||
| ProjectionElem::ConstantIndex { .. }
|
||||
|
|
|
@ -357,7 +357,9 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||
return Err(Unpromotable);
|
||||
}
|
||||
|
||||
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {}
|
||||
ProjectionElem::ConstantIndex { .. }
|
||||
| ProjectionElem::Subtype(_)
|
||||
| ProjectionElem::Subslice { .. } => {}
|
||||
|
||||
ProjectionElem::Index(local) => {
|
||||
let mut promotable = false;
|
||||
|
|
|
@ -608,6 +608,29 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
|
||||
match operand {
|
||||
Operand::Copy(place) | Operand::Move(place) => {
|
||||
if let Some(stmt) = self.body.stmt_at(location).left() {
|
||||
match &stmt.kind {
|
||||
StatementKind::Assign(box (lval, rvalue)) => {
|
||||
let place_ty = place.ty(&self.body.local_decls, self.tcx).ty;
|
||||
let lval_ty = lval.ty(&self.body.local_decls, self.tcx).ty;
|
||||
|
||||
if !place.is_subtype()
|
||||
&& place_ty != lval_ty
|
||||
&& rvalue.ty(&self.body.local_decls, self.tcx) != lval_ty
|
||||
&& (rvalue.ty(&self.body.local_decls, self.tcx).is_closure()
|
||||
!= lval_ty.is_closure())
|
||||
{
|
||||
self.fail(location, format!("Subtyping is not allowed between types {place_ty:#?} and {lval_ty:#?}"))
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
// This check is somewhat expensive, so only run it when -Zvalidate-mir is passed.
|
||||
if self.tcx.sess.opts.unstable_opts.validate_mir
|
||||
&& self.mir_phase < MirPhase::Runtime(RuntimePhase::Initial)
|
||||
|
@ -1088,6 +1111,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
// LHS and RHS of the assignment must have the same type.
|
||||
let left_ty = dest.ty(&self.body.local_decls, self.tcx).ty;
|
||||
let right_ty = rvalue.ty(&self.body.local_decls, self.tcx);
|
||||
|
||||
if !self.mir_assign_valid_types(right_ty, left_ty) {
|
||||
self.fail(
|
||||
location,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue