From 9aa3a8675f115216f4e5d182128450e29a9600ce Mon Sep 17 00:00:00 2001 From: Scott Olson Date: Sun, 13 Mar 2016 07:23:48 -0600 Subject: [PATCH] Reimplement variant downcast projection. --- src/interpreter.rs | 33 +++++++++++++++++++++++---------- test/sums.rs | 8 ++++---- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/interpreter.rs b/src/interpreter.rs index 5f8d46dc952..bd7a497bd7f 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -1,5 +1,6 @@ use rustc::middle::const_eval; use rustc::middle::ty::{self, TyCtxt}; +use rustc::middle::subst::Substs; use rustc::mir::mir_map::MirMap; use rustc::mir::repr as mir; use std::error::Error; @@ -340,7 +341,12 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> { Field(field, _) => match base_repr { Repr::Product { ref fields, .. } => 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!(), @@ -350,8 +356,13 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> { ref l => panic!("can't handle lvalue: {:?}", l), }; - let ty = self.current_frame().mir.lvalue_ty(self.tcx, lvalue).to_ty(self.tcx); - Ok((ptr, self.ty_to_repr(ty))) + use rustc::mir::tcx::LvalueTy; + 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) => { // 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 } } + 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. fn ty_to_repr(&self, ty: ty::Ty<'tcx>) -> Repr { 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::TyEnum(adt_def, ref subst) => { + ty::TyEnum(adt_def, substs) => { let num_variants = adt_def.variants.len(); let discr = if num_variants <= 1 { @@ -456,8 +472,7 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> { }; let variants: Vec = adt_def.variants.iter().map(|v| { - let field_tys = v.fields.iter().map(|f| f.ty(self.tcx, subst)); - self.make_product_repr(field_tys) + self.make_variant_repr(v, substs) }).collect(); 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); - let field_tys = adt_def.variants[0].fields.iter().map(|f| f.ty(self.tcx, subst)); - self.make_product_repr(field_tys) + self.make_variant_repr(&adt_def.variants[0], substs) } ref t => panic!("can't convert type to repr: {:?}", t), } } - fn current_frame(&self) -> &Frame<'a, 'tcx> { self.stack.last().expect("no call frames exist") } diff --git a/test/sums.rs b/test/sums.rs index 328539acca9..c63d3e68045 100644 --- a/test/sums.rs +++ b/test/sums.rs @@ -32,10 +32,10 @@ fn return_some() -> Option { #[miri_run] fn match_opt_none() -> i8 { - let x = None::; + let x = None; match x { - Some(_) => 10, - None => 20, + Some(data) => data, + None => 42, } } @@ -43,7 +43,7 @@ fn match_opt_none() -> i8 { fn match_opt_some() -> i8 { let x = Some(13); match x { - Some(_) => 10, + Some(data) => data, None => 20, } }