From bbeb7216e0985b21c6288acd4f09de1bb0c250cc Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 23 Mar 2017 18:32:57 +0100 Subject: [PATCH] Thinify the fat pointer on virtual function calls --- src/lvalue.rs | 6 ++++++ src/terminator/mod.rs | 9 +++++++- tests/run-pass/issue-3794.rs | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 tests/run-pass/issue-3794.rs diff --git a/src/lvalue.rs b/src/lvalue.rs index 62855c04505..b78824ea5c9 100644 --- a/src/lvalue.rs +++ b/src/lvalue.rs @@ -200,6 +200,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { (Size::from_bytes(field * elem_size), false) } + FatPointer { .. } => { + let bytes = field_index as u64 * self.memory.pointer_size(); + let offset = Size::from_bytes(bytes); + (offset, false) + } + _ => bug!("field access on non-product type: {:?}", base_layout), }; diff --git a/src/terminator/mod.rs b/src/terminator/mod.rs index 060299983ed..03804ccd0bd 100644 --- a/src/terminator/mod.rs +++ b/src/terminator/mod.rs @@ -337,11 +337,18 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let (_, vtable) = self.eval_operand(&arg_operands[0])?.expect_ptr_vtable_pair(&self.memory)?; let fn_ptr = self.memory.read_ptr(vtable.offset(ptr_size * (idx as u64 + 3)))?; let instance = self.memory.get_fn(fn_ptr.alloc_id)?; + let mut arg_operands = arg_operands.to_vec(); + let ty = self.operand_ty(&arg_operands[0]); + let ty = self.get_field_ty(ty, 0)?; + match arg_operands[0] { + mir::Operand::Consume(ref mut lval) => *lval = lval.clone().field(mir::Field::new(0), ty), + _ => bug!("virtual call first arg cannot be a constant"), + } // recurse with concrete function self.eval_fn_call( instance, destination, - arg_operands, + &arg_operands, span, sig, ) diff --git a/tests/run-pass/issue-3794.rs b/tests/run-pass/issue-3794.rs new file mode 100644 index 00000000000..badb833ee80 --- /dev/null +++ b/tests/run-pass/issue-3794.rs @@ -0,0 +1,41 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(box_syntax)] + +trait T { + fn print(&self); +} + +#[derive(Debug)] +struct S { + s: isize, +} + +impl T for S { + fn print(&self) { + println!("{:?}", self); + } +} + +fn print_t(t: &T) { + t.print(); +} + +fn print_s(s: &S) { + s.print(); +} + +pub fn main() { + let s: Box = box S { s: 5 }; + print_s(&*s); + let t: Box = s as Box; + print_t(&*t); +}