Skip to content

Commit 35a4177

Browse files
committed
Extend aliasability check to uncover & &mut &mut and the like
1 parent 6b23d20 commit 35a4177

File tree

3 files changed

+87
-18
lines changed

3 files changed

+87
-18
lines changed

src/librustc/middle/borrowck/check_loans.rs

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -391,15 +391,7 @@ impl<'self> CheckLoanCtxt<'self> {
391391
mc::cat_deref(b, _, mc::region_ptr(m_mutbl, _)) => {
392392
// Statically prohibit writes to `&mut` when aliasable
393393

394-
match b.freely_aliasable() {
395-
None => {}
396-
Some(cause) => {
397-
this.bccx.report_aliasability_violation(
398-
expr.span,
399-
MutabilityViolation,
400-
cause);
401-
}
402-
}
394+
check_for_aliasability_violation(this, expr, b);
403395
}
404396

405397
mc::cat_deref(_, deref_count, mc::gc_ptr(ast::m_mutbl)) => {
@@ -419,6 +411,52 @@ impl<'self> CheckLoanCtxt<'self> {
419411
return true; // no errors reported
420412
}
421413

414+
fn check_for_aliasability_violation(this: &CheckLoanCtxt,
415+
expr: @ast::expr,
416+
cmt: mc::cmt) -> bool {
417+
let mut cmt = cmt;
418+
419+
loop {
420+
match cmt.cat {
421+
mc::cat_deref(b, _, mc::region_ptr(m_mutbl, _)) |
422+
mc::cat_downcast(b) |
423+
mc::cat_stack_upvar(b) |
424+
mc::cat_deref(b, _, mc::uniq_ptr) |
425+
mc::cat_interior(b, _) |
426+
mc::cat_discr(b, _) => {
427+
// Aliasability depends on base cmt
428+
cmt = b;
429+
}
430+
431+
mc::cat_copied_upvar(_) |
432+
mc::cat_rvalue(*) |
433+
mc::cat_local(*) |
434+
mc::cat_arg(_) |
435+
mc::cat_self(*) |
436+
mc::cat_deref(_, _, mc::unsafe_ptr(*)) |
437+
mc::cat_static_item(*) |
438+
mc::cat_implicit_self(*) |
439+
mc::cat_deref(_, _, mc::gc_ptr(_)) |
440+
mc::cat_deref(_, _, mc::region_ptr(m_const, _)) |
441+
mc::cat_deref(_, _, mc::region_ptr(m_imm, _)) => {
442+
// Aliasability is independent of base cmt
443+
match cmt.freely_aliasable() {
444+
None => {
445+
return true;
446+
}
447+
Some(cause) => {
448+
this.bccx.report_aliasability_violation(
449+
expr.span,
450+
MutabilityViolation,
451+
cause);
452+
return false;
453+
}
454+
}
455+
}
456+
}
457+
}
458+
}
459+
422460
fn check_for_assignment_to_restricted_or_frozen_location(
423461
this: &CheckLoanCtxt,
424462
expr: @ast::expr,

src/librustc/middle/mem_categorization.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,9 +1146,10 @@ impl cmt_ {
11461146
}
11471147

11481148
pub fn freely_aliasable(&self) -> Option<AliasableReason> {
1149-
//! True if this lvalue resides in an area that is
1150-
//! freely aliasable, meaning that rustc cannot track
1151-
//! the alias//es with precision.
1149+
/*!
1150+
* Returns `Some(_)` if this lvalue represents a freely aliasable
1151+
* pointer type.
1152+
*/
11521153

11531154
// Maybe non-obvious: copied upvars can only be considered
11541155
// non-aliasable in once closures, since any other kind can be
@@ -1180,12 +1181,12 @@ impl cmt_ {
11801181
Some(AliasableBorrowed(m))
11811182
}
11821183

1183-
cat_downcast(b) |
1184-
cat_stack_upvar(b) |
1185-
cat_deref(b, _, uniq_ptr) |
1186-
cat_interior(b, _) |
1187-
cat_discr(b, _) => {
1188-
b.freely_aliasable()
1184+
cat_downcast(*) |
1185+
cat_stack_upvar(*) |
1186+
cat_deref(_, _, uniq_ptr) |
1187+
cat_interior(*) |
1188+
cat_discr(*) => {
1189+
None
11891190
}
11901191
}
11911192
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that assignments to an `&mut` pointer which is found in a
12+
// borrowed (but otherwise non-aliasable) location is illegal.
13+
14+
struct S<'self> {
15+
pointer: &'self mut int
16+
}
17+
18+
fn a(s: &S) {
19+
*s.pointer += 1; //~ ERROR cannot assign
20+
}
21+
22+
fn b(s: &mut S) {
23+
*s.pointer += 1;
24+
}
25+
26+
fn c(s: & &mut S) {
27+
*s.pointer += 1; //~ ERROR cannot assign
28+
}
29+
30+
fn main() {}

0 commit comments

Comments
 (0)