@@ -17,17 +17,55 @@ use rustc::mir::{Projection, ProjectionElem};
1717use rustc:: ty:: { self , TyCtxt } ;
1818use std:: cmp:: max;
1919
20+ /// When checking if a place conflicts with another place, this enum is used to influence decisions
21+ /// where a place might be equal or disjoint with another place, such as if `a[i] == a[j]`.
22+ /// `PlaceConflictBias::Overlap` would bias toward assuming that `i` might equal `j` and that these
23+ /// places overlap. `PlaceConflictBias::NoOverlap` assumes that for the purposes of the predicate
24+ /// being run in the calling context, the conservative choice is to assume the compared indices
25+ /// are disjoint (and therefore, do not overlap).
26+ #[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
27+ crate enum PlaceConflictBias {
28+ Overlap ,
29+ NoOverlap ,
30+ }
31+
32+ /// Helper function for checking if places conflict with a mutable borrow and deep access depth.
33+ /// This is used to check for places conflicting outside of the borrow checking code (such as in
34+ /// dataflow).
35+ crate fn places_conflict < ' gcx , ' tcx > (
36+ tcx : TyCtxt < ' _ , ' gcx , ' tcx > ,
37+ mir : & Mir < ' tcx > ,
38+ borrow_place : & Place < ' tcx > ,
39+ access_place : & Place < ' tcx > ,
40+ bias : PlaceConflictBias ,
41+ ) -> bool {
42+ borrow_conflicts_with_place (
43+ tcx,
44+ mir,
45+ borrow_place,
46+ BorrowKind :: Mut { allow_two_phase_borrow : true } ,
47+ access_place,
48+ AccessDepth :: Deep ,
49+ bias,
50+ )
51+ }
52+
53+ /// Checks whether the `borrow_place` conflicts with the `access_place` given a borrow kind and
54+ /// access depth. The `bias` parameter is used to determine how the unknowable (comparing runtime
55+ /// array indices, for example) should be interpreted - this depends on what the caller wants in
56+ /// order to make the conservative choice and preserve soundness.
2057pub ( super ) fn borrow_conflicts_with_place < ' gcx , ' tcx > (
2158 tcx : TyCtxt < ' _ , ' gcx , ' tcx > ,
2259 mir : & Mir < ' tcx > ,
2360 borrow_place : & Place < ' tcx > ,
2461 borrow_kind : BorrowKind ,
2562 access_place : & Place < ' tcx > ,
2663 access : AccessDepth ,
64+ bias : PlaceConflictBias ,
2765) -> bool {
2866 debug ! (
29- "borrow_conflicts_with_place({:?},{:?},{:?})" ,
30- borrow_place, access_place, access
67+ "borrow_conflicts_with_place({:?}, {:?}, {:?}, {:?})" ,
68+ borrow_place, access_place, access, bias ,
3169 ) ;
3270
3371 // This Local/Local case is handled by the more general code below, but
@@ -46,7 +84,8 @@ pub(super) fn borrow_conflicts_with_place<'gcx, 'tcx>(
4684 borrow_components,
4785 borrow_kind,
4886 access_components,
49- access
87+ access,
88+ bias,
5089 )
5190 } )
5291 } )
@@ -59,6 +98,7 @@ fn place_components_conflict<'gcx, 'tcx>(
5998 borrow_kind : BorrowKind ,
6099 mut access_components : PlaceComponentsIter < ' _ , ' tcx > ,
61100 access : AccessDepth ,
101+ bias : PlaceConflictBias ,
62102) -> bool {
63103 // The borrowck rules for proving disjointness are applied from the "root" of the
64104 // borrow forwards, iterating over "similar" projections in lockstep until
@@ -121,7 +161,7 @@ fn place_components_conflict<'gcx, 'tcx>(
121161 // check whether the components being borrowed vs
122162 // accessed are disjoint (as in the second example,
123163 // but not the first).
124- match place_element_conflict ( tcx, mir, borrow_c, access_c) {
164+ match place_element_conflict ( tcx, mir, borrow_c, access_c, bias ) {
125165 Overlap :: Arbitrary => {
126166 // We have encountered different fields of potentially
127167 // the same union - the borrow now partially overlaps.
@@ -193,7 +233,7 @@ fn place_components_conflict<'gcx, 'tcx>(
193233 bug ! ( "Tracking borrow behind shared reference." ) ;
194234 }
195235 ( ProjectionElem :: Deref , ty:: Ref ( _, _, hir:: MutMutable ) , AccessDepth :: Drop ) => {
196- // Values behind a mutatble reference are not access either by Dropping a
236+ // Values behind a mutable reference are not access either by dropping a
197237 // value, or by StorageDead
198238 debug ! ( "borrow_conflicts_with_place: drop access behind ptr" ) ;
199239 return false ;
@@ -331,6 +371,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
331371 mir : & Mir < ' tcx > ,
332372 elem1 : & Place < ' tcx > ,
333373 elem2 : & Place < ' tcx > ,
374+ bias : PlaceConflictBias ,
334375) -> Overlap {
335376 match ( elem1, elem2) {
336377 ( Place :: Local ( l1) , Place :: Local ( l2) ) => {
@@ -448,10 +489,20 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
448489 | ( ProjectionElem :: ConstantIndex { .. } , ProjectionElem :: Index ( ..) )
449490 | ( ProjectionElem :: Subslice { .. } , ProjectionElem :: Index ( ..) ) => {
450491 // Array indexes (`a[0]` vs. `a[i]`). These can either be disjoint
451- // (if the indexes differ) or equal (if they are the same), so this
452- // is the recursive case that gives "equal *or* disjoint" its meaning.
453- debug ! ( "place_element_conflict: DISJOINT-OR-EQ-ARRAY-INDEX" ) ;
454- Overlap :: EqualOrDisjoint
492+ // (if the indexes differ) or equal (if they are the same).
493+ match bias {
494+ PlaceConflictBias :: Overlap => {
495+ // If we are biased towards overlapping, then this is the recursive
496+ // case that gives "equal *or* disjoint" its meaning.
497+ debug ! ( "place_element_conflict: DISJOINT-OR-EQ-ARRAY-INDEX" ) ;
498+ Overlap :: EqualOrDisjoint
499+ }
500+ PlaceConflictBias :: NoOverlap => {
501+ // If we are biased towards no overlapping, then this is disjoint.
502+ debug ! ( "place_element_conflict: DISJOINT-ARRAY-INDEX" ) ;
503+ Overlap :: Disjoint
504+ }
505+ }
455506 }
456507 ( ProjectionElem :: ConstantIndex { offset : o1, min_length : _, from_end : false } ,
457508 ProjectionElem :: ConstantIndex { offset : o2, min_length : _, from_end : false } )
0 commit comments