Skip to content

Commit 8fa24bb

Browse files
committed
generate reborrow constraints at type check time
1 parent fbb7306 commit 8fa24bb

File tree

4 files changed

+154
-152
lines changed

4 files changed

+154
-152
lines changed

src/librustc_mir/borrow_check/nll/constraint_generation.rs

Lines changed: 1 addition & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,11 @@ use borrow_check::location::LocationTable;
1313
use borrow_check::nll::ToRegionVid;
1414
use borrow_check::nll::facts::AllFacts;
1515
use borrow_check::nll::region_infer::RegionInferenceContext;
16-
use borrow_check::nll::type_check::AtLocation;
17-
use rustc::hir;
1816
use rustc::infer::InferCtxt;
1917
use rustc::mir::visit::TyContext;
2018
use rustc::mir::visit::Visitor;
21-
use rustc::mir::Place::Projection;
2219
use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue};
23-
use rustc::mir::{Local, PlaceProjection, ProjectionElem, Statement, Terminator};
20+
use rustc::mir::{Local, Statement, Terminator};
2421
use rustc::ty::fold::TypeFoldable;
2522
use rustc::ty::subst::Substs;
2623
use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts};
@@ -41,7 +38,6 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
4138
regioncx,
4239
location_table,
4340
all_facts,
44-
mir,
4541
};
4642

4743
cg.add_region_liveness_constraints_from_type_check(liveness_set_from_typeck);
@@ -57,7 +53,6 @@ struct ConstraintGeneration<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> {
5753
all_facts: &'cg mut Option<AllFacts>,
5854
location_table: &'cg LocationTable,
5955
regioncx: &'cg mut RegionInferenceContext<'tcx>,
60-
mir: &'cg Mir<'tcx>,
6156
borrow_set: &'cg BorrowSet<'tcx>,
6257
}
6358

@@ -184,41 +179,6 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
184179
self.super_terminator(block, terminator, location);
185180
}
186181

