6565 * per-arm `ArmData` struct. There is a mapping from identifiers to
6666 * `BindingInfo` structs. These structs contain the mode/id/type of the
6767 * 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.
6973 *
7074 * The `llmatch` binding always stores a pointer into the value being matched
7175 * 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 {
352356
353357#[ deriving( Clone ) ]
354358pub enum TransBindingMode {
355- TrByValue ,
359+ TrByCopy ( /* llbinding */ ValueRef ) ,
360+ TrByMove ,
356361 TrByRef ,
357362}
358363
@@ -1249,7 +1254,7 @@ fn compare_values<'a>(
12491254 }
12501255}
12511256
1252- fn insert_lllocals < ' a > ( bcx : & ' a Block < ' a > ,
1257+ fn insert_lllocals < ' a > ( mut bcx : & ' a Block < ' a > ,
12531258 bindings_map : & BindingsMap ,
12541259 cleanup_scope : cleanup:: ScopeId )
12551260 -> & ' a Block < ' a > {
@@ -1262,8 +1267,18 @@ fn insert_lllocals<'a>(bcx: &'a Block<'a>,
12621267
12631268 for ( & ident, & binding_info) in bindings_map. iter ( ) {
12641269 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 ) ,
12671282
12681283 // By ref binding: use the ptr into the matched value
12691284 TrByRef => binding_info. llmatch
@@ -1762,18 +1777,28 @@ fn create_bindings_map(bcx: &Block, pat: Gc<ast::Pat>) -> BindingsMap {
17621777 let ident = path_to_ident ( path) ;
17631778 let variable_ty = node_id_type ( bcx, p_id) ;
17641779 let llvariable_ty = type_of:: type_of ( ccx, variable_ty) ;
1780+ let tcx = bcx. tcx ( ) ;
17651781
17661782 let llmatch;
17671783 let trmode;
17681784 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+ }
17691794 ast:: BindByValue ( _) => {
17701795 // in this case, the final type of the variable will be T,
17711796 // but during matching we need to store a *T as explained
17721797 // above
17731798 llmatch = alloca ( bcx,
17741799 llvariable_ty. ptr_to ( ) ,
17751800 bcx. ident ( ident) . as_slice ( ) ) ;
1776- trmode = TrByValue ;
1801+ trmode = TrByMove ;
17771802 }
17781803 ast:: BindByRef ( _) => {
17791804 llmatch = alloca ( bcx,
0 commit comments