Skip to content

Commit b71b921

Browse files
Rollup merge of rust-lang#52058 - davidtwco:issue-51345, r=nikomatsakis
Use of unimplemented!() causing ICE with NLL Fixes rust-lang#51345. r? @nikomatsakis
2 parents 9b3ec57 + f90eada commit b71b921

File tree

4 files changed

+70
-41
lines changed

4 files changed

+70
-41
lines changed

src/librustc_mir/borrow_check/borrow_set.rs

+30-36
Original file line numberDiff line numberDiff line change
@@ -53,25 +53,22 @@ impl<'tcx> Index<BorrowIndex> for BorrowSet<'tcx> {
5353
}
5454
}
5555

56-
/// Every two-phase borrow has *exactly one* use (or else it is not a
57-
/// proper two-phase borrow under our current definition). However, not
58-
/// all uses are actually ones that activate the reservation.. In
59-
/// particular, a shared borrow of a `&mut` does not activate the
60-
/// reservation.
56+
/// Location where a two phase borrow is activated, if a borrow
57+
/// is in fact a two phase borrow.
6158
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
62-
crate enum TwoPhaseUse {
63-
MutActivate,
64-
SharedUse,
59+
crate enum TwoPhaseActivation {
60+
NotTwoPhase,
61+
NotActivated,
62+
ActivatedAt(Location),
6563
}
6664

6765
#[derive(Debug)]
6866
crate struct BorrowData<'tcx> {
6967
/// Location where the borrow reservation starts.
7068
/// In many cases, this will be equal to the activation location but not always.
7169
crate reserve_location: Location,
72-
/// Location where the borrow is activated. None if this is not a
73-
/// 2-phase borrow.
74-
crate activation_location: Option<(TwoPhaseUse, Location)>,
70+
/// Location where the borrow is activated.
71+
crate activation_location: TwoPhaseActivation,
7572
/// What kind of borrow this is
7673
crate kind: mir::BorrowKind,
7774
/// The region for which this borrow is live
@@ -116,19 +113,6 @@ impl<'tcx> BorrowSet<'tcx> {
116113
visitor.visit_basic_block_data(block, block_data);
117114
}
118115

119-
// Double check: We should have found an activation for every pending
120-
// activation.
121-
assert_eq!(
122-
visitor
123-
.pending_activations
124-
.iter()
125-
.find(|&(_local, &borrow_index)| visitor.idx_vec[borrow_index]
126-
.activation_location
127-
.is_none()),
128-
None,
129-
"never found an activation for this borrow!",
130-
);
131-
132116
BorrowSet {
133117
borrows: visitor.idx_vec,
134118
location_map: visitor.location_map,
@@ -183,7 +167,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
183167
kind,
184168
region,
185169
reserve_location: location,
186-
activation_location: None,
170+
activation_location: TwoPhaseActivation::NotTwoPhase,
187171
borrowed_place: borrowed_place.clone(),
188172
assigned_place: assigned_place.clone(),
189173
};
@@ -232,38 +216,43 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
232216
return;
233217
}
234218

235-
if let Some(other_activation) = borrow_data.activation_location {
219+
if let TwoPhaseActivation::ActivatedAt(other_location) =
220+
borrow_data.activation_location {
236221
span_bug!(
237222
self.mir.source_info(location).span,
238223
"found two uses for 2-phase borrow temporary {:?}: \
239224
{:?} and {:?}",
240225
temp,
241226
location,
242-
other_activation,
227+
other_location,
243228
);
244229
}
245230

246231
// Otherwise, this is the unique later use
247232
// that we expect.
248-
249-
let two_phase_use;
250-
251-
match context {
233+
borrow_data.activation_location = match context {
252234
// The use of TMP in a shared borrow does not
253235
// count as an actual activation.
254236
PlaceContext::Borrow { kind: mir::BorrowKind::Shared, .. } => {
255-
two_phase_use = TwoPhaseUse::SharedUse;
237+
TwoPhaseActivation::NotActivated
256238
}
257239
_ => {
258-
two_phase_use = TwoPhaseUse::MutActivate;
240+
// Double check: This borrow is indeed a two-phase borrow (that is,
241+
// we are 'transitioning' from `NotActivated` to `ActivatedAt`) and
242+
// we've not found any other activations (checked above).
243+
assert_eq!(
244+
borrow_data.activation_location,
245+
TwoPhaseActivation::NotActivated,
246+
"never found an activation for this borrow!",
247+
);
248+
259249
self.activation_map
260250
.entry(location)
261251
.or_insert(Vec::new())
262252
.push(borrow_index);
253+
TwoPhaseActivation::ActivatedAt(location)
263254
}
264-
}
265-
266-
borrow_data.activation_location = Some((two_phase_use, location));
255+
};
267256
}
268257

269258
None => {}
@@ -342,6 +331,11 @@ impl<'a, 'gcx, 'tcx> GatherBorrows<'a, 'gcx, 'tcx> {
342331
);
343332
};
344333

334+
// Consider the borrow not activated to start. When we find an activation, we'll update
335+
// this field.
336+
let borrow_data = &mut self.idx_vec[borrow_index];
337+
borrow_data.activation_location = TwoPhaseActivation::NotActivated;
338+
345339
// Insert `temp` into the list of pending activations. From
346340
// now on, we'll be on the lookout for a use of it. Note that
347341
// we are guaranteed that this use will come after the

src/librustc_mir/borrow_check/path_utils.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use borrow_check::borrow_set::{BorrowSet, BorrowData, TwoPhaseUse};
11+
use borrow_check::borrow_set::{BorrowSet, BorrowData, TwoPhaseActivation};
1212
use borrow_check::places_conflict;
1313
use borrow_check::Context;
1414
use borrow_check::ShallowOrDeep;
@@ -83,11 +83,11 @@ pub(super) fn is_active<'tcx>(
8383

8484
let activation_location = match borrow_data.activation_location {
8585
// If this is not a 2-phase borrow, it is always active.
86-
None => return true,
86+
TwoPhaseActivation::NotTwoPhase => return true,
8787
// And if the unique 2-phase use is not an activation, then it is *never* active.
88-
Some((TwoPhaseUse::SharedUse, _)) => return false,
89-
// Otherwise, we derive info from the activation point `v`:
90-
Some((TwoPhaseUse::MutActivate, v)) => v,
88+
TwoPhaseActivation::NotActivated => return false,
89+
// Otherwise, we derive info from the activation point `loc`:
90+
TwoPhaseActivation::ActivatedAt(loc) => loc,
9191
};
9292

9393
// Otherwise, it is active for every location *except* in between

src/test/run-fail/issue-51345.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
// error-pattern: thread 'main' panicked at 'explicit panic'
12+
13+
#![feature(nll)]
14+
15+
fn main() {
16+
let mut vec = vec![];
17+
vec.push((vec.len(), panic!()));
18+
}

src/test/run-pass/issue-51345.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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+
#![feature(nll)]
12+
13+
fn main() {
14+
let mut v = Vec::new();
15+
16+
loop { v.push(break) }
17+
}

0 commit comments

Comments
 (0)