Skip to content

Commit 0c902cf

Browse files
Complete implementation of invalidates facts
1 parent 3b36fa8 commit 0c902cf

File tree

2 files changed

+60
-36
lines changed

2 files changed

+60
-36
lines changed

src/librustc_mir/borrow_check/nll/invalidation.rs

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,64 +17,70 @@ use borrow_check::{Context, ContextKind};
1717
use borrow_check::{LocalMutationIsAllowed, MutateMode};
1818
use borrow_check::ArtificialField;
1919
use borrow_check::{ReadKind, WriteKind, Overlap};
20-
use borrow_check::nll::region_infer::RegionInferenceContext;
2120
use borrow_check::nll::facts::AllFacts;
2221
use dataflow::move_paths::indexes::BorrowIndex;
2322
use rustc::hir;
23+
use rustc::hir::def_id::DefId;
2424
use rustc::infer::InferCtxt;
2525
use rustc::mir::visit::Visitor;
2626
use rustc::mir::{BasicBlock, Location, Mir, Place, Rvalue, Projection};
2727
use rustc::mir::{Local, ProjectionElem};
2828
use rustc::mir::{Statement, StatementKind};
2929
use rustc::mir::{Terminator, TerminatorKind};
3030
use rustc::mir::{Field, Operand, BorrowKind};
31-
use rustc::ty;
31+
use rustc::ty::{self, ParamEnv};
3232
use rustc_data_structures::indexed_vec::Idx;
3333
use std::iter;
3434

3535
pub(super) fn generate_invalidates<'cx, 'gcx, 'tcx>(
3636
infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
37-
regioncx: &mut RegionInferenceContext<'tcx>,
3837
all_facts: &mut Option<AllFacts>,
3938
location_table: &LocationTable,
4039
mir: &Mir<'tcx>,
40+
mir_def_id: DefId,
4141
borrow_set: &BorrowSet<'tcx>,
4242
) {
4343
if !all_facts.is_some() {
4444
// Nothing to do if we don't have any facts
4545
return;
4646
}
4747

48-
let mut ig = InvalidationGenerator {
49-
all_facts: &mut all_facts.unwrap(),
50-
borrow_set,
51-
infcx,
52-
regioncx,
53-
location_table,
54-
mir,
55-
};
48+
let param_env = infcx.tcx.param_env(mir_def_id);
49+
50+
let mut all_facts_taken = all_facts.take().unwrap();
51+
{
52+
let mut ig = InvalidationGenerator {
53+
all_facts: &mut all_facts_taken,
54+
borrow_set,
55+
infcx,
56+
location_table,
57+
mir,
58+
param_env,
59+
};
60+
ig.visit_mir(mir);
61+
}
62+
*all_facts = Some(all_facts_taken);
5663
}
5764

5865
/// 'cg = the duration of the constraint generation process itself.
59-
struct InvalidationGenerator<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> {
66+
struct InvalidationGenerator<'cg, 'cx: 'cg, 'tcx: 'cx, 'gcx: 'tcx> {
6067
infcx: &'cg InferCtxt<'cx, 'gcx, 'tcx>,
6168
all_facts: &'cg mut AllFacts,
6269
location_table: &'cg LocationTable,
63-
regioncx: &'cg mut RegionInferenceContext<'tcx>,
6470
mir: &'cg Mir<'tcx>,
6571
borrow_set: &'cg BorrowSet<'tcx>,
72+
param_env: ParamEnv<'gcx>,
6673
}
6774

