correct used_mut annotations for args, inherited case
This commit is contained in:
parent
aa48a170d5
commit
7a0c1ea560
@ -260,11 +260,21 @@ pub impl<'self> CheckLoanCtxt<'self> {
|
||||
// and report an error otherwise.
|
||||
match cmt.mutbl {
|
||||
mc::McDeclared => {
|
||||
// OK
|
||||
// OK, but we have to mark arguments as requiring mut
|
||||
// if they are assigned (other cases are handled by liveness,
|
||||
// since we need to distinguish local variables assigned
|
||||
// once vs those assigned multiple times)
|
||||
match cmt.cat {
|
||||
mc::cat_self(*) |
|
||||
mc::cat_arg(*) => {
|
||||
mark_variable_as_used_mut(self, cmt);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
mc::McInherited => {
|
||||
// OK, but we may have to add an entry to `used_mut_nodes`
|
||||
mark_writes_through_upvars_as_used_mut(self, cmt);
|
||||
mark_variable_as_used_mut(self, cmt);
|
||||
}
|
||||
mc::McReadOnly | mc::McImmutable => {
|
||||
// Subtle: liveness guarantees that immutable local
|
||||
@ -289,33 +299,28 @@ pub impl<'self> CheckLoanCtxt<'self> {
|
||||
self, expr, cmt);
|
||||
}
|
||||
|
||||
fn mark_writes_through_upvars_as_used_mut(self: &CheckLoanCtxt,
|
||||
cmt: mc::cmt) {
|
||||
fn mark_variable_as_used_mut(self: &CheckLoanCtxt,
|
||||
cmt: mc::cmt) {
|
||||
//! If the mutability of the `cmt` being written is inherited
|
||||
//! from a local variable in another closure, liveness may
|
||||
//! 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. This is because liveness
|
||||
//! does not consider closures.
|
||||
//! `used_mut_nodes` table here.
|
||||
|
||||
let mut passed_upvar = false;
|
||||
let mut cmt = cmt;
|
||||
loop {
|
||||
debug!("mark_writes_through_upvars_as_used_mut(cmt=%s)",
|
||||
cmt.repr(self.tcx()));
|
||||
match cmt.cat {
|
||||
mc::cat_local(id) |
|
||||
mc::cat_arg(id, _) |
|
||||
mc::cat_arg(id) |
|
||||
mc::cat_self(id) => {
|
||||
if passed_upvar {
|
||||
self.tcx().used_mut_nodes.insert(id);
|
||||
}
|
||||
self.tcx().used_mut_nodes.insert(id);
|
||||
return;
|
||||
}
|
||||
|
||||
mc::cat_stack_upvar(b) => {
|
||||
cmt = b;
|
||||
passed_upvar = true;
|
||||
}
|
||||
|
||||
mc::cat_rvalue |
|
||||
@ -552,7 +557,7 @@ pub impl<'self> CheckLoanCtxt<'self> {
|
||||
match cmt.cat {
|
||||
// Rvalues, locals, and arguments can be moved:
|
||||
mc::cat_rvalue | mc::cat_local(_) |
|
||||
mc::cat_arg(_, ast::by_copy) | mc::cat_self(_) => {}
|
||||
mc::cat_arg(_) | mc::cat_self(_) => {}
|
||||
|
||||
// It seems strange to allow a move out of a static item,
|
||||
// but what happens in practice is that you have a
|
||||
|
@ -255,7 +255,7 @@ impl GuaranteeLifetimeContext {
|
||||
match cmt.guarantor().cat {
|
||||
mc::cat_local(id) |
|
||||
mc::cat_self(id) |
|
||||
mc::cat_arg(id, _) => {
|
||||
mc::cat_arg(id) => {
|
||||
self.bccx.moved_variables_set.contains(&id)
|
||||
}
|
||||
mc::cat_rvalue |
|
||||
@ -292,7 +292,7 @@ impl GuaranteeLifetimeContext {
|
||||
ty::re_static
|
||||
}
|
||||
mc::cat_local(local_id) |
|
||||
mc::cat_arg(local_id, _) |
|
||||
mc::cat_arg(local_id) |
|
||||
mc::cat_self(local_id) => {
|
||||
self.bccx.tcx.region_maps.encl_region(local_id)
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ use util::common::indenter;
|
||||
use util::ppaux::{Repr};
|
||||
|
||||
use core::hashmap::HashSet;
|
||||
use core::vec;
|
||||
use syntax::ast::{m_const, m_imm, m_mutbl};
|
||||
use syntax::ast;
|
||||
use syntax::ast_util::id_range;
|
||||
@ -169,20 +168,6 @@ fn gather_loans_in_expr(ex: @ast::expr,
|
||||
visit::visit_expr(ex, self, vt);
|
||||
}
|
||||
|
||||
ast::expr_call(f, ref args, _) => {
|
||||
let arg_tys = ty::ty_fn_args(ty::expr_ty(self.tcx(), f));
|
||||
self.guarantee_arguments(ex, *args, arg_tys);
|
||||
visit::visit_expr(ex, self, vt);
|
||||
}
|
||||
|
||||
ast::expr_method_call(_, _, _, ref args, _) => {
|
||||
let arg_tys = ty::ty_fn_args(ty::node_id_to_type(self.tcx(),
|
||||
ex.callee_id));
|
||||
self.guarantee_arguments(ex, *args, arg_tys);
|
||||
|
||||
visit::visit_expr(ex, self, vt);
|
||||
}
|
||||
|
||||
ast::expr_match(ex_v, ref arms) => {
|
||||
let cmt = self.bccx.cat_expr(ex_v);
|
||||
for arms.each |arm| {
|
||||
@ -271,30 +256,6 @@ pub impl GatherLoanCtxt {
|
||||
assert!(id == popped);
|
||||
}
|
||||
|
||||
fn guarantee_arguments(&mut self,
|
||||
call_expr: @ast::expr,
|
||||
args: &[@ast::expr],
|
||||
arg_tys: &[ty::arg]) {
|
||||
for vec::each2(args, arg_tys) |arg, arg_ty| {
|
||||
match ty::resolved_mode(self.tcx(), arg_ty.mode) {
|
||||
ast::by_ref => {
|
||||
self.guarantee_by_ref_argument(call_expr, *arg);
|
||||
}
|
||||
ast::by_copy => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn guarantee_by_ref_argument(&mut self,
|
||||
call_expr: @ast::expr,
|
||||
arg_expr: @ast::expr) {
|
||||
// FIXME(#5074) nested method calls
|
||||
let scope_r = ty::re_scope(call_expr.id);
|
||||
let arg_cmt = self.bccx.cat_expr(arg_expr);
|
||||
self.guarantee_valid(arg_expr.id, arg_expr.span,
|
||||
arg_cmt, m_imm, scope_r);
|
||||
}
|
||||
|
||||
fn guarantee_adjustments(&mut self,
|
||||
expr: @ast::expr,
|
||||
adjustment: &ty::AutoAdjustment) {
|
||||
|
@ -15,7 +15,6 @@ use middle::borrowck::*;
|
||||
use mc = middle::mem_categorization;
|
||||
use middle::ty;
|
||||
use syntax::ast::{m_const, m_imm, m_mutbl};
|
||||
use syntax::ast;
|
||||
use syntax::codemap::span;
|
||||
|
||||
pub enum RestrictionResult {
|
||||
@ -74,7 +73,7 @@ impl RestrictionsContext {
|
||||
}
|
||||
|
||||
mc::cat_local(local_id) |
|
||||
mc::cat_arg(local_id, ast::by_copy) |
|
||||
mc::cat_arg(local_id) |
|
||||
mc::cat_self(local_id) => {
|
||||
let lp = @LpVar(local_id);
|
||||
SafeIf(lp, ~[Restriction {loan_path: lp,
|
||||
@ -114,7 +113,6 @@ impl RestrictionsContext {
|
||||
mc::cat_copied_upvar(*) | // FIXME(#2152) allow mutation of upvars
|
||||
mc::cat_static_item(*) |
|
||||
mc::cat_implicit_self(*) |
|
||||
mc::cat_arg(_, ast::by_ref) |
|
||||
mc::cat_deref(_, _, mc::region_ptr(m_imm, _)) |
|
||||
mc::cat_deref(_, _, mc::gc_ptr(m_imm)) => {
|
||||
Safe
|
||||
|
@ -242,13 +242,12 @@ pub fn opt_loan_path(cmt: mc::cmt) -> Option<@LoanPath> {
|
||||
mc::cat_rvalue |
|
||||
mc::cat_static_item |
|
||||
mc::cat_copied_upvar(_) |
|
||||
mc::cat_implicit_self |
|
||||
mc::cat_arg(_, ast::by_ref) => {
|
||||
mc::cat_implicit_self => {
|
||||
None
|
||||
}
|
||||
|
||||
mc::cat_local(id) |
|
||||
mc::cat_arg(id, ast::by_copy) |
|
||||
mc::cat_arg(id) |
|
||||
mc::cat_self(id) => {
|
||||
Some(@LpVar(id))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user