@@ -385,7 +385,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
385
385
// borrow of immutable ref, moves through non-`Box`-ref)
386
386
let ( sd, rw) = kind;
387
387
self . each_borrow_involving_path (
388
- context, ( sd, lvalue_span. 0 ) , flow_state, |this, _index, borrow| {
388
+ context, ( sd, lvalue_span. 0 ) , flow_state, |this, _index, borrow, common_prefix | {
389
389
match ( rw, borrow. kind ) {
390
390
( Read ( _) , BorrowKind :: Shared ) => {
391
391
Control :: Continue
@@ -399,6 +399,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
399
399
ReadKind :: Borrow ( bk) =>
400
400
this. report_conflicting_borrow (
401
401
context, lvalue_span,
402
+ common_prefix,
402
403
( lvalue_span. 0 , bk) , ( & borrow. lvalue , borrow. kind ) ) ,
403
404
}
404
405
Control :: Break
@@ -408,6 +409,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
408
409
WriteKind :: MutableBorrow ( bk) =>
409
410
this. report_conflicting_borrow (
410
411
context, lvalue_span,
412
+ common_prefix,
411
413
( lvalue_span. 0 , bk) , ( & borrow. lvalue , borrow. kind ) ) ,
412
414
WriteKind :: StorageDead |
413
415
WriteKind :: Mutate =>
@@ -704,7 +706,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
704
706
access_lvalue : ( ShallowOrDeep , & Lvalue < ' gcx > ) ,
705
707
flow_state : & InProgress < ' b , ' gcx > ,
706
708
mut op : F )
707
- where F : FnMut ( & mut Self , BorrowIndex , & BorrowData < ' gcx > ) -> Control
709
+ where F : FnMut ( & mut Self , BorrowIndex , & BorrowData < ' gcx > , & Lvalue ) -> Control
708
710
{
709
711
let ( access, lvalue) = access_lvalue;
710
712
@@ -726,9 +728,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
726
728
// to #38899. Will probably need back-compat mode flag.
727
729
for accessed_prefix in self . prefixes ( lvalue, PrefixSet :: All ) {
728
730
if * accessed_prefix == borrowed. lvalue {
729
- // FIXME: pass in prefix here too? And/or enum
730
- // describing case we are in?
731
- let ctrl = op ( self , i, borrowed) ;
731
+ // FIXME: pass in enum describing case we are in?
732
+ let ctrl = op ( self , i, borrowed, accessed_prefix) ;
732
733
if ctrl == Control :: Break { return ; }
733
734
}
734
735
}
@@ -753,9 +754,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
753
754
754
755
for borrowed_prefix in self . prefixes ( & borrowed. lvalue , prefix_kind) {
755
756
if borrowed_prefix == lvalue {
756
- // FIXME: pass in prefix here too? And/or enum
757
- // describing case we are in?
758
- let ctrl = op ( self , i, borrowed) ;
757
+ // FIXME: pass in enum describing case we are in?
758
+ let ctrl = op ( self , i, borrowed, borrowed_prefix) ;
759
759
if ctrl == Control :: Break { return ; }
760
760
}
761
761
}
@@ -780,6 +780,30 @@ mod prefixes {
780
780
use rustc:: ty:: { self , TyCtxt } ;
781
781
use rustc:: mir:: { Lvalue , Mir , ProjectionElem } ;
782
782
783
+ pub trait IsPrefixOf < ' tcx > {
784
+ fn is_prefix_of ( & self , other : & Lvalue < ' tcx > ) -> bool ;
785
+ }
786
+
787
+ impl < ' tcx > IsPrefixOf < ' tcx > for Lvalue < ' tcx > {
788
+ fn is_prefix_of ( & self , other : & Lvalue < ' tcx > ) -> bool {
789
+ let mut cursor = other;
790
+ loop {
791
+ if self == cursor {
792
+ return true ;
793
+ }
794
+
795
+ match * cursor {
796
+ Lvalue :: Local ( _) |
797
+ Lvalue :: Static ( _) => return false ,
798
+ Lvalue :: Projection ( ref proj) => {
799
+ cursor = & proj. base ;
800
+ }
801
+ }
802
+ }
803
+ }
804
+ }
805
+
806
+
783
807
pub ( super ) struct Prefixes < ' c , ' tcx : ' c > {
784
808
mir : & ' c Mir < ' tcx > ,
785
809
tcx : TyCtxt < ' c , ' tcx , ' tcx > ,
@@ -943,12 +967,16 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
943
967
fn report_conflicting_borrow ( & mut self ,
944
968
_context : Context ,
945
969
( lvalue, span) : ( & Lvalue , Span ) ,
970
+ common_prefix : & Lvalue ,
946
971
loan1 : ( & Lvalue , BorrowKind ) ,
947
972
loan2 : ( & Lvalue , BorrowKind ) ) {
973
+ use self :: prefixes:: IsPrefixOf ;
974
+
948
975
let ( loan1_lvalue, loan1_kind) = loan1;
949
976
let ( loan2_lvalue, loan2_kind) = loan2;
950
- // FIXME: obviously falsifiable. Generalize for non-eq lvalues later.
951
- assert_eq ! ( loan1_lvalue, loan2_lvalue) ;
977
+
978
+ assert ! ( common_prefix. is_prefix_of( loan1_lvalue) ) ;
979
+ assert ! ( common_prefix. is_prefix_of( loan2_lvalue) ) ;
952
980
953
981
// FIXME: supply non-"" `opt_via` when appropriate
954
982
let mut err = match ( loan1_kind, "immutable" , "mutable" ,
0 commit comments