diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 2f24a8ceb2465..a41dfdade0f38 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -310,8 +310,8 @@ pub impl<'self> CheckLoanCtxt<'self> { // 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(&expr.id) { - None => self.bccx.cat_expr_unadjusted(expr), - Some(&adj) => self.bccx.cat_expr_autoderefd(expr, adj) + None => self.bccx.cat_expr_unadjusted(expr, false), + Some(&adj) => self.bccx.cat_expr_autoderefd(expr, adj, false) }; debug!("check_assignment(cmt=%s)", cmt.repr(self.tcx())); diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index 64d32d713d0da..3f294ffffce31 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -248,7 +248,14 @@ pub impl GatherLoanCtxt { let mcx = &mc::mem_categorization_ctxt { tcx: self.tcx(), method_map: self.bccx.method_map}; - let cmt = mcx.cat_expr_autoderefd(expr, autoderefs); + let mutbl = match *autoref { + ty::AutoPtr(_, m) => m, + ty::AutoBorrowVec(_, m) => m, + ty::AutoBorrowVecRef(_, m) => m, + ty::AutoUnsafe(m) => m, + _ => ast::m_imm + }; + let cmt = mcx.cat_expr_autoderefd(expr, autoderefs, mutbl == m_mutbl); debug!("after autoderef, cmt=%s", cmt.repr(self.tcx())); match *autoref { diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 0f01b2b1e418e..7a40b2c783252 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -424,23 +424,23 @@ pub impl BorrowckCtxt { mc::cat_expr(self.tcx, self.method_map, expr) } - fn cat_expr_unadjusted(&self, expr: @ast::expr) -> mc::cmt { - mc::cat_expr_unadjusted(self.tcx, self.method_map, expr) + fn cat_expr_unadjusted(&self, expr: @ast::expr, mutbl: bool) -> mc::cmt { + mc::cat_expr_unadjusted(self.tcx, self.method_map, expr, mutbl) } fn cat_expr_autoderefd(&self, expr: @ast::expr, - adj: @ty::AutoAdjustment) -> mc::cmt { + adj: @ty::AutoAdjustment, mutbl: bool) -> mc::cmt { match *adj { ty::AutoAddEnv(*) => { // no autoderefs - mc::cat_expr_unadjusted(self.tcx, self.method_map, expr) + mc::cat_expr_unadjusted(self.tcx, self.method_map, expr, mutbl) } ty::AutoDerefRef( ty::AutoDerefRef { autoderefs: autoderefs, _}) => { mc::cat_expr_autoderefd(self.tcx, self.method_map, expr, - autoderefs) + autoderefs, mutbl) } } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 95ed7fe8efcd5..b4351d353f50c 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -219,24 +219,26 @@ pub fn cat_expr(tcx: ty::ctxt, pub fn cat_expr_unadjusted(tcx: ty::ctxt, method_map: typeck::method_map, - expr: @ast::expr) + expr: @ast::expr, + mutbl: bool) -> cmt { let mcx = &mem_categorization_ctxt { tcx: tcx, method_map: method_map }; - return mcx.cat_expr_unadjusted(expr); + return mcx.cat_expr_unadjusted(expr, mutbl); } pub fn cat_expr_autoderefd( tcx: ty::ctxt, method_map: typeck::method_map, expr: @ast::expr, - autoderefs: uint) -> cmt + autoderefs: uint, + mutbl: bool) -> cmt { let mcx = &mem_categorization_ctxt { tcx: tcx, method_map: method_map }; - return mcx.cat_expr_autoderefd(expr, autoderefs); + return mcx.cat_expr_autoderefd(expr, autoderefs, mutbl); } pub fn cat_def( @@ -333,24 +335,31 @@ pub impl mem_categorization_ctxt { match self.tcx.adjustments.find(&expr.id) { None => { // No adjustments. - self.cat_expr_unadjusted(expr) + self.cat_expr_unadjusted(expr, false) } Some(&@ty::AutoAddEnv(*)) => { // Convert a bare fn to a closure by adding NULL env. // Result is an rvalue. let expr_ty = ty::expr_ty_adjusted(self.tcx, expr); - self.cat_rvalue(expr, expr_ty) + self.cat_rvalue(expr, expr_ty, false) } Some( &@ty::AutoDerefRef( ty::AutoDerefRef { - autoref: Some(_), _})) => { + autoref: Some(autoref), _})) => { // Equivalent to &*expr or something similar. // Result is an rvalue. let expr_ty = ty::expr_ty_adjusted(self.tcx, expr); - self.cat_rvalue(expr, expr_ty) + let mutbl = match autoref { + ty::AutoPtr(_, m) => m, + ty::AutoBorrowVec(_, m) => m, + ty::AutoBorrowVecRef(_, m) => m, + ty::AutoUnsafe(m) => m, + _ => ast::m_imm + }; + self.cat_rvalue(expr, expr_ty, mutbl == m_mutbl) } Some( @@ -358,22 +367,23 @@ pub impl mem_categorization_ctxt { ty::AutoDerefRef { autoref: None, autoderefs: autoderefs})) => { // Equivalent to *expr or something similar. - self.cat_expr_autoderefd(expr, autoderefs) + self.cat_expr_autoderefd(expr, autoderefs, false) } } } fn cat_expr_autoderefd(&self, expr: @ast::expr, - autoderefs: uint) -> cmt { - let mut cmt = self.cat_expr_unadjusted(expr); + autoderefs: uint, + mutbl: bool) -> cmt { + let mut cmt = self.cat_expr_unadjusted(expr, mutbl); for uint::range(1, autoderefs+1) |deref| { cmt = self.cat_deref(expr, cmt, deref); } return cmt; } - fn cat_expr_unadjusted(&self, expr: @ast::expr) -> cmt { + fn cat_expr_unadjusted(&self, expr: @ast::expr, mutbl: bool) -> cmt { debug!("cat_expr: id=%d expr=%s", expr.id, pprust::expr_to_str(expr, self.tcx.sess.intr())); @@ -381,7 +391,7 @@ pub impl mem_categorization_ctxt { match expr.node { ast::expr_unary(ast::deref, e_base) => { if self.method_map.contains_key(&expr.id) { - return self.cat_rvalue(expr, expr_ty); + return self.cat_rvalue(expr, expr_ty, mutbl); } let base_cmt = self.cat_expr(e_base); @@ -399,7 +409,7 @@ pub impl mem_categorization_ctxt { ast::expr_index(base, _) => { if self.method_map.contains_key(&expr.id) { - return self.cat_rvalue(expr, expr_ty); + return self.cat_rvalue(expr, expr_ty, mutbl); } let base_cmt = self.cat_expr(base); @@ -411,7 +421,7 @@ pub impl mem_categorization_ctxt { self.cat_def(expr.id, expr.span, expr_ty, def) } - ast::expr_paren(e) => self.cat_expr_unadjusted(e), + ast::expr_paren(e) => self.cat_expr_unadjusted(e, mutbl), ast::expr_addr_of(*) | ast::expr_call(*) | ast::expr_assign(*) | ast::expr_assign_op(*) | @@ -424,7 +434,7 @@ pub impl mem_categorization_ctxt { ast::expr_match(*) | ast::expr_lit(*) | ast::expr_break(*) | ast::expr_mac(*) | ast::expr_again(*) | ast::expr_struct(*) | ast::expr_repeat(*) | ast::expr_inline_asm(*) => { - return self.cat_rvalue(expr, expr_ty); + return self.cat_rvalue(expr, expr_ty, mutbl); } } } @@ -546,13 +556,13 @@ pub impl mem_categorization_ctxt { } } - fn cat_rvalue(&self, elt: N, expr_ty: ty::t) -> cmt { + fn cat_rvalue(&self, elt: N, expr_ty: ty::t, mutbl: bool) -> cmt { @cmt_ { - id:elt.id(), - span:elt.span(), - cat:cat_rvalue, - mutbl:McImmutable, - ty:expr_ty + id: elt.id(), + span: elt.span(), + cat: cat_rvalue, + mutbl: if mutbl { McDeclared } else { McImmutable }, + ty: expr_ty } } @@ -907,7 +917,7 @@ pub impl mem_categorization_ctxt { } for slice.each |&slice_pat| { let slice_ty = self.pat_ty(slice_pat); - let slice_cmt = self.cat_rvalue(pat, slice_ty); + let slice_cmt = self.cat_rvalue(pat, slice_ty, false); self.cat_pattern(slice_cmt, slice_pat, op); } for after.each |&after_pat| { diff --git a/src/libuv b/src/libuv index 97ac7c087a0ca..218ab86721eef 160000 --- a/src/libuv +++ b/src/libuv @@ -1 +1 @@ -Subproject commit 97ac7c087a0caf6b0f611b80e14f7fe3cb18bb27 +Subproject commit 218ab86721eefd7b7e97fa6d9f95a80a1fa8686c diff --git a/src/test/run-pass/rvalue-borrow-as-mut.rs b/src/test/run-pass/rvalue-borrow-as-mut.rs new file mode 100644 index 0000000000000..c195ee1f1e9d8 --- /dev/null +++ b/src/test/run-pass/rvalue-borrow-as-mut.rs @@ -0,0 +1,27 @@ +// 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. + +struct Foo { + x: int +} + +impl Foo { + fn bar(&mut self) { + self.x = 21; + } + fn baz(&self) { + + } +} + +pub fn main() { + Foo { x: 42 }.bar(); + Foo { x: 42 }.baz(); +}