Skip to content

Commit

Permalink
check that the path from which we borrow is readable
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nikomatsakis committed Jan 7, 2017
1 parent 373efe8 commit 58365e2
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 4 deletions.
9 changes: 5 additions & 4 deletions src/libgetopts/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ use self::SplitWithinState::*;
use self::Whitespace::*;
use self::LengthLimit::*;

use std::cell::Cell;
use std::fmt;
use std::iter::repeat;
use std::result;
Expand Down Expand Up @@ -858,7 +859,7 @@ fn each_split_within<F>(ss: &str, lim: usize, mut it: F) -> bool
let mut slice_start = 0;
let mut last_start = 0;
let mut last_end = 0;
let mut state = A;
let state = Cell::new(A);
let mut fake_i = ss.len();
let mut lim = lim;

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

state = match (state, whitespace, limit) {
state.set(match (state.get(), whitespace, limit) {
(A, Ws, _) => A,
(A, Cr, _) => {
slice_start = i;
Expand Down Expand Up @@ -925,7 +926,7 @@ fn each_split_within<F>(ss: &str, lim: usize, mut it: F) -> bool
A
}
(C, Ws, UnderLim) => C,
};
});

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

// Let the automaton 'run out' by supplying trailing whitespace
while cont &&
match state {
match state.get() {
B | C => true,
A => false,
} {
Expand Down
1 change: 1 addition & 0 deletions src/librustc_borrowck/borrowck/check_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
_ => MovedInUse,
};
self.check_if_path_is_moved(borrow_id, borrow_span, moved_value_use_kind, &lp);
self.check_for_copy_of_frozen_path(borrow_id, borrow_span, &lp);
}

self.check_for_conflicting_loans(borrow_id);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test that reborrowing the referent of an `&T` reference is not
// possible if the path we use to reach that reference is itself
// borrowed. Regression test for #38899.

#![allow(dead_code)]

pub struct Block<'a> {
current: &'a u8,
unrelated: &'a u8,
}

fn bump<'a>(mut block: &mut Block<'a>) {
let x = &mut block;
let p: &'a u8 = &*block.current; //~ ERROR E0503
}

fn main() {}

0 comments on commit 58365e2

Please sign in to comment.