Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit cf30759

Browse files
committedDec 6, 2017
Auto merge of #46268 - arielb1:union-borrow, r=nikomatsakis
MIR borrowck: implement union-and-array-compatible semantics Fixes #44831. Fixes #44834. Fixes #45537. Fixes #45696 (by implementing DerefPure semantics, which is what we want going forward). r? @nikomatsakis
2 parents 833785b + 9d35587 commit cf30759

17 files changed

+608
-176
lines changed
 

‎src/libcore/cell.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,9 +1084,11 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
10841084
pub fn map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> RefMut<'b, U>
10851085
where F: FnOnce(&mut T) -> &mut U
10861086
{
1087+
// FIXME(nll-rfc#40): fix borrow-check
1088+
let RefMut { value, borrow } = orig;
10871089
RefMut {
1088-
value: f(orig.value),
1089-
borrow: orig.borrow,
1090+
value: f(value),
1091+
borrow: borrow,
10901092
}
10911093
}
10921094
}

‎src/libcore/iter/mod.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,12 +1776,18 @@ impl<I: Iterator> Iterator for Peekable<I> {
17761776

17771777
#[inline]
17781778
fn nth(&mut self, n: usize) -> Option<I::Item> {
1779-
match self.peeked.take() {
1780-
// the .take() below is just to avoid "move into pattern guard"
1781-
Some(ref mut v) if n == 0 => v.take(),
1782-
Some(None) => None,
1783-
Some(Some(_)) => self.iter.nth(n - 1),
1784-
None => self.iter.nth(n),
1779+
// FIXME(#6393): merge these when borrow-checking gets better.
1780+
if n == 0 {
1781+
match self.peeked.take() {
1782+
Some(v) => v,
1783+
None => self.iter.nth(n),
1784+
}
1785+
} else {
1786+
match self.peeked.take() {
1787+
Some(None) => None,
1788+
Some(Some(_)) => self.iter.nth(n - 1),
1789+
None => self.iter.nth(n),
1790+
}
17851791
}
17861792
}
17871793

‎src/librustc_mir/borrow_check/mod.rs

Lines changed: 428 additions & 85 deletions
Large diffs are not rendered by default.

‎src/librustc_mir/build/cfg.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,17 @@ impl<'tcx> CFG<'tcx> {
5151
source_info: SourceInfo,
5252
region_scope: region::Scope) {
5353
if tcx.sess.emit_end_regions() {
54+
if let region::ScopeData::CallSite(_) = region_scope.data() {
55+
// The CallSite scope (aka the root scope) is sort of weird, in that it is
56+
// supposed to "separate" the "interior" and "exterior" of a closure. Being
57+
// that, it is not really a part of the region hierarchy, but for some
58+
// reason it *is* considered a part of it.
59+
//
60+
// It should die a hopefully painful death with NLL, so let's leave this hack
61+
// for now so that nobody can complain about soundness.
62+
return
63+
}
64+
5465
self.push(block, Statement {
5566
source_info,
5667
kind: StatementKind::EndRegion(region_scope),

‎src/librustc_mir/dataflow/impls/borrows.rs

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use rustc::hir;
12+
use rustc::hir::def_id::DefId;
13+
use rustc::middle::region;
1114
use rustc::mir::{self, Location, Mir};
1215
use rustc::mir::visit::Visitor;
1316
use rustc::ty::{self, Region, TyCtxt};
@@ -27,16 +30,20 @@ use borrow_check::nll::ToRegionVid;
2730
use syntax_pos::Span;
2831

2932
use std::fmt;
33+
use std::rc::Rc;
3034

3135
// `Borrows` maps each dataflow bit to an `Rvalue::Ref`, which can be
3236
// uniquely identified in the MIR by the `Location` of the assigment
3337
// statement in which it appears on the right hand side.
3438
pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
3539
tcx: TyCtxt<'a, 'gcx, 'tcx>,
3640
mir: &'a Mir<'tcx>,
41+
scope_tree: Rc<region::ScopeTree>,
42+
root_scope: Option<region::Scope>,
3743
borrows: IndexVec<BorrowIndex, BorrowData<'tcx>>,
3844
location_map: FxHashMap<Location, BorrowIndex>,
3945
region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
46+
local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
4047
region_span_map: FxHashMap<RegionKind, Span>,
4148
nonlexical_regioncx: Option<RegionInferenceContext<'tcx>>,
4249
}
@@ -69,22 +76,32 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
6976
impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
7077
pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
7178
mir: &'a Mir<'tcx>,
72-
nonlexical_regioncx: Option<RegionInferenceContext<'tcx>>)
79+
nonlexical_regioncx: Option<RegionInferenceContext<'tcx>>,
80+
def_id: DefId,
81+
body_id: Option<hir::BodyId>)
7382
-> Self {
83+
let scope_tree = tcx.region_scope_tree(def_id);
84+
let root_scope = body_id.map(|body_id| {
85+
region::Scope::CallSite(tcx.hir.body(body_id).value.hir_id.local_id)
86+
});
7487
let mut visitor = GatherBorrows {
7588
tcx,
7689
mir,
7790
idx_vec: IndexVec::new(),
7891
location_map: FxHashMap(),
7992
region_map: FxHashMap(),
93+
local_map: FxHashMap(),
8094
region_span_map: FxHashMap()
8195
};
8296
visitor.visit_mir(mir);
8397
return Borrows { tcx: tcx,
8498
mir: mir,
8599
borrows: visitor.idx_vec,
100+
scope_tree,
101+
root_scope,
86102
location_map: visitor.location_map,
87103
region_map: visitor.region_map,
104+
local_map: visitor.local_map,
88105
region_span_map: visitor.region_span_map,
89106
nonlexical_regioncx };
90107

@@ -94,13 +111,22 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
94111
idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
95112
location_map: FxHashMap<Location, BorrowIndex>,
96113
region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
114+
local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
97115
region_span_map: FxHashMap<RegionKind, Span>,
98116
}
99117

100118
impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
101119
fn visit_rvalue(&mut self,
102120
rvalue: &mir::Rvalue<'tcx>,
103121
location: mir::Location) {
122+
fn root_local(mut p: &mir::Place<'_>) -> Option<mir::Local> {
123+
loop { match p {
124+
mir::Place::Projection(pi) => p = &pi.base,
125+
mir::Place::Static(_) => return None,
126+
mir::Place::Local(l) => return Some(*l)
127+
}}
128+
}
129+
104130
if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue {
105131
if is_unsafe_place(self.tcx, self.mir, place) { return; }
106132

@@ -109,8 +135,14 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
109135
};
110136
let idx = self.idx_vec.push(borrow);
111137
self.location_map.insert(location, idx);
138+
112139
let borrows = self.region_map.entry(region).or_insert(FxHashSet());
113140
borrows.insert(idx);
141+
142+
if let Some(local) = root_local(place) {
143+
let borrows = self.local_map.entry(local).or_insert(FxHashSet());
144+
borrows.insert(idx);
145+
}
114146
}
115147
}
116148

@@ -199,7 +231,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
199231
mir::StatementKind::EndRegion(region_scope) => {
200232
if let Some(borrow_indexes) = self.region_map.get(&ReScope(region_scope)) {
201233
assert!(self.nonlexical_regioncx.is_none());
202-
for idx in borrow_indexes { sets.kill(&idx); }
234+
sets.kill_all(borrow_indexes);
203235
} else {
204236
// (if there is no entry, then there are no borrows to be tracked)
205237
}
@@ -224,10 +256,19 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
224256
}
225257
}
226258

259+
mir::StatementKind::StorageDead(local) => {
260+
// Make sure there are no remaining borrows for locals that
261+
// are gone out of scope.
262+
//
263+
// FIXME: expand this to variables that are assigned over.
264+
if let Some(borrow_indexes) = self.local_map.get(&local) {
265+
sets.kill_all(borrow_indexes);
266+
}
267+
}
268+
227269
mir::StatementKind::InlineAsm { .. } |
228270
mir::StatementKind::SetDiscriminant { .. } |
229271
mir::StatementKind::StorageLive(..) |
230-
mir::StatementKind::StorageDead(..) |
231272
mir::StatementKind::Validate(..) |
232273
mir::StatementKind::Nop => {}
233274

@@ -253,8 +294,17 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
253294
// like unwind paths, we do not always emit `EndRegion` statements, so we
254295
// add some kills here as a "backup" and to avoid spurious error messages.
255296
for (borrow_index, borrow_data) in self.borrows.iter_enumerated() {
256-
if let ReScope(..) = borrow_data.region {
257-
sets.kill(&borrow_index);
297+
if let ReScope(scope) = borrow_data.region {
298+
// Check that the scope is not actually a scope from a function that is
299+
// a parent of our closure. Note that the CallSite scope itself is
300+
// *outside* of the closure, for some weird reason.
301+
if let Some(root_scope) = self.root_scope {
302+
if *scope != root_scope &&
303+
self.scope_tree.is_subscope_of(*scope, root_scope)
304+
{
305+
sets.kill(&borrow_index);
306+
}
307+
}
258308
}
259309
}
260310
}

‎src/librustc_mir/dataflow/impls/mod.rs

Lines changed: 39 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
1515
use rustc::ty::TyCtxt;
1616
use rustc::mir::{self, Mir, Location};
17-
use rustc_data_structures::bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep.
1817
use rustc_data_structures::bitslice::{BitwiseOperator};
1918
use rustc_data_structures::indexed_set::{IdxSet};
2019
use rustc_data_structures::indexed_vec::Idx;
@@ -504,7 +503,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> {
504503
let stmt = &mir[location.block].statements[location.statement_index];
505504
let loc_map = &move_data.loc_map;
506505
let path_map = &move_data.path_map;
507-
let bits_per_block = self.bits_per_block();
508506

509507
match stmt.kind {
510508
// this analysis only tries to find moves explicitly
@@ -515,21 +513,15 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> {
515513
_ => {
516514
debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}",
517515
stmt, location, &loc_map[location]);
518-
for move_index in &loc_map[location] {
519-
// Every path deinitialized by a *particular move*
520-
// has corresponding bit, "gen'ed" (i.e. set)
521-
// here, in dataflow vector
522-
zero_to_one(sets.gen_set.words_mut(), *move_index);
523-
}
516+
// Every path deinitialized by a *particular move*
517+
// has corresponding bit, "gen'ed" (i.e. set)
518+
// here, in dataflow vector
519+
sets.gen_all_and_assert_dead(&loc_map[location]);
524520
}
525521
}
526522

527523
for_location_inits(tcx, mir, move_data, location,
528-
|mpi| for moi in &path_map[mpi] {
529-
assert!(moi.index() < bits_per_block);
530-
sets.kill_set.add(&moi);
531-
}
532-
);
524+
|mpi| sets.kill_all(&path_map[mpi]));
533525
}
534526

