提交 35a41775 编写于 作者: N Niko Matsakis

Extend aliasability check to uncover `& &mut &mut` and the like

上级 6b23d204
......@@ -391,15 +391,7 @@ fn check_for_aliasable_mutable_writes(this: &CheckLoanCtxt,
mc::cat_deref(b, _, mc::region_ptr(m_mutbl, _)) => {
// Statically prohibit writes to `&mut` when aliasable
match b.freely_aliasable() {
None => {}
Some(cause) => {
this.bccx.report_aliasability_violation(
expr.span,
MutabilityViolation,
cause);
}
}
check_for_aliasability_violation(this, expr, b);
}
mc::cat_deref(_, deref_count, mc::gc_ptr(ast::m_mutbl)) => {
......@@ -419,6 +411,52 @@ fn check_for_aliasable_mutable_writes(this: &CheckLoanCtxt,
return true; // no errors reported
}
fn check_for_aliasability_violation(this: &CheckLoanCtxt,
expr: @ast::expr,
cmt: mc::cmt) -> bool {
let mut cmt = cmt;
loop {
match cmt.cat {
mc::cat_deref(b, _, mc::region_ptr(m_mutbl, _)) |
mc::cat_downcast(b) |
mc::cat_stack_upvar(b) |
mc::cat_deref(b, _, mc::uniq_ptr) |
mc::cat_interior(b, _) |
mc::cat_discr(b, _) => {
// Aliasability depends on base cmt
cmt = b;
}
mc::cat_copied_upvar(_) |
mc::cat_rvalue(*) |
mc::cat_local(*) |
mc::cat_arg(_) |
mc::cat_self(*) |
mc::cat_deref(_, _, mc::unsafe_ptr(*)) |
mc::cat_static_item(*) |
mc::cat_implicit_self(*) |
mc::cat_deref(_, _, mc::gc_ptr(_)) |
mc::cat_deref(_, _, mc::region_ptr(m_const, _)) |
mc::cat_deref(_, _, mc::region_ptr(m_imm, _)) => {
// Aliasability is independent of base cmt
match cmt.freely_aliasable() {
None => {
return true;
}
Some(cause) => {
this.bccx.report_aliasability_violation(
expr.span,
MutabilityViolation,
cause);
return false;
}
}
}
}
}
}
fn check_for_assignment_to_restricted_or_frozen_location(
this: &CheckLoanCtxt,
expr: @ast::expr,
......
......@@ -1146,9 +1146,10 @@ pub fn is_freely_aliasable(&self) -> bool {
}
pub fn freely_aliasable(&self) -> Option<AliasableReason> {
//! True if this lvalue resides in an area that is
//! freely aliasable, meaning that rustc cannot track
//! the alias//es with precision.
/*!
* Returns `Some(_)` if this lvalue represents a freely aliasable
* pointer type.
*/
// Maybe non-obvious: copied upvars can only be considered
// non-aliasable in once closures, since any other kind can be
......@@ -1180,12 +1181,12 @@ pub fn freely_aliasable(&self) -> Option<AliasableReason> {
Some(AliasableBorrowed(m))
}
cat_downcast(b) |
cat_stack_upvar(b) |
cat_deref(b, _, uniq_ptr) |
cat_interior(b, _) |
cat_discr(b, _) => {
b.freely_aliasable()
cat_downcast(*) |
cat_stack_upvar(*) |
cat_deref(_, _, uniq_ptr) |
cat_interior(*) |
cat_discr(*) => {
None
}
}
}
......
// 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 <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.
// Test that assignments to an `&mut` pointer which is found in a
// borrowed (but otherwise non-aliasable) location is illegal.
struct S<'self> {
pointer: &'self mut int
}
fn a(s: &S) {
*s.pointer += 1; //~ ERROR cannot assign
}
fn b(s: &mut S) {
*s.pointer += 1;
}
fn c(s: & &mut S) {
*s.pointer += 1; //~ ERROR cannot assign
}
fn main() {}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册