@@ -35,6 +35,7 @@ use dataflow::{MovingOutStatements};
35
35
use dataflow:: { Borrows , BorrowData , BorrowIndex } ;
36
36
use dataflow:: move_paths:: { MoveError , IllegalMoveOriginKind } ;
37
37
use dataflow:: move_paths:: { HasMoveData , MoveData , MovePathIndex , LookupResult , MoveOutIndex } ;
38
+ use dataflow:: abs_domain:: Lift ;
38
39
use util:: borrowck_errors:: { BorrowckErrors , Origin } ;
39
40
40
41
use self :: MutateMode :: { JustWrite , WriteAndRead } ;
@@ -841,15 +842,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
841
842
-> Result < MovePathIndex , NoMovePathFound >
842
843
{
843
844
let mut last_prefix = lvalue;
844
- for prefix in self . prefixes ( lvalue, PrefixSet :: All ) {
845
+ for prefix in self . prefixes ( lvalue) {
845
846
if let Some ( mpi) = self . move_path_for_lvalue ( prefix) {
846
847
return Ok ( mpi) ;
847
848
}
848
849
last_prefix = prefix;
849
850
}
850
851
match * last_prefix {
851
852
Lvalue :: Local ( _) => panic ! ( "should have move path for every Local" ) ,
852
- Lvalue :: Projection ( _) => panic ! ( "PrefixSet::All meant dont stop for Projection" ) ,
853
+ Lvalue :: Projection ( _) => panic ! ( "`prefixes` meant dont stop for Projection" ) ,
853
854
Lvalue :: Static ( _) => return Err ( NoMovePathFound :: ReachedStatic ) ,
854
855
}
855
856
}
@@ -1093,6 +1094,19 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1093
1094
where F : FnMut ( & mut Self , BorrowIndex , & BorrowData < ' tcx > , & Lvalue < ' tcx > ) -> Control
1094
1095
{
1095
1096
let ( access, lvalue) = access_lvalue;
1097
+ debug ! (
1098
+ "each_borrow_involving_path({:?}, {:?})" ,
1099
+ access,
1100
+ self . describe_lvalue( lvalue)
1101
+ ) ;
1102
+
1103
+ let mut ps = vec ! [ ] ;
1104
+ let mut base = lvalue;
1105
+ while let Lvalue :: Projection ( ref proj) = * base {
1106
+ ps. push ( proj. elem . lift ( ) ) ;
1107
+ base = & proj. base ;
1108
+ }
1109
+ debug ! ( "base = {:?}, projections = {:?}" , base, ps) ;
1096
1110
1097
1111
// FIXME: analogous code in check_loans first maps `lvalue` to
1098
1112
// its base_path.
@@ -1105,49 +1119,84 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1105
1119
' next_borrow: for i in flow_state. borrows . elems_incoming ( ) {
1106
1120
let borrowed = & data[ i] ;
1107
1121
1108
- // Is `lvalue` (or a prefix of it) already borrowed? If
1109
- // so, that's relevant.
1110
- //
1122
+ debug ! ( "borrowed = {:?}" , borrowed) ;
1123
+
1111
1124
// FIXME: Differs from AST-borrowck; includes drive-by fix
1112
1125
// to #38899. Will probably need back-compat mode flag.
1113
- for accessed_prefix in self . prefixes ( lvalue, PrefixSet :: All ) {
1114
- if * accessed_prefix == borrowed. lvalue {
1126
+ if base == & borrowed. base_lvalue {
1127
+ let bps = & borrowed. projections ;
1128
+
1129
+ // Is `lvalue` (or a prefix of it) already borrowed? If
1130
+ // so, that's relevant.
1131
+ if ps. ends_with ( bps) {
1132
+ let accessed_prefix = {
1133
+ let mut lv = lvalue;
1134
+ for _ in 0 ..ps. len ( ) - bps. len ( ) {
1135
+ if let Lvalue :: Projection ( ref proj) = * lv {
1136
+ lv = & proj. base ;
1137
+ } else {
1138
+ unreachable ! ( )
1139
+ }
1140
+ }
1141
+ lv
1142
+ } ;
1143
+ debug ! ( "accessed_prefix = {:?}" , accessed_prefix) ;
1115
1144
// FIXME: pass in enum describing case we are in?
1116
1145
let ctrl = op ( self , i, borrowed, accessed_prefix) ;
1117
- if ctrl == Control :: Break { return ; }
1146
+ if ctrl == Control :: Break {
1147
+ return ;
1148
+ }
1118
1149
}
1119
- }
1120
1150
1121
- // Is `lvalue` a prefix (modulo access type) of the
1122
- // `borrowed.lvalue`? If so, that's relevant.
1123
-
1124
- let prefix_kind = match access {
1125
- Shallow ( Some ( ArtificialField :: Discriminant ) ) |
1126
- Shallow ( Some ( ArtificialField :: ArrayLength ) ) => {
1127
- // The discriminant and array length are like
1128
- // additional fields on the type; they do not
1129
- // overlap any existing data there. Furthermore,
1130
- // they cannot actually be a prefix of any
1131
- // borrowed lvalue (at least in MIR as it is
1132
- // currently.)
1133
- continue ' next_borrow;
1134
- }
1135
- Shallow ( None ) => PrefixSet :: Shallow ,
1136
- Deep => PrefixSet :: Supporting ,
1137
- } ;
1151
+ // Is `lvalue` a prefix (modulo access type) of the
1152
+ // `borrowed.lvalue`? If so, that's relevant.
1153
+
1154
+ let shallow = match access {
1155
+ Shallow ( Some ( ArtificialField :: Discriminant ) ) |
1156
+ Shallow ( Some ( ArtificialField :: ArrayLength ) ) => {
1157
+ // The discriminant and array length are like
1158
+ // additional fields on the type; they do not
1159
+ // overlap any existing data there. Furthermore,
1160
+ // they cannot actually be a prefix of any
1161
+ // borrowed lvalue (at least in MIR as it is
1162
+ // currently.)
1163
+ continue ' next_borrow;
1164
+ }
1165
+ Shallow ( None ) => true ,
1166
+ Deep => false ,
1167
+ } ;
1168
+ let bps = if shallow {
1169
+ & bps[ borrowed. shallow_projections_len ..]
1170
+ } else {
1171
+ bps
1172
+ } ;
1138
1173
1139
- for borrowed_prefix in self . prefixes ( & borrowed. lvalue , prefix_kind) {
1140
- if borrowed_prefix == lvalue {
1174
+ if bps. len ( ) != ps. len ( ) &&
1175
+ bps. ends_with ( & ps)
1176
+ {
1177
+ let borrowed_prefix = {
1178
+ let mut lv = & borrowed. lvalue ;
1179
+ for _ in 0 ..bps. len ( ) - ps. len ( ) {
1180
+ if let Lvalue :: Projection ( ref proj) = * lv {
1181
+ lv = & proj. base ;
1182
+ } else {
1183
+ unreachable ! ( )
1184
+ }
1185
+ }
1186
+ lv
1187
+ } ;
1188
+ debug ! ( "borrowed_prefix = {:?}" , borrowed_prefix) ;
1141
1189
// FIXME: pass in enum describing case we are in?
1142
1190
let ctrl = op ( self , i, borrowed, borrowed_prefix) ;
1143
- if ctrl == Control :: Break { return ; }
1191
+ if ctrl == Control :: Break {
1192
+ return ;
1193
+ }
1144
1194
}
1145
1195
}
1146
1196
}
1147
1197
}
1148
1198
}
1149
1199
1150
- use self :: prefixes:: PrefixSet ;
1151
1200
1152
1201
/// From the NLL RFC: "The deep [aka 'supporting'] prefixes for an
1153
1202
/// lvalue are formed by stripping away fields and derefs, except that
@@ -1158,11 +1207,9 @@ use self::prefixes::PrefixSet;
1158
1207
/// is borrowed. But: writing `a` is legal if `*a` is borrowed,
1159
1208
/// whether or not `a` is a shared or mutable reference. [...] "
1160
1209
mod prefixes {
1161
- use super :: { MirBorrowckCtxt } ;
1210
+ use super :: MirBorrowckCtxt ;
1162
1211
1163
- use rustc:: hir;
1164
- use rustc:: ty:: { self , TyCtxt } ;
1165
- use rustc:: mir:: { Lvalue , Mir , ProjectionElem } ;
1212
+ use rustc:: mir:: { Lvalue , ProjectionElem } ;
1166
1213
1167
1214
pub trait IsPrefixOf < ' tcx > {
1168
1215
fn is_prefix_of ( & self , other : & Lvalue < ' tcx > ) -> bool ;
@@ -1188,38 +1235,23 @@ mod prefixes {
1188
1235
}
1189
1236
1190
1237
1191
- pub ( super ) struct Prefixes < ' cx , ' gcx : ' tcx , ' tcx : ' cx > {
1192
- mir : & ' cx Mir < ' tcx > ,
1193
- tcx : TyCtxt < ' cx , ' gcx , ' tcx > ,
1194
- kind : PrefixSet ,
1238
+ pub ( super ) struct Prefixes < ' cx , ' tcx : ' cx > {
1195
1239
next : Option < & ' cx Lvalue < ' tcx > > ,
1196
1240
}
1197
1241
1198
- #[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
1199
- pub ( super ) enum PrefixSet {
1200
- /// Doesn't stop until it returns the base case (a Local or
1201
- /// Static prefix).
1202
- All ,
1203
- /// Stops at any dereference.
1204
- Shallow ,
1205
- /// Stops at the deref of a shared reference.
1206
- Supporting ,
1207
- }
1208
-
1209
1242
impl < ' cx , ' gcx , ' tcx > MirBorrowckCtxt < ' cx , ' gcx , ' tcx > {
1210
1243
/// Returns an iterator over the prefixes of `lvalue`
1211
1244
/// (inclusive) from longest to smallest, potentially
1212
1245
/// terminating the iteration early based on `kind`.
1213
1246
pub ( super ) fn prefixes ( & self ,
1214
- lvalue : & ' cx Lvalue < ' tcx > ,
1215
- kind : PrefixSet )
1216
- -> Prefixes < ' cx , ' gcx , ' tcx >
1247
+ lvalue : & ' cx Lvalue < ' tcx > )
1248
+ -> Prefixes < ' cx , ' tcx >
1217
1249
{
1218
- Prefixes { next : Some ( lvalue) , kind , mir : self . mir , tcx : self . tcx }
1250
+ Prefixes { next : Some ( lvalue) }
1219
1251
}
1220
1252
}
1221
1253
1222
- impl < ' cx , ' gcx , ' tcx > Iterator for Prefixes < ' cx , ' gcx , ' tcx > {
1254
+ impl < ' cx , ' tcx : ' cx > Iterator for Prefixes < ' cx , ' tcx > {
1223
1255
type Item = & ' cx Lvalue < ' tcx > ;
1224
1256
fn next ( & mut self ) -> Option < Self :: Item > {
1225
1257
let mut cursor = match self . next {
@@ -1246,8 +1278,6 @@ mod prefixes {
1246
1278
match proj. elem {
1247
1279
ProjectionElem :: Field ( _/*field*/ , _/*ty*/ ) => {
1248
1280
// FIXME: add union handling
1249
- self . next = Some ( & proj. base ) ;
1250
- return Some ( cursor) ;
1251
1281
}
1252
1282
ProjectionElem :: Downcast ( ..) |
1253
1283
ProjectionElem :: Subslice { .. } |
@@ -1256,58 +1286,10 @@ mod prefixes {
1256
1286
cursor = & proj. base ;
1257
1287
continue ' cursor;
1258
1288
}
1259
- ProjectionElem :: Deref => {
1260
- // (handled below)
1261
- }
1262
- }
1263
-
1264
- assert_eq ! ( proj. elem, ProjectionElem :: Deref ) ;
1265
-
1266
- match self . kind {
1267
- PrefixSet :: Shallow => {
1268
- // shallow prefixes are found by stripping away
1269
- // fields, but stop at *any* dereference.
1270
- // So we can just stop the traversal now.
1271
- self . next = None ;
1272
- return Some ( cursor) ;
1273
- }
1274
- PrefixSet :: All => {
1275
- // all prefixes: just blindly enqueue the base
1276
- // of the projection
1277
- self . next = Some ( & proj. base ) ;
1278
- return Some ( cursor) ;
1279
- }
1280
- PrefixSet :: Supporting => {
1281
- // fall through!
1282
- }
1283
- }
1284
-
1285
- assert_eq ! ( self . kind, PrefixSet :: Supporting ) ;
1286
- // supporting prefixes: strip away fields and
1287
- // derefs, except we stop at the deref of a shared
1288
- // reference.
1289
-
1290
- let ty = proj. base . ty ( self . mir , self . tcx ) . to_ty ( self . tcx ) ;
1291
- match ty. sty {
1292
- ty:: TyRawPtr ( _) |
1293
- ty:: TyRef ( _/*rgn*/ , ty:: TypeAndMut { ty : _, mutbl : hir:: MutImmutable } ) => {
1294
- // don't continue traversing over derefs of raw pointers or shared borrows.
1295
- self . next = None ;
1296
- return Some ( cursor) ;
1297
- }
1298
-
1299
- ty:: TyRef ( _/*rgn*/ , ty:: TypeAndMut { ty : _, mutbl : hir:: MutMutable } ) => {
1300
- self . next = Some ( & proj. base ) ;
1301
- return Some ( cursor) ;
1302
- }
1303
-
1304
- ty:: TyAdt ( ..) if ty. is_box ( ) => {
1305
- self . next = Some ( & proj. base ) ;
1306
- return Some ( cursor) ;
1307
- }
1308
-
1309
- _ => panic ! ( "unknown type fed to Projection Deref." ) ,
1289
+ _ => { }
1310
1290
}
1291
+ self . next = Some ( & proj. base ) ;
1292
+ return Some ( cursor) ;
1311
1293
}
1312
1294
}
1313
1295
}
0 commit comments