From b808cfbb74a6d9ee01d22a1754f8ddfe3022b1e5 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Sun, 2 Sep 2012 16:50:00 -0700 Subject: [PATCH] rustc: Don't translate the expression twice when adapting a borrowed method receiver. Closes #3357. Adds a test case. I had to stare at this one for a bit. --- src/rustc/middle/trans/base.rs | 5 ++++- src/rustc/middle/typeck/check/method.rs | 1 + .../autoderef-and-borrow-method-receiver.rs | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/autoderef-and-borrow-method-receiver.rs diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index cb49daa4814..49d626cce96 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -3151,6 +3151,9 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr, // routine consults this table and performs these adaptations. It returns a // new location for the borrowed result as well as a new type for the argument // that reflects the borrowed value and not the original. +// +// NB: "e" has already been translated; do not translate it again. If you do, +// this will cause problems with autoderef and method receivers (bug #3357). fn adapt_borrowed_value(lv: lval_result, e: @ast::expr, e_ty: ty::t) -> {lv: lval_result, @@ -3200,7 +3203,7 @@ fn adapt_borrowed_value(lv: lval_result, _ => { // Just take a reference. This is basically like trans_addr_of. - let mut {bcx, val, kind} = trans_temp_lval(bcx, e); + let mut {bcx, val, kind} = lv; let is_immediate = ty::type_is_immediate(e_ty); if (kind == lv_temporary && is_immediate) || kind == lv_owned_imm { val = do_spill(bcx, val, e_ty); diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs index 93bab0f84e5..b3dc032f0bf 100644 --- a/src/rustc/middle/typeck/check/method.rs +++ b/src/rustc/middle/typeck/check/method.rs @@ -183,6 +183,7 @@ struct lookup { match ty::deref(self.tcx(), self.self_ty, false) { None => break, Some(mt) => { + debug!("(checking method) ... autodereffing"); self.self_ty = mt.ty; self.derefs += 1u; } diff --git a/src/test/run-pass/autoderef-and-borrow-method-receiver.rs b/src/test/run-pass/autoderef-and-borrow-method-receiver.rs new file mode 100644 index 00000000000..d8cdb109b6d --- /dev/null +++ b/src/test/run-pass/autoderef-and-borrow-method-receiver.rs @@ -0,0 +1,15 @@ +struct Foo { + x: int; +} + +impl Foo { + fn f(&self) {} +} + +fn g(x: &mut Foo) { + x.f(); +} + +fn main() { +} +