mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-26 06:35:27 +00:00
Extend aliasability check to uncover & &mut &mut
and the like
This commit is contained in:
parent
6b23d20452
commit
35a4177550
@ -391,15 +391,7 @@ impl<'self> CheckLoanCtxt<'self> {
|
||||
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 @@ impl<'self> CheckLoanCtxt<'self> {
|
||||
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 @@ impl cmt_ {
|
||||
}
|
||||
|
||||
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 @@ impl cmt_ {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
// 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() {}
|
Loading…
Reference in New Issue
Block a user