about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-11-27 14:12:33 -0800
committerPatrick Walton <pcwalton@mimiga.net>2012-11-28 11:01:14 -0800
commitca6970a65ebdc153d53e9b6c2ccb224ee705ac94 (patch)
tree883d7bd463736587a47d4d86a559180960521c1c
parent082a88e42cdefce78a8f1f869971bbabd74ebca2 (diff)
downloadrust-ca6970a65ebdc153d53e9b6c2ccb224ee705ac94.tar.gz
rust-ca6970a65ebdc153d53e9b6c2ccb224ee705ac94.zip
librustc: Make overloaded operators with explicit self translate correctly
-rw-r--r--src/librustc/middle/borrowck.rs10
-rw-r--r--src/librustc/middle/borrowck/check_loans.rs7
-rw-r--r--src/librustc/middle/mem_categorization.rs23
-rw-r--r--src/librustc/middle/trans/expr.rs2
-rw-r--r--src/test/run-pass/operator-overloading-explicit-self.rs16
5 files changed, 56 insertions, 2 deletions
diff --git a/src/librustc/middle/borrowck.rs b/src/librustc/middle/borrowck.rs
index 25e184c2c02..5745d2e84bf 100644
--- a/src/librustc/middle/borrowck.rs
+++ b/src/librustc/middle/borrowck.rs
@@ -513,6 +513,16 @@ impl borrowck_ctxt {
         cat_expr(self.tcx, self.method_map, expr)
     }
 
+    fn cat_expr_unadjusted(expr: @ast::expr) -> cmt {
+        cat_expr_unadjusted(self.tcx, self.method_map, expr)
+    }
+
+    fn cat_expr_autoderefd(expr: @ast::expr,
+                           adj: @ty::AutoAdjustment)
+                        -> cmt {
+        cat_expr_autoderefd(self.tcx, self.method_map, expr, adj)
+    }
+
     fn cat_def(id: ast::node_id,
                span: span,
                ty: ty::t,
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs
index 366dd7e7e85..03bd403bf46 100644
--- a/src/librustc/middle/borrowck/check_loans.rs
+++ b/src/librustc/middle/borrowck/check_loans.rs
@@ -362,7 +362,12 @@ impl check_loan_ctxt {
     }
 
     fn check_assignment(at: assignment_type, ex: @ast::expr) {
-        let cmt = self.bccx.cat_expr(ex);
+        // We don't use cat_expr() here because we don't want to treat
+        // auto-ref'd parameters in overloaded operators as rvalues.
+        let cmt = match self.bccx.tcx.adjustments.find(ex.id) {
+            None => self.bccx.cat_expr_unadjusted(ex),
+            Some(adj) => self.bccx.cat_expr_autoderefd(ex, adj)
+        };
 
         debug!("check_assignment(cmt=%s)",
                self.bccx.cmt_to_repr(cmt));
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index ebc06435c64..9eafec930f6 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -573,6 +573,29 @@ fn cat_expr(
     return mcx.cat_expr(expr);
 }
 
+fn cat_expr_unadjusted(
+    tcx: ty::ctxt,
+    method_map: typeck::method_map,
+    expr: @ast::expr) -> cmt {
+
+    let mcx = &mem_categorization_ctxt {
+        tcx: tcx, method_map: method_map
+    };
+    return mcx.cat_expr_unadjusted(expr);
+}
+
+fn cat_expr_autoderefd(
+    tcx: ty::ctxt,
+    method_map: typeck::method_map,
+    expr: @ast::expr,
+    adj: @ty::AutoAdjustment) -> cmt {
+
+    let mcx = &mem_categorization_ctxt {
+        tcx: tcx, method_map: method_map
+    };
+    return mcx.cat_expr_autoderefd(expr, adj);
+}
+
 fn cat_def(
     tcx: ty::ctxt,
     method_map: typeck::method_map,
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 2e4d95acdfb..4927d2773c1 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -1572,7 +1572,7 @@ fn trans_assign_op(bcx: block,
     debug!("trans_assign_op(expr=%s)", bcx.expr_to_str(expr));
 
     // Evaluate LHS (destination), which should be an lvalue
-    let dst_datum = unpack_datum!(bcx, trans_lvalue(bcx, dst));
+    let dst_datum = unpack_datum!(bcx, trans_lvalue_unadjusted(bcx, dst));
 
     // A user-defined operator method
     if bcx.ccx().maps.method_map.find(expr.id).is_some() {
diff --git a/src/test/run-pass/operator-overloading-explicit-self.rs b/src/test/run-pass/operator-overloading-explicit-self.rs
new file mode 100644
index 00000000000..3b198078cf8
--- /dev/null
+++ b/src/test/run-pass/operator-overloading-explicit-self.rs
@@ -0,0 +1,16 @@
+struct S {
+    x: int
+}
+
+impl S {
+    pure fn add(&self, other: &S) -> S {
+        S { x: self.x + other.x }
+    }
+}
+
+fn main() {
+    let mut s = S { x: 1 };
+    s += S { x: 2 };
+    assert s.x == 3;
+}
+