6875
/// Visits the whole MIR and generates invalidates() facts
6976
/// Most of the code implementing this was stolen from borrow_check/mod.rs
70-
impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> Visitor<'tcx> for InvalidationGenerator<'cg, 'cx, 'gcx, 'tcx> {
77+
impl<'cg, 'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cg, 'cx, 'tcx, 'gcx> {
7178
fn visit_statement(&mut self, block: BasicBlock, statement: &Statement<'tcx>, location: Location) {
7279
match statement.kind {
7380
StatementKind::Assign(ref lhs, ref rhs) => {
7481
self.consume_rvalue(
7582
ContextKind::AssignRhs.new(location),
7683
rhs,
77-
location
7884
);
7985

8086
self.mutate_place(
@@ -170,6 +176,7 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> Visitor<'tcx> for InvalidationGenerat
170176
let gcx = tcx.global_tcx();
171177
let drop_place_ty = drop_place.ty(self.mir, tcx);
172178
let drop_place_ty = tcx.erase_regions(&drop_place_ty).to_ty(tcx);
179+
let drop_place_ty = gcx.lift(&drop_place_ty).unwrap();
173180
self.visit_terminator_drop(location, terminator, drop_place, drop_place_ty);
174181
}
175182
TerminatorKind::DropAndReplace {
@@ -275,7 +282,7 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> Visitor<'tcx> for InvalidationGenerat
275282
}
276283
}
277284

278-
impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx, 'tcx> {
285+
impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cg, 'cx, 'tcx, 'gcx> {
279286
/// Simulates dropping of a variable
280287
fn visit_terminator_drop(
281288
&mut self,
@@ -286,10 +293,10 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx,
286293
) {
287294
let gcx = self.infcx.tcx.global_tcx();
288295
let drop_field = |
289-
ig: &mut InvalidationGenerator<'cg, 'cx, 'gcx, 'tcx>,
290-
(index, field): (usize, ty::Ty<'gcx>),
296+
ig: &mut InvalidationGenerator<'cg, 'cx, 'gcx, 'tcx>,
297+
(index, field): (usize, ty::Ty<'gcx>),
291298
| {
292-
let field_ty = gcx.normalize_erasing_regions(self.mir.param_env, field);
299+
let field_ty = gcx.normalize_erasing_regions(ig.param_env, field);
293300
let place = drop_place.clone().field(Field::new(index), field_ty);
294301

295302
ig.visit_terminator_drop(loc, term, &place, field_ty);
@@ -351,7 +358,7 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx,
351358
context: Context,
352359
place: &Place<'tcx>,
353360
kind: ShallowOrDeep,
354-
mode: MutateMode,
361+
_mode: MutateMode,
355362
) {
356363
self.access_place(
357364
context,
@@ -393,7 +400,6 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx,
393400
&mut self,
394401
context: Context,
395402
rvalue: &Rvalue<'tcx>,
396-
location: Location,
397403
) {
398404
match *rvalue {
399405
Rvalue::Ref(_ /*rgn*/, bk, ref place) => {
@@ -447,7 +453,7 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx,
447453
Rvalue::NullaryOp(_op, _ty) => {
448454
}
449455

450-
Rvalue::Aggregate(ref aggregate_kind, ref operands) => {
456+
Rvalue::Aggregate(_, ref operands) => {
451457
for operand in operands {
452458
self.consume_operand(context, operand);
453459
}
@@ -461,7 +467,7 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx,
461467
context: Context,
462468
place: &Place<'tcx>,
463469
kind: (ShallowOrDeep, ReadOrWrite),
464-
is_local_mutation_allowed: LocalMutationIsAllowed,
470+
_is_local_mutation_allowed: LocalMutationIsAllowed,
465471
) {
466472
let (sd, rw) = kind;
467473
// note: not doing check_access_permissions checks because they don't generate invalidates
@@ -502,7 +508,7 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx,
502508
// Reads/reservations don't invalidate shared borrows
503509
}
504510

505-
(Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut { .. }) => {
511+
(Read(_), BorrowKind::Unique) | (Read(_), BorrowKind::Mut { .. }) => {
506512
// Reading from mere reservations of mutable-borrows is OK.
507513
if !this.is_active(borrow, context.loc) {
508514
// If the borrow isn't active yet, reads don't invalidate it
@@ -512,20 +518,13 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx,
512518

513519
// Unique and mutable borrows are invalidated by reads from any
514520
// involved path
515-
match kind {
516-
ReadKind::Copy => {
517-
this.generate_invalidates(borrow_index, context.loc);
518-
}
519-
ReadKind::Borrow(bk) => {
520-
this.generate_invalidates(borrow_index, context.loc);
521-
}
522-
}
521+
this.generate_invalidates(borrow_index, context.loc);
523522
}
524523

525-
(Reservation(kind), BorrowKind::Unique)
526-
| (Reservation(kind), BorrowKind::Mut { .. })
527-
| (Activation(kind, _), _)
528-
| (Write(kind), _) => {
524+
(Reservation(_), BorrowKind::Unique)
525+
| (Reservation(_), BorrowKind::Mut { .. })
526+
| (Activation(_, _), _)
527+
| (Write(_), _) => {
529528
// unique or mutable borrows are invalidated by writes.
530529
// Reservations count as writes since we need to check
531530
// that activating the borrow will be OK
@@ -588,6 +587,23 @@ impl<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> InvalidationGenerator<'cg, 'cx, 'gcx,
588587
}
589588
}
590589

590+
/// Determine if a given two-phase borrow is active using dominator information
591+
fn is_active(&self, borrow: &BorrowData, location: Location) -> bool {
592+
// If it's not two-phase, the borrow is definitely active
593+
if !self.allow_two_phase_borrow(borrow.kind) {
594+
return true;
595+
}
596+
if borrow.activation_location.is_none() {
597+
return false;
598+
}
599+
let activation_location = borrow.activation_location.unwrap();
600+
if activation_location.block == location.block {
601+
activation_location.statement_index >= location.statement_index
602+
} else {
603+
self.mir.dominators().is_dominated_by(location.block, activation_location.block)
604+
}
605+
}
606+
591607
/// Returns whether an access of kind `access` to `access_place` conflicts with
592608
/// a borrow/full access to `borrow_place` (for deep accesses to mutable
593609
/// locations, this function is symmetric between `borrow_place` & `access_place`).

src/librustc_mir/borrow_check/nll/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,14 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
131131
&mir,
132132
borrow_set,
133133
);
134+
invalidation::generate_invalidates(
135+
infcx,
136+
&mut all_facts,
137+
location_table,
138+
&mir,
139+
def_id,
140+
borrow_set
141+
);
134142

135143
// Dump facts if requested.
136144
if let Some(all_facts) = all_facts {

0 commit comments

Comments
 (0)