commit
1712ab2300
@ -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(..)) => {
|
||||
|
@ -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
|
||||
}))
|
||||
}
|
||||
|
15
src/test/compile-fail/cannot-mutate-captured-non-mut-var.rs
Normal file
15
src/test/compile-fail/cannot-mutate-captured-non-mut-var.rs
Normal 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`
|
||||
}
|
17
src/test/compile-fail/unused-mut-warning-captured-var.rs
Normal file
17
src/test/compile-fail/unused-mut-warning-captured-var.rs
Normal 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); };
|
||||
}
|
22
src/test/run-pass/issue-11958.rs
Normal file
22
src/test/run-pass/issue-11958.rs
Normal 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; };
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user