Skip to content

Commit 6b23d20

Browse files
committed
Prohibit assignment to &mut pointers that are found in frozen or borrowed locations.
Fixes #8625.
1 parent 0ea2a20 commit 6b23d20

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

src/librustc/middle/borrowck/check_loans.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,12 @@ impl<'self> CheckLoanCtxt<'self> {
496496
// path, and check that the super path was not lent out as
497497
// mutable or immutable (a const loan is ok).
498498
//
499+
// Mutability of a path can be dependent on the super path
500+
// in two ways. First, it might be inherited mutability.
501+
// Second, the pointee of an `&mut` pointer can only be
502+
// mutated if it is found in an unaliased location, so we
503+
// have to check that the owner location is not borrowed.
504+
//
499505
// Note that we are *not* checking for any and all
500506
// restrictions. We are only interested in the pointers
501507
// that the user created, whereas we add restrictions for
@@ -513,9 +519,12 @@ impl<'self> CheckLoanCtxt<'self> {
513519
let mut loan_path = loan_path;
514520
loop {
515521
match *loan_path {
516-
// Peel back one layer if `loan_path` has
517-
// inherited mutability
518-
LpExtend(lp_base, mc::McInherited, _) => {
522+
// Peel back one layer if, for `loan_path` to be
523+
// mutable, `lp_base` must be mutable. This occurs
524+
// with inherited mutability and with `&mut`
525+
// pointers.
526+
LpExtend(lp_base, mc::McInherited, _) |
527+
LpExtend(lp_base, _, LpDeref(mc::region_ptr(ast::m_mutbl, _))) => {
519528
loan_path = lp_base;
520529
}
521530

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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 copy_borrowed_ptr<'a>(p: &'a mut S<'a>) -> S<'a> {
19+
S { pointer: &mut *p.pointer }
20+
}
21+
22+
fn main() {
23+
let mut x = 1;
24+
25+
{
26+
let mut y = S { pointer: &mut x };
27+
let z = copy_borrowed_ptr(&mut y);
28+
*y.pointer += 1; //~ ERROR cannot assign
29+
*z.pointer += 1;
30+
}
31+
}

0 commit comments

Comments
 (0)