Skip to content

Commit d441c54

Browse files
committed
auto merge of #10787 : nikomatsakis/rust/issue-9629-freeze-andmut, r=pnkfelix
See #9629 for details. r? @pnkfelix
2 parents 5c2f8aa + fc74d64 commit d441c54

8 files changed

+454
-218
lines changed

src/librustc/middle/borrowck/doc.rs

+282-177
Large diffs are not rendered by default.

src/librustc/middle/borrowck/gather_loans/restrictions.rs

+31-26
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,26 @@ impl<'self> RestrictionsContext<'self> {
114114
}
115115

116116
mc::cat_copied_upvar(..) | // FIXME(#2152) allow mutation of upvars
117-
mc::cat_static_item(..) |
118-
mc::cat_deref(_, _, mc::region_ptr(MutImmutable, _)) |
119-
mc::cat_deref(_, _, mc::gc_ptr(MutImmutable)) => {
117+
mc::cat_static_item(..) => {
118+
Safe
119+
}
120+
121+
mc::cat_deref(cmt_base, _, mc::region_ptr(MutImmutable, lt)) => {
120122
// R-Deref-Imm-Borrowed
123+
if !self.bccx.is_subregion_of(self.loan_region, lt) {
124+
self.bccx.report(
125+
BckError {
126+
span: self.span,
127+
cmt: cmt_base,
128+
code: err_borrowed_pointer_too_short(
129+
self.loan_region, lt, restrictions)});
130+
return Safe;
131+
}
132+
Safe
133+
}
134+
135+
mc::cat_deref(_, _, mc::gc_ptr(MutImmutable)) => {
136+
// R-Deref-Imm-Managed
121137
Safe
122138
}
123139

@@ -170,30 +186,19 @@ impl<'self> RestrictionsContext<'self> {
170186
}
171187

172188
mc::cat_deref(cmt_base, _, pk @ mc::region_ptr(MutMutable, lt)) => {
173-
// Because an `&mut` pointer does not inherit its
174-
// mutability, we can only prevent mutation or prevent
175-
// freezing if it is not aliased. Therefore, in such
176-
// cases we restrict aliasing on `cmt_base`.
177-
if restrictions != RESTR_EMPTY {
178-
if !self.bccx.is_subregion_of(self.loan_region, lt) {
179-
self.bccx.report(
180-
BckError {
181-
span: self.span,
182-
cmt: cmt_base,
183-
code: err_mut_pointer_too_short(
184-
self.loan_region, lt, restrictions)});
185-
return Safe;
186-
}
187-
188-
// R-Deref-Mut-Borrowed-1
189-
let result = self.restrict(
190-
cmt_base,
191-
RESTR_ALIAS | RESTR_MUTATE | RESTR_CLAIM);
192-
self.extend(result, cmt.mutbl, LpDeref(pk), restrictions)
193-
} else {
194-
// R-Deref-Mut-Borrowed-2
195-
Safe
189+
// R-Deref-Mut-Borrowed
190+
if !self.bccx.is_subregion_of(self.loan_region, lt) {
191+
self.bccx.report(
192+
BckError {
193+
span: self.span,
194+
cmt: cmt_base,
195+
code: err_borrowed_pointer_too_short(
196+
self.loan_region, lt, restrictions)});
197+
return Safe;
196198
}
199+
200+
let result = self.restrict(cmt_base, restrictions);
201+
self.extend(result, cmt.mutbl, LpDeref(pk), restrictions)
197202
}
198203

199204
mc::cat_deref(_, _, mc::unsafe_ptr(..)) => {

src/librustc/middle/borrowck/mod.rs

+9-14
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,8 @@ pub enum bckerr_code {
444444
err_out_of_root_scope(ty::Region, ty::Region), // superscope, subscope
445445
err_out_of_scope(ty::Region, ty::Region), // superscope, subscope
446446
err_freeze_aliasable_const,
447-
err_mut_pointer_too_short(ty::Region, ty::Region, RestrictionSet), // loan, ptr
447+
err_borrowed_pointer_too_short(
448+
ty::Region, ty::Region, RestrictionSet), // loan, ptr
448449
}
449450

450451
// Combination of an error code and the categorization of the expression
@@ -670,21 +671,15 @@ impl BorrowckCtxt {
670671
// supposed to be going away.
671672
format!("unsafe borrow of aliasable, const value")
672673
}
673-
err_mut_pointer_too_short(_, _, r) => {
674+
err_borrowed_pointer_too_short(..) => {
674675
let descr = match opt_loan_path(err.cmt) {
675676
Some(lp) => format!("`{}`", self.loan_path_to_str(lp)),
676-
None => ~"`&mut` pointer"
677+
None => self.cmt_to_str(err.cmt),
677678
};
678679

679-
let tag = if r.intersects(RESTR_ALIAS) {
680-
"its contents are unique"
681-
} else {
682-
"its contents are not otherwise mutable"
683-
};
684-
685-
format!("lifetime of {} is too short to guarantee {} \
686-
so they can be safely reborrowed",
687-
descr, tag)
680+
format!("lifetime of {} is too short to guarantee \
681+
its contents can be safely reborrowed",
682+
descr)
688683
}
689684
}
690685
}
@@ -761,10 +756,10 @@ impl BorrowckCtxt {
761756
"");
762757
}
763758

764-
err_mut_pointer_too_short(loan_scope, ptr_scope, _) => {
759+
err_borrowed_pointer_too_short(loan_scope, ptr_scope, _) => {
765760
let descr = match opt_loan_path(err.cmt) {
766761
Some(lp) => format!("`{}`", self.loan_path_to_str(lp)),
767-
None => ~"`&mut` pointer"
762+
None => self.cmt_to_str(err.cmt),
768763
};
769764
note_and_explain_region(
770765
self.tcx,

src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
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+
111
// Test that attempt to reborrow an `&mut` pointer in an aliasable
212
// location yields an error.
313
//
@@ -7,7 +17,7 @@ use std::util::swap;
717

818
fn foo(t0: & &mut int) {
919
let t1 = t0;
10-
let p: &int = &**t0; //~ ERROR cannot borrow an `&mut` in a `&` pointer
20+
let p: &int = &**t0;
1121
**t1 = 22; //~ ERROR cannot assign
1222
}
1323

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2013 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 attempt to freeze an `&mut` pointer while referent is
12+
// claimed yields an error.
13+
//
14+
// Example from src/middle/borrowck/doc.rs
15+
16+
use std::util::swap;
17+
18+
fn foo<'a>(mut t0: &'a mut int,
19+
mut t1: &'a mut int) {
20+
let p: &mut int = &mut *t0; // Claims `*t0`
21+
let mut t2 = &t0; //~ ERROR cannot borrow `t0`
22+
let q: &int = &**t2; // Freezes `*t0` but not through `*p`
23+
*p += 1; // violates type of `*q`
24+
}
25+
26+
fn main() {
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2013 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 attempt to mutably borrow `&mut` pointer while pointee is
12+
// borrowed yields an error.
13+
//
14+
// Example from src/middle/borrowck/doc.rs
15+
16+
use std::util::swap;
17+
18+
fn foo<'a>(mut t0: &'a mut int,
19+
mut t1: &'a mut int) {
20+
let p: &int = &*t0; // Freezes `*t0`
21+
let mut t2 = &mut t0; //~ ERROR cannot borrow `t0`
22+
**t2 += 1; // Mutates `*t0`
23+
}
24+
25+
fn bar<'a>(mut t0: &'a mut int,
26+
mut t1: &'a mut int) {
27+
let p: &mut int = &mut *t0; // Claims `*t0`
28+
let mut t2 = &mut t0; //~ ERROR cannot borrow `t0`
29+
**t2 += 1; // Mutates `*t0` but not through `*p`
30+
}
31+
32+
fn main() {
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2013 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 freezing an `&mut` pointer while referent is
12+
// frozen is legal.
13+
//
14+
// Example from src/middle/borrowck/doc.rs
15+
16+
fn foo<'a>(mut t0: &'a mut int,
17+
mut t1: &'a mut int) {
18+
let p: &int = &*t0; // Freezes `*t0`
19+
let mut t2 = &t0;
20+
let q: &int = &**t2; // Freezes `*t0`, but that's ok...
21+
let r: &int = &*t0; // ...after all, could do same thing directly.
22+
}
23+
24+
pub fn main() {
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2012-2013 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 a `&mut` inside of an `&` is freezable.
12+
13+
struct MutSlice<'a, T> {
14+
data: &'a mut [T]
15+
}
16+
17+
fn get<'a, T>(ms: &'a MutSlice<'a, T>, index: uint) -> &'a T {
18+
&ms.data[index]
19+
}
20+
21+
pub fn main() {
22+
let mut data = [1, 2, 3];
23+
{
24+
let slice = MutSlice { data: data };
25+
slice.data[0] += 4;
26+
let index0 = get(&slice, 0);
27+
let index1 = get(&slice, 1);
28+
let index2 = get(&slice, 2);
29+
assert_eq!(*index0, 5);
30+
assert_eq!(*index1, 2);
31+
assert_eq!(*index2, 3);
32+
}
33+
assert_eq!(data[0], 5);
34+
assert_eq!(data[1], 2);
35+
assert_eq!(data[2], 3);
36+
}

0 commit comments

Comments
 (0)