187-
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
188-
debug!("visit_rvalue(rvalue={:?}, location={:?})", rvalue, location);
189-
190-
match rvalue {
191-
Rvalue::Ref(region, _borrow_kind, borrowed_place) => {
192-
// In some cases, e.g. when borrowing from an unsafe
193-
// place, we don't bother to create a loan, since
194-
// there are no conditions to validate.
195-
if let Some(all_facts) = self.all_facts {
196-
if let Some(borrow_index) = self.borrow_set.location_map.get(&location) {
197-
let region_vid = region.to_region_vid();
198-
all_facts.borrow_region.push((
199-
region_vid,
200-
*borrow_index,
201-
self.location_table.mid_index(location),
202-
));
203-
}
204-
}
205-
206-
// Look for an rvalue like:
207-
//
208-
// & L
209-
//
210-
// where L is the path that is borrowed. In that case, we have
211-
// to add the reborrow constraints (which don't fall out
212-
// naturally from the type-checker).
213-
self.add_reborrow_constraint(location, region, borrowed_place);
214-
}
215-
216-
_ => {}
217-
}
218-
219-
self.super_rvalue(rvalue, location);
220-
}
221-
222182
fn visit_user_assert_ty(
223183
&mut self,
224184
_c_ty: &CanonicalTy<'tcx>,
@@ -285,100 +245,4 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
285245
self.regioncx.add_live_point(vid, location);
286246
});
287247
}
288-
289-
// Add the reborrow constraint at `location` so that `borrowed_place`
290-
// is valid for `borrow_region`.
291-
fn add_reborrow_constraint(
292-
&mut self,
293-
location: Location,
294-
borrow_region: ty::Region<'tcx>,
295-
borrowed_place: &Place<'tcx>,
296-
) {
297-
let mut borrowed_place = borrowed_place;
298-
299-
debug!(
300-
"add_reborrow_constraint({:?}, {:?}, {:?})",
301-
location, borrow_region, borrowed_place
302-
);
303-
while let Projection(box PlaceProjection { base, elem }) = borrowed_place {
304-
debug!("add_reborrow_constraint - iteration {:?}", borrowed_place);
305-
306-
match *elem {
307-
ProjectionElem::Deref => {
308-
let tcx = self.infcx.tcx;
309-
let base_ty = base.ty(self.mir, tcx).to_ty(tcx);
310-
311-
debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
312-
match base_ty.sty {
313-
ty::TyRef(ref_region, _, mutbl) => {
314-
self.regioncx.add_outlives(
315-
location.boring(),
316-
ref_region.to_region_vid(),
317-
borrow_region.to_region_vid(),
318-
);
319-
320-
if let Some(all_facts) = self.all_facts {
321-
all_facts.outlives.push((
322-
ref_region.to_region_vid(),
323-
borrow_region.to_region_vid(),
324-
self.location_table.mid_index(location),
325-
));
326-
}
327-
328-
match mutbl {
329-
hir::Mutability::MutImmutable => {
330-
// Immutable reference. We don't need the base
331-
// to be valid for the entire lifetime of
332-
// the borrow.
333-
break;
334-
}
335-
hir::Mutability::MutMutable => {
336-
// Mutable reference. We *do* need the base
337-
// to be valid, because after the base becomes
338-
// invalid, someone else can use our mutable deref.
339-
340-
// This is in order to make the following function
341-
// illegal:
342-
// ```
343-
// fn unsafe_deref<'a, 'b>(x: &'a &'b mut T) -> &'b mut T {
344-
// &mut *x
345-
// }
346-
// ```
347-
//
348-
// As otherwise you could clone `&mut T` using the
349-
// following function:
350-
// ```
351-
// fn bad(x: &mut T) -> (&mut T, &mut T) {
352-
// let my_clone = unsafe_deref(&'a x);
353-
// ENDREGION 'a;
354-
// (my_clone, x)
355-
// }
356-
// ```
357-
}
358-
}
359-
}
360-
ty::TyRawPtr(..) => {
361-
// deref of raw pointer, guaranteed to be valid
362-
break;
363-
}
364-
ty::TyAdt(def, _) if def.is_box() => {
365-
// deref of `Box`, need the base to be valid - propagate
366-
}
367-
_ => bug!("unexpected deref ty {:?} in {:?}", base_ty, borrowed_place),
368-
}
369-
}
370-
ProjectionElem::Field(..)
371-
| ProjectionElem::Downcast(..)
372-
| ProjectionElem::Index(..)
373-
| ProjectionElem::ConstantIndex { .. }
374-
| ProjectionElem::Subslice { .. } => {
375-
// other field access
376-
}
377-
}
378-
379-
// The "propagate" case. We need to check that our base is valid
380-
// for the borrow's lifetime.
381-
borrowed_place = base;
382-
}
383-
}
384248
}

src/librustc_mir/borrow_check/nll/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
108108
def_id,
109109
&universal_regions,
110110
location_table,
111+
borrow_set,
111112
&liveness,
112113
&mut all_facts,
113114
flow_inits,

src/librustc_mir/borrow_check/nll/region_infer/mod.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -333,17 +333,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
333333
self.liveness_constraints.add_element(v, element)
334334
}
335335

336-
/// Indicates that the region variable `sup` must outlive `sub` is live at the point `point`.
337-
pub(super) fn add_outlives(&mut self, locations: Locations, sup: RegionVid, sub: RegionVid) {
338-
assert!(self.inferred_values.is_none(), "values already inferred");
339-
self.constraints.push(OutlivesConstraint {
340-
locations,
341-
sup,
342-
sub,
343-
next: None,
344-
})
345-
}
346-
347336
/// Perform region inference and report errors if we see any
348337
/// unsatisfiable constraints. If this is a closure, returns the
349338
/// region requirements to propagate to our creator, if any.

0 commit comments

Comments
 (0)