65
65
* per-arm `ArmData` struct. There is a mapping from identifiers to
66
66
* `BindingInfo` structs. These structs contain the mode/id/type of the
67
67
* binding, but they also contain an LLVM value which points at an alloca
68
- * called `llmatch`.
68
+ * called `llmatch`. For by value bindings that are Copy, we also create
69
+ * an extra alloca that we copy the matched value to so that any changes
70
+ * we do to our copy is not reflected in the original and vice-versa.
71
+ * We don't do this if it's a move since the original value can't be used
72
+ * and thus allowing us to cheat in not creating an extra alloca.
69
73
*
70
74
* The `llmatch` binding always stores a pointer into the value being matched
71
75
* which points at the data for the binding. If the value being matched has
@@ -352,7 +356,8 @@ fn variant_opt(bcx: &Block, pat_id: ast::NodeId) -> Opt {
352
356
353
357
#[ deriving( Clone ) ]
354
358
pub enum TransBindingMode {
355
- TrByValue ,
359
+ TrByCopy ( /* llbinding */ ValueRef ) ,
360
+ TrByMove ,
356
361
TrByRef ,
357
362
}
358
363
@@ -1249,7 +1254,7 @@ fn compare_values<'a>(
1249
1254
}
1250
1255
}
1251
1256
1252
- fn insert_lllocals < ' a > ( bcx : & ' a Block < ' a > ,
1257
+ fn insert_lllocals < ' a > ( mut bcx : & ' a Block < ' a > ,
1253
1258
bindings_map : & BindingsMap ,
1254
1259
cleanup_scope : cleanup:: ScopeId )
1255
1260
-> & ' a Block < ' a > {
@@ -1262,8 +1267,18 @@ fn insert_lllocals<'a>(bcx: &'a Block<'a>,
1262
1267
1263
1268
for ( & ident, & binding_info) in bindings_map. iter ( ) {
1264
1269
let llval = match binding_info. trmode {
1265
- // By value bindings: load from the ptr into the matched value
1266
- TrByValue => Load ( bcx, binding_info. llmatch ) ,
1270
+ // By value mut binding for a copy type: load from the ptr
1271
+ // into the matched value and copy to our alloca
1272
+ TrByCopy ( llbinding) => {
1273
+ let llval = Load ( bcx, binding_info. llmatch ) ;
1274
+ let datum = Datum :: new ( llval, binding_info. ty , Lvalue ) ;
1275
+ bcx = datum. store_to ( bcx, llbinding) ;
1276
+
1277
+ llbinding
1278
+ } ,
1279
+
1280
+ // By value move bindings: load from the ptr into the matched value
1281
+ TrByMove => Load ( bcx, binding_info. llmatch ) ,
1267
1282
1268
1283
// By ref binding: use the ptr into the matched value
1269
1284
TrByRef => binding_info. llmatch
@@ -1762,18 +1777,28 @@ fn create_bindings_map(bcx: &Block, pat: Gc<ast::Pat>) -> BindingsMap {
1762
1777
let ident = path_to_ident ( path) ;
1763
1778
let variable_ty = node_id_type ( bcx, p_id) ;
1764
1779
let llvariable_ty = type_of:: type_of ( ccx, variable_ty) ;
1780
+ let tcx = bcx. tcx ( ) ;
1765
1781
1766
1782
let llmatch;
1767
1783
let trmode;
1768
1784
match bm {
1785
+ ast:: BindByValue ( _)
1786
+ if !ty:: type_moves_by_default ( tcx, variable_ty) => {
1787
+ llmatch = alloca ( bcx,
1788
+ llvariable_ty. ptr_to ( ) ,
1789
+ "__llmatch" ) ;
1790
+ trmode = TrByCopy ( alloca ( bcx,
1791
+ llvariable_ty,
1792
+ bcx. ident ( ident) . as_slice ( ) ) ) ;
1793
+ }
1769
1794
ast:: BindByValue ( _) => {
1770
1795
// in this case, the final type of the variable will be T,
1771
1796
// but during matching we need to store a *T as explained
1772
1797
// above
1773
1798
llmatch = alloca ( bcx,
1774
1799
llvariable_ty. ptr_to ( ) ,
1775
1800
bcx. ident ( ident) . as_slice ( ) ) ;
1776
- trmode = TrByValue ;
1801
+ trmode = TrByMove ;
1777
1802
}
1778
1803
ast:: BindByRef ( _) => {
1779
1804
llmatch = alloca ( bcx,
0 commit comments