auto merge of #16253 : luqmana/rust/muv, r=nikomatsakis

Fixes #11958.
This commit is contained in:
bors 2014-08-09 11:36:22 +00:00
commit 1712ab2300
5 changed files with 91 additions and 28 deletions

View File

@ -764,18 +764,17 @@ impl<'a> CheckLoanCtxt<'a> {
return;
fn mark_variable_as_used_mut(this: &CheckLoanCtxt,
cmt: mc::cmt) {
mut cmt: mc::cmt) {
//! If the mutability of the `cmt` being written is inherited
//! from a local variable, liveness will
//! not have been able to detect that this variable's mutability
//! is important, so we must add the variable to the
//! `used_mut_nodes` table here.
let mut cmt = cmt;
loop {
debug!("mark_writes_through_upvars_as_used_mut(cmt={})",
cmt.repr(this.tcx()));
debug!("mark_variable_as_used_mut(cmt={})", cmt.repr(this.tcx()));
match cmt.cat.clone() {
mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: id, .. }) |
mc::cat_local(id) | mc::cat_arg(id) => {
this.tcx().used_mut_nodes.borrow_mut().insert(id);
return;
@ -792,7 +791,6 @@ impl<'a> CheckLoanCtxt<'a> {
mc::cat_rvalue(..) |
mc::cat_static_item |
mc::cat_copied_upvar(..) |
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
mc::cat_deref(_, _, mc::Implicit(..)) => {

View File

@ -306,6 +306,29 @@ impl MutabilityCategory {
}
}
fn from_def(def: &def::Def) -> MutabilityCategory {
match *def {
def::DefFn(..) | def::DefStaticMethod(..) | def::DefSelfTy(..) |
def::DefMod(..) | def::DefForeignMod(..) | def::DefVariant(..) |
def::DefTy(..) | def::DefTrait(..) | def::DefPrimTy(..) |
def::DefTyParam(..) | def::DefUse(..) | def::DefStruct(..) |
def::DefTyParamBinder(..) | def::DefRegion(..) | def::DefLabel(..) |
def::DefMethod(..) => fail!("no MutabilityCategory for def: {}", *def),
def::DefStatic(_, false) => McImmutable,
def::DefStatic(_, true) => McDeclared,
def::DefArg(_, binding_mode) |
def::DefBinding(_, binding_mode) |
def::DefLocal(_, binding_mode) => match binding_mode {
ast::BindByValue(ast::MutMutable) => McDeclared,
_ => McImmutable
},
def::DefUpvar(_, def, _, _) => MutabilityCategory::from_def(&*def)
}
}
pub fn inherit(&self) -> MutabilityCategory {
match *self {
McImmutable => McImmutable,
@ -503,8 +526,8 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
def::DefStaticMethod(..) => {
Ok(self.cat_rvalue_node(id, span, expr_ty))
}
def::DefMod(_) | def::DefForeignMod(_) | def::DefStatic(_, false) |
def::DefUse(_) | def::DefTrait(_) | def::DefTy(_) | def::DefPrimTy(_) |
def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
def::DefTrait(_) | def::DefTy(_) | def::DefPrimTy(_) |
def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) |
def::DefLabel(_) | def::DefSelfTy(..) | def::DefMethod(..) => {
Ok(Rc::new(cmt_ {
@ -516,30 +539,25 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
}))
}
def::DefStatic(_, true) => {
def::DefStatic(_, _) => {
Ok(Rc::new(cmt_ {
id:id,
span:span,
cat:cat_static_item,
mutbl: McDeclared,
mutbl: MutabilityCategory::from_def(&def),
ty:expr_ty
}))
}
def::DefArg(vid, binding_mode) => {
def::DefArg(vid, _) => {
// Idea: make this could be rewritten to model by-ref
// stuff as `&const` and `&mut`?
// m: mutability of the argument
let m = match binding_mode {
ast::BindByValue(ast::MutMutable) => McDeclared,
_ => McImmutable
};
Ok(Rc::new(cmt_ {
id: id,
span: span,
cat: cat_arg(vid),
mutbl: m,
mutbl: MutabilityCategory::from_def(&def),
ty:expr_ty
}))
}
@ -564,7 +582,6 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
if var_is_refd {
self.cat_upvar(id, span, var_id, fn_node_id)
} else {
// FIXME #2152 allow mutation of moved upvars
Ok(Rc::new(cmt_ {
id:id,
span:span,
@ -573,13 +590,12 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
onceness: closure_ty.onceness,
capturing_proc: fn_node_id,
}),
mutbl:McImmutable,
mutbl: MutabilityCategory::from_def(&def),
ty:expr_ty
}))
}
}
ty::ty_unboxed_closure(_) => {
// FIXME #2152 allow mutation of moved upvars
Ok(Rc::new(cmt_ {
id: id,
span: span,
@ -588,7 +604,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
onceness: ast::Many,
capturing_proc: fn_node_id,
}),
mutbl: McImmutable,
mutbl: MutabilityCategory::from_def(&def),
ty: expr_ty
}))
}
@ -602,19 +618,14 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
}
}
def::DefLocal(vid, binding_mode) |
def::DefBinding(vid, binding_mode) => {
def::DefLocal(vid, _) |
def::DefBinding(vid, _) => {
// by-value/by-ref bindings are local variables
let m = match binding_mode {
ast::BindByValue(ast::MutMutable) => McDeclared,
_ => McImmutable
};
Ok(Rc::new(cmt_ {
id: id,
span: span,
cat: cat_local(vid),
mutbl: m,
mutbl: MutabilityCategory::from_def(&def),
ty: expr_ty
}))
}

View File

@ -0,0 +1,15 @@
// Copyright 2014 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
let x = 1i;
proc() { x = 2; };
//~^ ERROR: cannot assign to immutable captured outer variable in a proc `x`
}

View File

@ -0,0 +1,17 @@
// Copyright 2014 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![forbid(unused_mut)]
fn main() {
let mut x = 1i;
//~^ ERROR: variable does not need to be mutable
proc() { println!("{}", x); };
}

View File

@ -0,0 +1,22 @@
// Copyright 2014 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![forbid(warnings)]
// Pretty printing tests complain about `use std::predule::*`
#![allow(unused_imports)]
// We shouldn't need to rebind a moved upvar as mut if it's already
// marked as mut
pub fn main() {
let mut x = 1i;
proc() { x = 2; };
}