535527
fn terminator_effect(&self,
@@ -543,18 +535,10 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> {
543535

544536
debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}",
545537
term, location, &loc_map[location]);
546-
let bits_per_block = self.bits_per_block();
547-
for move_index in &loc_map[location] {
548-
assert!(move_index.index() < bits_per_block);
549-
zero_to_one(sets.gen_set.words_mut(), *move_index);
550-
}
538+
sets.gen_all_and_assert_dead(&loc_map[location]);
551539

552540
for_location_inits(tcx, mir, move_data, location,
553-
|mpi| for moi in &path_map[mpi] {
554-
assert!(moi.index() < bits_per_block);
555-
sets.kill_set.add(&moi);
556-
}
557-
);
541+
|mpi| sets.kill_all(&path_map[mpi]));
558542
}
559543

560544
fn propagate_call_return(&self,
@@ -585,11 +569,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> {
585569
}
586570

587571
fn start_block_effect(&self, sets: &mut BlockSets<InitIndex>) {
588-
let bits_per_block = self.bits_per_block();
589-
for init_index in (0..self.mir.arg_count).map(InitIndex::new) {
590-
assert!(init_index.index() < bits_per_block);
591-
sets.gen_set.add(&init_index);
592-
}
572+
sets.gen_all((0..self.mir.arg_count).map(InitIndex::new));
593573
}
594574
fn statement_effect(&self,
595575
sets: &mut BlockSets<InitIndex>,
@@ -599,26 +579,39 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> {
599579
let init_path_map = &move_data.init_path_map;
600580
let init_loc_map = &move_data.init_loc_map;
601581
let rev_lookup = &move_data.rev_lookup;
602-
let bits_per_block = self.bits_per_block();
603582

604583
debug!("statement {:?} at loc {:?} initializes move_indexes {:?}",
605584
stmt, location, &init_loc_map[location]);
606-
for init_index in &init_loc_map[location] {
607-
assert!(init_index.index() < bits_per_block);
608-
sets.gen_set.add(init_index);
609-
}
585+
sets.gen_all(&init_loc_map[location]);
610586

611587
match stmt.kind {
612-
mir::StatementKind::StorageDead(local) => {
613-
// End inits for StorageDead, so that an immutable variable can
614-
// be reinitialized on the next iteration of the loop.
588+
mir::StatementKind::StorageDead(local) |
589+
mir::StatementKind::StorageLive(local) => {
590+
// End inits for StorageDead and StorageLive, so that an immutable
591+
// variable can be reinitialized on the next iteration of the loop.
592+
//
593+
// FIXME(#46525): We *need* to do this for StorageLive as well as
594+
// StorageDead, because lifetimes of match bindings with guards are
595+
// weird - i.e. this code
596+
//
597+
// ```
598+
// fn main() {
599+
// match 0 {
600+
// a | a
601+
// if { println!("a={}", a); false } => {}
602+
// _ => {}
603+
// }
604+
// }
605+
// ```
606+
//
607+
// runs the guard twice, using the same binding for `a`, and only
608+
// storagedeads after everything ends, so if we don't regard the
609+
// storagelive as killing storage, we would have a multiple assignment
610+
// to immutable data error.
615611
if let LookupResult::Exact(mpi) = rev_lookup.find(&mir::Place::Local(local)) {
616612
debug!("stmt {:?} at loc {:?} clears the ever initialized status of {:?}",
617-
stmt, location, &init_path_map[mpi]);
618-
for ii in &init_path_map[mpi] {
619-
assert!(ii.index() < bits_per_block);
620-
sets.kill_set.add(&ii);
621-
}
613+
stmt, location, &init_path_map[mpi]);
614+
sets.kill_all(&init_path_map[mpi]);
622615
}
623616
}
624617
_ => {}
@@ -634,13 +627,11 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> {
634627
let init_loc_map = &move_data.init_loc_map;
635628
debug!("terminator {:?} at loc {:?} initializes move_indexes {:?}",
636629
term, location, &init_loc_map[location]);
637-
let bits_per_block = self.bits_per_block();
638-
for init_index in &init_loc_map[location] {
639-
if move_data.inits[*init_index].kind != InitKind::NonPanicPathOnly {
640-
assert!(init_index.index() < bits_per_block);
641-
sets.gen_set.add(init_index);
642-
}
643-
}
630+
sets.gen_all(
631+
init_loc_map[location].iter().filter(|init_index| {
632+
move_data.inits[**init_index].kind != InitKind::NonPanicPathOnly
633+
})
634+
);
644635
}
645636

646637
fn propagate_call_return(&self,
@@ -663,11 +654,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> {
663654
}
664655
}
665656

666-
fn zero_to_one(bitvec: &mut [usize], move_index: MoveOutIndex) {
667-
let retval = bitvec.set_bit(move_index.index());
668-
assert!(retval);
669-
}
670-
671657
impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeInitializedLvals<'a, 'gcx, 'tcx> {
672658
#[inline]
673659
fn join(&self, pred1: usize, pred2: usize) -> usize {

‎src/librustc_mir/dataflow/mod.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc::ty::{self, TyCtxt};
1818
use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator};
1919
use rustc::session::Session;
2020

21+
use std::borrow::Borrow;
2122
use std::fmt::{self, Debug};
2223
use std::io;
2324
use std::mem;
@@ -492,10 +493,39 @@ impl<'a, E:Idx> BlockSets<'a, E> {
492493
self.gen_set.add(e);
493494
self.kill_set.remove(e);
494495
}
496+
fn gen_all<I>(&mut self, i: I)
497+
where I: IntoIterator,
498+
I::Item: Borrow<E>
499+
{
500+
for j in i {
501+
self.gen(j.borrow());
502+
}
503+
}
504+
505+
fn gen_all_and_assert_dead<I>(&mut self, i: I)
506+
where I: IntoIterator,
507+
I::Item: Borrow<E>
508+
{
509+
for j in i {
510+
let j = j.borrow();
511+
let retval = self.gen_set.add(j);
512+
self.kill_set.remove(j);
513+
assert!(retval);
514+
}
515+
}
516+
495517
fn kill(&mut self, e: &E) {
496518
self.gen_set.remove(e);
497519
self.kill_set.add(e);
498520
}
521+
fn kill_all<I>(&mut self, i: I)
522+
where I: IntoIterator,
523+
I::Item: Borrow<E>
524+
{
525+
for j in i {
526+
self.kill(j.borrow());
527+
}
528+
}
499529
}
500530

501531
impl<E:Idx> AllSets<E> {

‎src/test/compile-fail/borrowck/borrowck-local-borrow-outlives-fn.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
fn cplusplus_mode(x: isize) -> &'static isize {
1515
&x //[ast]~ ERROR `x` does not live long enough
16-
//[mir]~^ ERROR borrowed value does not live long enough
1716
}
17+
//[mir]~^ ERROR borrowed value does not live long enough
1818

1919
fn main() {}

‎src/test/compile-fail/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
fn cplusplus_mode_exceptionally_unsafe(x: &mut Option<&'static mut isize>) {
1515
let mut z = (0, 0);
1616
*x = Some(&mut z.1); //[ast]~ ERROR [E0597]
17-
//[mir]~^ ERROR [E0597]
1817
panic!("catch me for a dangling pointer!")
1918
}
19+
//[mir]~^ ERROR [E0597]
2020

2121
fn main() {
2222
cplusplus_mode_exceptionally_unsafe(&mut None);

‎src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// revisions: ast mir
12+
//[mir]compile-flags: -Z borrowck=mir
13+
1114
#![feature(box_syntax)]
1215

1316
fn call_f<F:FnOnce() -> isize>(f: F) -> isize {
@@ -18,5 +21,6 @@ fn main() {
1821
let t: Box<_> = box 3;
1922

2023
call_f(move|| { *t + 1 });
21-
call_f(move|| { *t + 1 }); //~ ERROR capture of moved value
24+
call_f(move|| { *t + 1 }); //[ast]~ ERROR capture of moved value
25+
//[mir]~^ ERROR use of moved value
2226
}

‎src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,9 @@ fn main() {
2323
1 => { addr = &mut x; } //[ast]~ ERROR [E0499]
2424
//[mir]~^ ERROR [E0499]
2525
2 => { addr = &mut x; } //[ast]~ ERROR [E0499]
26-
//[mir]~^ ERROR [E0506]
27-
//[mir]~| ERROR [E0499]
28-
//[mir]~| ERROR [E0499]
26+
//[mir]~^ ERROR [E0499]
2927
_ => { addr = &mut x; } //[ast]~ ERROR [E0499]
30-
//[mir]~^ ERROR [E0506]
31-
//[mir]~| ERROR [E0499]
32-
//[mir]~| ERROR [E0499]
28+
//[mir]~^ ERROR [E0499]
3329
}
3430
}
3531
}
36-
37-

‎src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// ignore-test will be fixed later
1112
// revisions: ast mir
1213
//[mir]compile-flags: -Z borrowck=mir
1314

‎src/test/compile-fail/borrowck/borrowck-union-borrow.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,12 @@ fn main() {
5252
{
5353
let ra = &u.a;
5454
let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
55-
// FIXME Error for MIR (needs support for union)
55+
//[mir]~^ ERROR cannot borrow `u.b` as mutable because it is also borrowed as immutable
5656
}
5757
{
5858
let ra = &u.a;
5959
u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
60-
// FIXME Error for MIR (needs support for union)
60+
//[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
6161
}
6262
// Mut borrow, same field
6363
{
@@ -84,22 +84,23 @@ fn main() {
8484
{
8585
let rma = &mut u.a;
8686
let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
87-
// FIXME Error for MIR (needs support for union)
87+
//[mir]~^ ERROR cannot borrow `u.b` as immutable because it is also borrowed as mutable
8888
}
8989
{
9090
let ra = &mut u.a;
9191
let b = u.b; //[ast]~ ERROR cannot use `u.b` because it was mutably borrowed
92-
// FIXME Error for MIR (needs support for union)
92+
//[mir]~^ ERROR cannot use `u.b` because it was mutably borrowed
93+
9394
}
9495
{
9596
let rma = &mut u.a;
9697
let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
97-
// FIXME Error for MIR (needs support for union)
98+
//[mir]~^ ERROR cannot borrow `u.b` as mutable more than once at a time
9899
}
99100
{
100101
let rma = &mut u.a;
101102
u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
102-
// FIXME Error for MIR (needs support for union)
103+
//[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
103104
}
104105
}
105106
}

‎src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
23
// file at the top-level directory of this distribution and at
34
// http://rust-lang.org/COPYRIGHT.
@@ -22,7 +23,7 @@ fn main() {
2223
println!("t[0]: {}", t[0]);
2324
a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed
2425
//[cmp]~^ ERROR cannot assign to `a[..]` because it is borrowed (Ast)
25-
// FIXME Error for MIR (error missed)
26+
//[cmp]~| ERROR cannot assign to `a[..]` because it is borrowed (Mir)
2627
println!("t[0]: {}", t[0]);
2728
t[0];
2829
}

‎src/test/compile-fail/issue-25579.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,9 @@ fn causes_ice(mut l: &mut Sexpression) {
2020
loop { match l {
2121
&mut Sexpression::Num(ref mut n) => {},
2222
&mut Sexpression::Cons(ref mut expr) => { //[ast]~ ERROR [E0499]
23-
//[mir]~^ ERROR [E0506]
24-
//[mir]~| ERROR [E0499]
23+
//[mir]~^ ERROR [E0499]
2524
l = &mut **expr; //[ast]~ ERROR [E0506]
2625
//[mir]~^ ERROR [E0506]
27-
//[mir]~| ERROR [E0506]
28-
//[mir]~| ERROR [E0499]
29-
//[mir]~| ERROR [E0499]
3026
}
3127
}}
3228
}

‎src/test/compile-fail/region-borrow-params-issue-29793-big.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
// behavior (because the improperly accepted closure was actually
1717
// able to be invoked).
1818

19+
// ignore-tidy-linelength
20+
// revisions: ast mir
21+
//[mir]compile-flags: -Z borrowck=mir
22+
1923
struct WrapA<F>(Option<F>);
2024

2125
impl<F> WrapA<F> {
@@ -75,9 +79,11 @@ impl<F, T> WrapA<F>
7579
fn main() {
7680
let mut w = WrapA::new().set(|x: usize, y: usize| {
7781
WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
78-
//~^ ERROR `x` does not live long enough
79-
//~| ERROR `y` does not live long enough
82+
//[ast]~^ ERROR `x` does not live long enough
83+
//[ast]~| ERROR `y` does not live long enough
8084
});
85+
//[mir]~^ ERROR borrowed value does not live long enough
86+
//[mir]~| ERROR borrowed value does not live long enough
8187

8288
w.handle(); // This works
8389
// w.handle_ref(); // This doesn't

‎src/test/run-pass/match-pipe-binding.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// compile-flags: -Z borrowck=compare
1112

1213
fn test1() {
1314
// from issue 6338

0 commit comments

Comments
 (0)
Please sign in to comment.