Reimplement variant downcast projection.
This commit is contained in:
parent
dd3d58f249
commit
9aa3a8675f
2 changed files with 27 additions and 14 deletions
|
@ -1,5 +1,6 @@
|
||||||
use rustc::middle::const_eval;
|
use rustc::middle::const_eval;
|
||||||
use rustc::middle::ty::{self, TyCtxt};
|
use rustc::middle::ty::{self, TyCtxt};
|
||||||
|
use rustc::middle::subst::Substs;
|
||||||
use rustc::mir::mir_map::MirMap;
|
use rustc::mir::mir_map::MirMap;
|
||||||
use rustc::mir::repr as mir;
|
use rustc::mir::repr as mir;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
@ -340,7 +341,12 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
||||||
Field(field, _) => match base_repr {
|
Field(field, _) => match base_repr {
|
||||||
Repr::Product { ref fields, .. } =>
|
Repr::Product { ref fields, .. } =>
|
||||||
base_ptr.offset(fields[field.index()].offset),
|
base_ptr.offset(fields[field.index()].offset),
|
||||||
_ => panic!("field access on non-product type"),
|
_ => panic!("field access on non-product type: {:?}", base_repr),
|
||||||
|
},
|
||||||
|
|
||||||
|
Downcast(_, variant) => match base_repr {
|
||||||
|
Repr::Sum { ref discr, .. } => base_ptr.offset(discr.size()),
|
||||||
|
_ => panic!("variant downcast on non-sum type"),
|
||||||
},
|
},
|
||||||
|
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
|
@ -350,8 +356,13 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
||||||
ref l => panic!("can't handle lvalue: {:?}", l),
|
ref l => panic!("can't handle lvalue: {:?}", l),
|
||||||
};
|
};
|
||||||
|
|
||||||
let ty = self.current_frame().mir.lvalue_ty(self.tcx, lvalue).to_ty(self.tcx);
|
use rustc::mir::tcx::LvalueTy;
|
||||||
Ok((ptr, self.ty_to_repr(ty)))
|
let repr = match self.current_frame().mir.lvalue_ty(self.tcx, lvalue) {
|
||||||
|
LvalueTy::Ty { ty } => self.ty_to_repr(ty),
|
||||||
|
LvalueTy::Downcast { ref adt_def, substs, variant_index } =>
|
||||||
|
self.make_variant_repr(&adt_def.variants[variant_index], substs),
|
||||||
|
};
|
||||||
|
Ok((ptr, repr))
|
||||||
|
|
||||||
// mir::Lvalue::Projection(ref proj) => {
|
// mir::Lvalue::Projection(ref proj) => {
|
||||||
// let base_ptr = self.lvalue_to_ptr(&proj.base);
|
// let base_ptr = self.lvalue_to_ptr(&proj.base);
|
||||||
|
@ -426,6 +437,11 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
||||||
Repr::Product { size: size, fields: fields }
|
Repr::Product { size: size, fields: fields }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_variant_repr(&self, v: ty::VariantDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Repr {
|
||||||
|
let field_tys = v.fields.iter().map(|f| f.ty(self.tcx, substs));
|
||||||
|
self.make_product_repr(field_tys)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(tsion): Cache these outputs.
|
// TODO(tsion): Cache these outputs.
|
||||||
fn ty_to_repr(&self, ty: ty::Ty<'tcx>) -> Repr {
|
fn ty_to_repr(&self, ty: ty::Ty<'tcx>) -> Repr {
|
||||||
use syntax::ast::IntTy;
|
use syntax::ast::IntTy;
|
||||||
|
@ -440,7 +456,7 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
||||||
|
|
||||||
ty::TyTuple(ref fields) => self.make_product_repr(fields.iter().cloned()),
|
ty::TyTuple(ref fields) => self.make_product_repr(fields.iter().cloned()),
|
||||||
|
|
||||||
ty::TyEnum(adt_def, ref subst) => {
|
ty::TyEnum(adt_def, substs) => {
|
||||||
let num_variants = adt_def.variants.len();
|
let num_variants = adt_def.variants.len();
|
||||||
|
|
||||||
let discr = if num_variants <= 1 {
|
let discr = if num_variants <= 1 {
|
||||||
|
@ -456,8 +472,7 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let variants: Vec<Repr> = adt_def.variants.iter().map(|v| {
|
let variants: Vec<Repr> = adt_def.variants.iter().map(|v| {
|
||||||
let field_tys = v.fields.iter().map(|f| f.ty(self.tcx, subst));
|
self.make_variant_repr(v, substs)
|
||||||
self.make_product_repr(field_tys)
|
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
Repr::Sum {
|
Repr::Sum {
|
||||||
|
@ -467,17 +482,15 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::TyStruct(adt_def, ref subst) => {
|
ty::TyStruct(adt_def, substs) => {
|
||||||
assert_eq!(adt_def.variants.len(), 1);
|
assert_eq!(adt_def.variants.len(), 1);
|
||||||
let field_tys = adt_def.variants[0].fields.iter().map(|f| f.ty(self.tcx, subst));
|
self.make_variant_repr(&adt_def.variants[0], substs)
|
||||||
self.make_product_repr(field_tys)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ref t => panic!("can't convert type to repr: {:?}", t),
|
ref t => panic!("can't convert type to repr: {:?}", t),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn current_frame(&self) -> &Frame<'a, 'tcx> {
|
fn current_frame(&self) -> &Frame<'a, 'tcx> {
|
||||||
self.stack.last().expect("no call frames exist")
|
self.stack.last().expect("no call frames exist")
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,10 +32,10 @@ fn return_some() -> Option<i64> {
|
||||||
|
|
||||||
#[miri_run]
|
#[miri_run]
|
||||||
fn match_opt_none() -> i8 {
|
fn match_opt_none() -> i8 {
|
||||||
let x = None::<i32>;
|
let x = None;
|
||||||
match x {
|
match x {
|
||||||
Some(_) => 10,
|
Some(data) => data,
|
||||||
None => 20,
|
None => 42,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ fn match_opt_none() -> i8 {
|
||||||
fn match_opt_some() -> i8 {
|
fn match_opt_some() -> i8 {
|
||||||
let x = Some(13);
|
let x = Some(13);
|
||||||
match x {
|
match x {
|
||||||
Some(_) => 10,
|
Some(data) => data,
|
||||||
None => 20,
|
None => 20,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue