Skip to content

Commit 58365e2

Browse files
committed
check that the path from which we borrow is readable
The old code incorrectly assumed that the borrow would always generate a loan. In that case, we will check if that loan conflicts with other loans and hence get an error if the path we borrowed is mutably borrowed. But this is not true if we are borrowing the referent of an `&T` reference. Fixes rust-lang#38899.
1 parent 373efe8 commit 58365e2

File tree

3 files changed

+33
-4
lines changed

3 files changed

+33
-4
lines changed

src/libgetopts/lib.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ use self::SplitWithinState::*;
101101
use self::Whitespace::*;
102102
use self::LengthLimit::*;
103103

104+
use std::cell::Cell;
104105
use std::fmt;
105106
use std::iter::repeat;
106107
use std::result;
@@ -858,7 +859,7 @@ fn each_split_within<F>(ss: &str, lim: usize, mut it: F) -> bool
858859
let mut slice_start = 0;
859860
let mut last_start = 0;
860861
let mut last_end = 0;
861-
let mut state = A;
862+
let state = Cell::new(A);
862863
let mut fake_i = ss.len();
863864
let mut lim = lim;
864865

@@ -881,7 +882,7 @@ fn each_split_within<F>(ss: &str, lim: usize, mut it: F) -> bool
881882
OverLim
882883
};
883884

884-
state = match (state, whitespace, limit) {
885+
state.set(match (state.get(), whitespace, limit) {
885886
(A, Ws, _) => A,
886887
(A, Cr, _) => {
887888
slice_start = i;
@@ -925,7 +926,7 @@ fn each_split_within<F>(ss: &str, lim: usize, mut it: F) -> bool
925926
A
926927
}
927928
(C, Ws, UnderLim) => C,
928-
};
929+
});
929930

930931
*cont
931932
};
@@ -934,7 +935,7 @@ fn each_split_within<F>(ss: &str, lim: usize, mut it: F) -> bool
934935

935936
// Let the automaton 'run out' by supplying trailing whitespace
936937
while cont &&
937-
match state {
938+
match state.get() {
938939
B | C => true,
939940
A => false,
940941
} {

src/librustc_borrowck/borrowck/check_loans.rs

+1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
141141
_ => MovedInUse,
142142
};
143143
self.check_if_path_is_moved(borrow_id, borrow_span, moved_value_use_kind, &lp);
144+
self.check_for_copy_of_frozen_path(borrow_id, borrow_span, &lp);
144145
}
145146

146147
self.check_for_conflicting_loans(borrow_id);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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 reborrowing the referent of an `&T` reference is not
12+
// possible if the path we use to reach that reference is itself
13+
// borrowed. Regression test for #38899.
14+
15+
#![allow(dead_code)]
16+
17+
pub struct Block<'a> {
18+
current: &'a u8,
19+
unrelated: &'a u8,
20+
}
21+
22+
fn bump<'a>(mut block: &mut Block<'a>) {
23+
let x = &mut block;
24+
let p: &'a u8 = &*block.current; //~ ERROR E0503
25+
}
26+
27+
fn main() {}

0 commit comments

Comments
 (0)