about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-09-02 16:50:00 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-09-02 16:51:05 -0700
commitb808cfbb74a6d9ee01d22a1754f8ddfe3022b1e5 (patch)
treeac829ca2cb540660d7f39148415f3e66960e013d /src
parent49c9ac175f07505f2113feaca3546d4b8b44dfa8 (diff)
downloadrust-b808cfbb74a6d9ee01d22a1754f8ddfe3022b1e5.tar.gz
rust-b808cfbb74a6d9ee01d22a1754f8ddfe3022b1e5.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/rustc/middle/trans/base.rs5
-rw-r--r--src/rustc/middle/typeck/check/method.rs1
-rw-r--r--src/test/run-pass/autoderef-and-borrow-method-receiver.rs15
3 files changed, 20 insertions, 1 deletions
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() {
+}
+