@@ -330,11 +330,35 @@ pub enum OptResult<'blk, 'tcx: 'blk> {
330
330
331
331
#[ derive( Clone , Copy , PartialEq ) ]
332
332
pub enum TransBindingMode {
333
+ /// By-value binding for a copy type: copies from matched data
334
+ /// into a fresh LLVM alloca.
333
335
TrByCopy ( /* llbinding */ ValueRef ) ,
334
- TrByMove ,
336
+
337
+ /// By-value binding for a non-copy type where we copy into a
338
+ /// fresh LLVM alloca; this most accurately reflects the language
339
+ /// semantics (e.g. it properly handles overwrites of the matched
340
+ /// input), but potentially injects an unwanted copy.
341
+ TrByMoveIntoCopy ( /* llbinding */ ValueRef ) ,
342
+
343
+ /// Binding a non-copy type by reference under the hood; this is
344
+ /// a codegen optimization to avoid unnecessary memory traffic.
345
+ TrByMoveRef ,
346
+
347
+ /// By-ref binding exposed in the original source input.
335
348
TrByRef ,
336
349
}
337
350
351
+ impl TransBindingMode {
352
+ /// if binding by making a fresh copy; returns the alloca that it
353
+ /// will copy into; otherwise None.
354
+ fn alloca_if_copy ( & self ) -> Option < ValueRef > {
355
+ match * self {
356
+ TrByCopy ( llbinding) | TrByMoveIntoCopy ( llbinding) => Some ( llbinding) ,
357
+ TrByMoveRef | TrByRef => None ,
358
+ }
359
+ }
360
+ }
361
+
338
362
/// Information about a pattern binding:
339
363
/// - `llmatch` is a pointer to a stack slot. The stack slot contains a
340
364
/// pointer into the value being matched. Hence, llmatch has type `T**`
@@ -891,7 +915,8 @@ fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
891
915
let llval = match binding_info. trmode {
892
916
// By value mut binding for a copy type: load from the ptr
893
917
// into the matched value and copy to our alloca
894
- TrByCopy ( llbinding) => {
918
+ TrByCopy ( llbinding) |
919
+ TrByMoveIntoCopy ( llbinding) => {
895
920
let llval = Load ( bcx, binding_info. llmatch ) ;
896
921
let datum = Datum :: new ( llval, binding_info. ty , Lvalue ) ;
897
922
call_lifetime_start ( bcx, llbinding) ;
@@ -904,7 +929,7 @@ fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
904
929
} ,
905
930
906
931
// By value move bindings: load from the ptr into the matched value
907
- TrByMove => Load ( bcx, binding_info. llmatch ) ,
932
+ TrByMoveRef => Load ( bcx, binding_info. llmatch ) ,
908
933
909
934
// By ref binding: use the ptr into the matched value
910
935
TrByRef => binding_info. llmatch
@@ -944,8 +969,8 @@ fn compile_guard<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
944
969
let val = val. to_llbool ( bcx) ;
945
970
946
971
for ( _, & binding_info) in & data. bindings_map {
947
- if let TrByCopy ( llbinding) = binding_info. trmode {
948
- call_lifetime_end ( bcx, llbinding) ;
972
+ if let Some ( llbinding) = binding_info. trmode . alloca_if_copy ( ) {
973
+ call_lifetime_end ( bcx, llbinding)
949
974
}
950
975
}
951
976
@@ -1415,16 +1440,21 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat,
1415
1440
1416
1441
let llmatch;
1417
1442
let trmode;
1443
+ let moves_by_default = variable_ty. moves_by_default ( & param_env, span) ;
1418
1444
match bm {
1419
- ast:: BindByValue ( _)
1420
- if !variable_ty. moves_by_default ( & param_env, span) || reassigned =>
1445
+ ast:: BindByValue ( _) if !moves_by_default || reassigned =>
1421
1446
{
1422
1447
llmatch = alloca_no_lifetime ( bcx,
1423
- llvariable_ty. ptr_to ( ) ,
1424
- "__llmatch" ) ;
1425
- trmode = TrByCopy ( alloca_no_lifetime ( bcx,
1426
- llvariable_ty,
1427
- & bcx. name ( name) ) ) ;
1448
+ llvariable_ty. ptr_to ( ) ,
1449
+ "__llmatch" ) ;
1450
+ let llcopy = alloca_no_lifetime ( bcx,
1451
+ llvariable_ty,
1452
+ & bcx. name ( name) ) ;
1453
+ trmode = if moves_by_default {
1454
+ TrByMoveIntoCopy ( llcopy)
1455
+ } else {
1456
+ TrByCopy ( llcopy)
1457
+ } ;
1428
1458
}
1429
1459
ast:: BindByValue ( _) => {
1430
1460
// in this case, the final type of the variable will be T,
@@ -1433,11 +1463,11 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat,
1433
1463
llmatch = alloca_no_lifetime ( bcx,
1434
1464
llvariable_ty. ptr_to ( ) ,
1435
1465
& bcx. name ( name) ) ;
1436
- trmode = TrByMove ;
1466
+ trmode = TrByMoveRef ;
1437
1467
}
1438
1468
ast:: BindByRef ( _) => {
1439
1469
llmatch = alloca_no_lifetime ( bcx,
1440
- llvariable_ty,
1470
+ llvariable_ty,
1441
1471
& bcx. name ( name) ) ;
1442
1472
trmode = TrByRef ;
1443
1473
}
0 commit comments