@@ -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.
@@ -190,7 +230,7 @@ fn place_components_conflict<'gcx, 'tcx>(
190230 bug ! ( "Tracking borrow behind shared reference." ) ;
191231 }
192232 ( ProjectionElem :: Deref , ty:: Ref ( _, _, hir:: MutMutable ) , AccessDepth :: Drop ) => {
193- // Values behind a mutatble reference are not access either by Dropping a
233+ // Values behind a mutable reference are not access either by dropping a
194234 // value, or by StorageDead
195235 debug ! ( "borrow_conflicts_with_place: drop access behind ptr" ) ;
196236 return false ;
@@ -328,6 +368,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
328368 mir : & Mir < ' tcx > ,
329369 elem1 : & Place < ' tcx > ,
330370 elem2 : & Place < ' tcx > ,
371+ bias : PlaceConflictBias ,
331372) -> Overlap {
332373 match ( elem1, elem2) {
333374 ( Place :: Local ( l1) , Place :: Local ( l2) ) => {
@@ -445,10 +486,20 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
445486 | ( ProjectionElem :: ConstantIndex { .. } , ProjectionElem :: Index ( ..) )
446487 | ( ProjectionElem :: Subslice { .. } , ProjectionElem :: Index ( ..) ) => {
447488 // Array indexes (`a[0]` vs. `a[i]`). These can either be disjoint
448- // (if the indexes differ) or equal (if they are the same), so this
449- // is the recursive case that gives "equal *or* disjoint" its meaning.
450- debug ! ( "place_element_conflict: DISJOINT-OR-EQ-ARRAY-INDEX" ) ;
451- Overlap :: EqualOrDisjoint
489+ // (if the indexes differ) or equal (if they are the same).
490+ match bias {
491+ PlaceConflictBias :: Overlap => {
492+ // If we are biased towards overlapping, then this is the recursive
493+ // case that gives "equal *or* disjoint" its meaning.
494+ debug ! ( "place_element_conflict: DISJOINT-OR-EQ-ARRAY-INDEX" ) ;
495+ Overlap :: EqualOrDisjoint
496+ }
497+ PlaceConflictBias :: NoOverlap => {
498+ // If we are biased towards no overlapping, then this is disjoint.
499+ debug ! ( "place_element_conflict: DISJOINT-ARRAY-INDEX" ) ;
500+ Overlap :: Disjoint
501+ }
502+ }
452503 }
453504 ( ProjectionElem :: ConstantIndex { offset : o1, min_length : _, from_end : false } ,
454505 ProjectionElem :: ConstantIndex { offset : o2, min_length : _, from_end : false } )
0 commit comments