@@ -29,6 +29,7 @@ extern mod rustrt {
29
29
#[ abi = "rust-intrinsic" ]
30
30
extern mod rusti {
31
31
fn move_val_init < T > ( dst : & mut T , -src : T ) ;
32
+ fn init < T > ( ) -> T ;
32
33
}
33
34
34
35
@@ -483,9 +484,15 @@ pub fn remove<T>(v: &mut ~[T], i: uint) -> T {
483
484
pub fn consume < T > ( v : ~[ T ] , f : fn ( uint , v : T ) ) unsafe {
484
485
let mut v = v; // FIXME(#3488)
485
486
486
- do as_imm_buf ( v) |p, ln| {
487
+ do as_mut_buf ( v) |p, ln| {
487
488
for uint:: range( 0 , ln) |i| {
488
- let x = move * ptr:: offset ( p, i) ;
489
+ // NB: This unsafe operation counts on init writing 0s to the
490
+ // holes we create in the vector. That ensures that, if the
491
+ // iterator fails then we won't try to clean up the consumed
492
+ // elements during unwinding
493
+ let mut x = rusti:: init ( ) ;
494
+ let p = ptr:: mut_offset ( p, i) ;
495
+ x <-> * p;
489
496
f ( i, x) ;
490
497
}
491
498
}
@@ -505,7 +512,9 @@ pub fn pop<T>(v: &mut ~[T]) -> T {
505
512
}
506
513
let valptr = ptr:: to_mut_unsafe_ptr ( & mut v[ ln - 1 u] ) ;
507
514
unsafe {
508
- let val = move * valptr;
515
+ // XXX: Should be rusti::uninit() - we don't need this zeroed
516
+ let mut val = rusti:: init ( ) ;
517
+ val <-> * valptr;
509
518
raw:: set_len ( v, ln - 1 u) ;
510
519
val
511
520
}
@@ -574,9 +583,11 @@ pub fn push_all_move<T>(v: &mut ~[T], rhs: ~[T]) {
574
583
let mut rhs = rhs; // FIXME(#3488)
575
584
reserve ( v, v. len ( ) + rhs. len ( ) ) ;
576
585
unsafe {
577
- do as_imm_buf ( rhs) |p, len| {
586
+ do as_mut_buf ( rhs) |p, len| {
578
587
for uint:: range( 0 , len) |i| {
579
- let x = move * ptr:: offset ( p, i) ;
588
+ // XXX Should be rusti::uninit() - don't need to zero
589
+ let mut x = rusti:: init ( ) ;
590
+ x <-> * ptr:: mut_offset ( p, i) ;
580
591
push ( v, x) ;
581
592
}
582
593
}
@@ -586,12 +597,14 @@ pub fn push_all_move<T>(v: &mut ~[T], rhs: ~[T]) {
586
597
587
598
/// Shorten a vector, dropping excess elements.
588
599
pub fn truncate < T > ( v : & mut ~[ T ] , newlen : uint ) {
589
- do as_imm_buf ( * v) |p, oldlen| {
600
+ do as_mut_buf ( * v) |p, oldlen| {
590
601
assert ( newlen <= oldlen) ;
591
602
unsafe {
592
603
// This loop is optimized out for non-drop types.
593
604
for uint:: range( newlen, oldlen) |i| {
594
- let _dropped = move * ptr:: offset ( p, i) ;
605
+ // XXX Should be rusti::uninit() - don't need to zero
606
+ let mut dropped = rusti:: init ( ) ;
607
+ dropped <-> * ptr:: mut_offset ( p, i) ;
595
608
}
596
609
raw:: set_len ( v, newlen) ;
597
610
}
@@ -614,12 +627,14 @@ pub fn dedup<T: Eq>(v: &mut ~[T]) unsafe {
614
627
// last_written < next_to_read < ln
615
628
if * ptr:: mut_offset ( p, next_to_read) ==
616
629
* ptr:: mut_offset ( p, last_written) {
617
- let _dropped = move * ptr:: mut_offset ( p, next_to_read) ;
630
+ // XXX Should be rusti::uninit() - don't need to zero
631
+ let mut dropped = rusti:: init ( ) ;
632
+ dropped <-> * ptr:: mut_offset ( p, next_to_read) ;
618
633
} else {
619
634
last_written += 1 ;
620
635
// last_written <= next_to_read < ln
621
636
if next_to_read != last_written {
622
- * ptr:: mut_offset ( p, last_written) = move
637
+ * ptr:: mut_offset ( p, last_written) <->
623
638
* ptr:: mut_offset ( p, next_to_read) ;
624
639
}
625
640
}
0 commit comments