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() { +} +