Skip to content

Commit f1799fd

Browse files
committed
librustc: Record unique immutable borrows in the restrictions table.
This fixes borrow checking for closures. Code like this will break: struct Foo { x: int, } pub fn main() { let mut this = &mut Foo { x: 1, }; let r = || { let p = &this.x; &mut this.x; }; r() } Change this code to not take multiple mutable references to the same value. For example: struct Foo { x: int, } pub fn main() { let mut this = &mut Foo { x: 1, }; let r = || { &mut this.x; }; r() } Closes #16361. [breaking-change]
1 parent e2273d9 commit f1799fd

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

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

+2
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ impl<'a> GatherLoanCtxt<'a> {
261261
self.bccx, borrow_span, cause,
262262
cmt.clone(), loan_region);
263263

264+
debug!("guarantee_valid(): restrictions={:?}", restr);
265+
264266
// Create the loan record (if needed).
265267
let loan = match restr {
266268
restrictions::Safe => {

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,7 @@ impl<'a> RestrictionsContext<'a> {
122122
}
123123

124124
mc::cat_deref(cmt_base, _, mc::BorrowedPtr(ty::ImmBorrow, lt)) |
125-
mc::cat_deref(cmt_base, _, mc::BorrowedPtr(ty::UniqueImmBorrow, lt)) |
126-
mc::cat_deref(cmt_base, _, mc::Implicit(ty::ImmBorrow, lt)) |
127-
mc::cat_deref(cmt_base, _, mc::Implicit(ty::UniqueImmBorrow, lt)) => {
125+
mc::cat_deref(cmt_base, _, mc::Implicit(ty::ImmBorrow, lt)) => {
128126
// R-Deref-Imm-Borrowed
129127
if !self.bccx.is_subregion_of(self.loan_region, lt) {
130128
self.bccx.report(
@@ -142,7 +140,9 @@ impl<'a> RestrictionsContext<'a> {
142140
mc::cat_deref(cmt_base, _, pk) => {
143141
match pk {
144142
mc::BorrowedPtr(ty::MutBorrow, lt) |
145-
mc::Implicit(ty::MutBorrow, lt) => {
143+
mc::BorrowedPtr(ty::UniqueImmBorrow, lt) |
144+
mc::Implicit(ty::MutBorrow, lt) |
145+
mc::Implicit(ty::UniqueImmBorrow, lt) => {
146146
// R-Deref-Mut-Borrowed
147147
if !self.bccx.is_subregion_of(self.loan_region, lt) {
148148
self.bccx.report(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2014 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+
struct Foo {
12+
x: int,
13+
}
14+
15+
pub fn main() {
16+
let mut this = &mut Foo {
17+
x: 1,
18+
};
19+
let r = || {
20+
let p = &this.x;
21+
&mut this.x; //~ ERROR cannot borrow
22+
};
23+
r()
24+
}
25+

0 commit comments

Comments
 (0)