auto merge of #6260 : alexcrichton/rust/issue-3466-no-swap, r=pcwalton

There may be a more efficient implementation of `core::util::swap_ptr`. The issue mentioned using `move_val_init`, but I couldn't figure out what that did, so I just used `copy_memory` a few times instead.

I'm not exactly the best at reading LLVM generated by rust, but this does appear to be optimized away just as expected (when possible).
This commit is contained in:
bors 2013-05-10 20:35:00 -07:00
commit 9f106a643e
48 changed files with 296 additions and 430 deletions

View File

@ -1946,35 +1946,6 @@ fn avg(v: &[float]) -> float {
}
~~~~
#### Swap expressions
A _swap expression_ consists of an [lvalue](#lvalues-rvalues-and-temporaries) followed by a bi-directional arrow (`<->`) and another [lvalue](#lvalues-rvalues-and-temporaries).
Evaluating a swap expression causes, as a side effect, the values held in the left-hand-side and right-hand-side [lvalues](#lvalues-rvalues-and-temporaries) to be exchanged indivisibly.
Evaluating a swap expression neither changes reference counts,
nor deeply copies any owned structure pointed to by the moved [rvalue](#lvalues-rvalues-and-temporaries).
Instead, the swap expression represents an indivisible *exchange of ownership*,
between the right-hand-side and the left-hand-side of the expression.
No allocation or destruction is entailed.
An example of three different swap expressions:
~~~~~~~~
# let mut x = &mut [0];
# let mut a = &mut [0];
# let i = 0;
# struct S1 { z: int };
# struct S2 { c: int };
# let mut y = S1{z: 0};
# let mut b = S2{c: 0};
x <-> a;
x[i] <-> a[i];
y.z <-> b.c;
~~~~~~~~
#### Assignment expressions
An _assignment expression_ consists of an [lvalue](#lvalues-rvalues-and-temporaries) expression followed by an
@ -2015,7 +1986,7 @@ as
== !=
&&
||
= <->
=
~~~~
Operators at the same precedence level are evaluated left-to-right.

View File

@ -151,6 +151,7 @@ wrapping `malloc` and `free`:
~~~~
use core::libc::{c_void, size_t, malloc, free};
use core::unstable::intrinsics;
use core::util;
// a wrapper around the handle returned by the foreign code
pub struct Unique<T> {
@ -184,7 +185,8 @@ impl<T: Owned> Drop for Unique<T> {
fn finalize(&self) {
unsafe {
let mut x = intrinsics::init(); // dummy value to swap in
x <-> *self.ptr; // moving the object out is needed to call the destructor
// moving the object out is needed to call the destructor
util::replace_ptr(self.ptr, x);
free(self.ptr as *c_void)
}
}

View File

@ -12,6 +12,7 @@
use cast::transmute_mut;
use prelude::*;
use util::replace;
/*
A dynamic, mutable location.
@ -48,9 +49,7 @@ pub impl<T> Cell<T> {
fail!(~"attempt to take an empty cell");
}
let mut value = None;
value <-> self.value;
value.unwrap()
replace(&mut self.value, None).unwrap()
}
/// Returns the value, failing if the cell is full.

View File

@ -21,6 +21,7 @@ use uint;
use unstable;
use vec;
use unstable::Exclusive;
use util::replace;
use pipes::{recv, try_recv, wait_many, peek, PacketHeader};
@ -149,9 +150,8 @@ impl<T: Owned> GenericChan<T> for Chan<T> {
#[inline(always)]
fn send(&self, x: T) {
unsafe {
let mut endp = None;
let mut self_endp = transmute_mut(&self.endp);
endp <-> *self_endp;
let endp = replace(self_endp, None);
*self_endp = Some(streamp::client::data(endp.unwrap(), x))
}
}
@ -161,9 +161,8 @@ impl<T: Owned> GenericSmartChan<T> for Chan<T> {
#[inline(always)]
fn try_send(&self, x: T) -> bool {
unsafe {
let mut endp = None;
let mut self_endp = transmute_mut(&self.endp);
endp <-> *self_endp;
let endp = replace(self_endp, None);
match streamp::client::try_data(endp.unwrap(), x) {
Some(next) => {
*self_endp = Some(next);
@ -179,9 +178,8 @@ impl<T: Owned> GenericPort<T> for Port<T> {
#[inline(always)]
fn recv(&self) -> T {
unsafe {
let mut endp = None;
let mut self_endp = transmute_mut(&self.endp);
endp <-> *self_endp;
let endp = replace(self_endp, None);
let streamp::data(x, endp) = recv(endp.unwrap());
*self_endp = Some(endp);
x
@ -191,9 +189,8 @@ impl<T: Owned> GenericPort<T> for Port<T> {
#[inline(always)]
fn try_recv(&self) -> Option<T> {
unsafe {
let mut endp = None;
let mut self_endp = transmute_mut(&self.endp);
endp <-> *self_endp;
let endp = replace(self_endp, None);
match try_recv(endp.unwrap()) {
Some(streamp::data(x, endp)) => {
*self_endp = Some(endp);
@ -209,14 +206,13 @@ impl<T: Owned> Peekable<T> for Port<T> {
#[inline(always)]
fn peek(&self) -> bool {
unsafe {
let mut endp = None;
let mut self_endp = transmute_mut(&self.endp);
endp <-> *self_endp;
let mut endp = replace(self_endp, None);
let peek = match endp {
Some(ref mut endp) => peek(endp),
None => fail!(~"peeking empty stream")
};
*self_endp <-> endp;
*self_endp = endp;
peek
}
}
@ -267,8 +263,7 @@ impl<T:Owned> GenericPort<T> for PortSet<T> {
let mut result = None;
// we have to swap the ports array so we aren't borrowing
// aliasable mutable memory.
let mut ports = ~[];
ports <-> *self_ports;
let mut ports = replace(self_ports, ~[]);
while result.is_none() && ports.len() > 0 {
let i = wait_many(ports);
match ports[i].try_recv() {
@ -281,7 +276,7 @@ impl<T:Owned> GenericPort<T> for PortSet<T> {
}
}
}
ports <-> *self_ports;
*self_ports = ports;
result
}
}
@ -320,8 +315,7 @@ impl<T: Owned> GenericChan<T> for SharedChan<T> {
fn send(&self, x: T) {
let mut xx = Some(x);
do self.ch.with_imm |chan| {
let mut x = None;
x <-> xx;
let x = replace(&mut xx, None);
chan.send(x.unwrap())
}
}
@ -331,8 +325,7 @@ impl<T: Owned> GenericSmartChan<T> for SharedChan<T> {
fn try_send(&self, x: T) -> bool {
let mut xx = Some(x);
do self.ch.with_imm |chan| {
let mut x = None;
x <-> xx;
let x = replace(&mut xx, None);
chan.try_send(x.unwrap())
}
}

View File

@ -176,16 +176,13 @@ priv impl<K:Hash + Eq,V> HashMap<K, V> {
/// Expands the capacity of the array and re-insert each of the
/// existing buckets.
fn resize(&mut self, new_capacity: uint) {
let old_capacity = self.buckets.len();
self.resize_at = resize_at(new_capacity);
let mut old_buckets = vec::from_fn(new_capacity, |_| None);
self.buckets <-> old_buckets;
let old_buckets = replace(&mut self.buckets,
vec::from_fn(new_capacity, |_| None));
self.size = 0;
for uint::range(0, old_capacity) |i| {
let mut bucket = None;
bucket <-> old_buckets[i];
do vec::consume(old_buckets) |_, bucket| {
self.insert_opt_bucket(bucket);
}
}
@ -265,13 +262,11 @@ priv impl<K:Hash + Eq,V> HashMap<K, V> {
};
let len_buckets = self.buckets.len();
let mut bucket = None;
self.buckets[idx] <-> bucket;
let bucket = replace(&mut self.buckets[idx], None);
let value = match bucket {
None => None,
Some(bucket) => {
let Bucket{value: value, _} = bucket;
Some(Bucket{value, _}) => {
Some(value)
},
};
@ -281,8 +276,7 @@ priv impl<K:Hash + Eq,V> HashMap<K, V> {
let size = self.size - 1;
idx = self.next_bucket(idx, len_buckets);
while self.buckets[idx].is_some() {
let mut bucket = None;
bucket <-> self.buckets[idx];
let bucket = replace(&mut self.buckets[idx], None);
self.insert_opt_bucket(bucket);
idx = self.next_bucket(idx, len_buckets);
}
@ -613,15 +607,13 @@ pub impl<K: Hash + Eq, V> HashMap<K, V> {
}
fn consume(&mut self, f: &fn(K, V)) {
let mut buckets = ~[];
self.buckets <-> buckets;
let buckets = replace(&mut self.buckets, ~[]);
self.size = 0;
do vec::consume(buckets) |_, bucket| {
match bucket {
None => {},
Some(bucket) => {
let Bucket{key: key, value: value, _} = bucket;
Some(Bucket{key, value, _}) => {
f(key, value)
}
}

View File

@ -93,6 +93,7 @@ use unstable::intrinsics;
use ptr;
use task;
use vec;
use util::replace;
static SPIN_COUNT: uint = 0;
@ -428,8 +429,7 @@ fn try_recv_<T:Owned>(p: &mut Packet<T>) -> Option<T> {
// optimistic path
match p.header.state {
Full => {
let mut payload = None;
payload <-> p.payload;
let payload = replace(&mut p.payload, None);
p.header.state = Empty;
return Some(payload.unwrap())
},
@ -480,8 +480,7 @@ fn try_recv_<T:Owned>(p: &mut Packet<T>) -> Option<T> {
fail!(~"blocking on already blocked packet")
},
Full => {
let mut payload = None;
payload <-> p.payload;
let payload = replace(&mut p.payload, None);
let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
if !old_task.is_null() {
unsafe {
@ -675,8 +674,7 @@ impl<T:Owned,Tbuffer:Owned> Drop for SendPacketBuffered<T,Tbuffer> {
unsafe {
let this: &mut SendPacketBuffered<T,Tbuffer> = transmute(self);
if this.p != None {
let mut p = None;
p <-> this.p;
let p = replace(&mut this.p, None);
sender_terminate(p.unwrap())
}
}
@ -695,9 +693,7 @@ pub fn SendPacketBuffered<T,Tbuffer>(p: *mut Packet<T>)
pub impl<T,Tbuffer> SendPacketBuffered<T,Tbuffer> {
fn unwrap(&mut self) -> *mut Packet<T> {
let mut p = None;
p <-> self.p;
p.unwrap()
replace(&mut self.p, None).unwrap()
}
fn header(&mut self) -> *mut PacketHeader {
@ -713,9 +709,7 @@ pub impl<T,Tbuffer> SendPacketBuffered<T,Tbuffer> {
fn reuse_buffer(&mut self) -> BufferResource<Tbuffer> {
//error!("send reuse_buffer");
let mut tmp = None;
tmp <-> self.buffer;
tmp.unwrap()
replace(&mut self.buffer, None).unwrap()
}
}
@ -738,8 +732,7 @@ impl<T:Owned,Tbuffer:Owned> Drop for RecvPacketBuffered<T,Tbuffer> {
unsafe {
let this: &mut RecvPacketBuffered<T,Tbuffer> = transmute(self);
if this.p != None {
let mut p = None;
p <-> this.p;
let p = replace(&mut this.p, None);
receiver_terminate(p.unwrap())
}
}
@ -748,15 +741,11 @@ impl<T:Owned,Tbuffer:Owned> Drop for RecvPacketBuffered<T,Tbuffer> {
pub impl<T:Owned,Tbuffer:Owned> RecvPacketBuffered<T, Tbuffer> {
fn unwrap(&mut self) -> *mut Packet<T> {
let mut p = None;
p <-> self.p;
p.unwrap()
replace(&mut self.p, None).unwrap()
}
fn reuse_buffer(&mut self) -> BufferResource<Tbuffer> {
let mut tmp = None;
tmp <-> self.buffer;
tmp.unwrap()
replace(&mut self.buffer, None).unwrap()
}
}

View File

@ -15,6 +15,7 @@ Miscellaneous helpers for common patterns.
*/
use prelude::*;
use unstable::intrinsics;
/// The identity function.
#[inline(always)]
@ -34,12 +35,12 @@ pub fn ignore<T>(_x: T) { }
#[inline(always)]
pub fn with<T,R>(
ptr: @mut T,
mut value: T,
value: T,
op: &fn() -> R) -> R
{
value <-> *ptr;
let prev = replace(ptr, value);
let result = op();
*ptr = value;
*ptr = prev;
return result;
}
@ -49,7 +50,55 @@ pub fn with<T,R>(
*/
#[inline(always)]
pub fn swap<T>(x: &mut T, y: &mut T) {
*x <-> *y;
unsafe {
swap_ptr(ptr::to_mut_unsafe_ptr(x), ptr::to_mut_unsafe_ptr(y));
}
}
/**
* Swap the values at two mutable locations of the same type, without
* deinitialising or copying either one.
*/
#[inline]
#[cfg(not(stage0))]
pub unsafe fn swap_ptr<T>(x: *mut T, y: *mut T) {
if x == y { return }
// Give ourselves some scratch space to work with
let mut tmp: T = intrinsics::uninit();
let t = ptr::to_mut_unsafe_ptr(&mut tmp);
// Perform the swap
ptr::copy_memory(t, x, 1);
ptr::copy_memory(x, y, 1);
ptr::copy_memory(y, t, 1);
// y and t now point to the same thing, but we need to completely forget t
// because it's no longer relevant.
cast::forget(tmp);
}
/**
* Swap the values at two mutable locations of the same type, without
* deinitialising or copying either one.
*/
#[inline]
#[cfg(stage0)]
pub unsafe fn swap_ptr<T>(x: *mut T, y: *mut T) {
if x == y { return }
// Give ourselves some scratch space to work with
let mut tmp: T = intrinsics::init();
let t = ptr::to_mut_unsafe_ptr(&mut tmp);
// Perform the swap
ptr::copy_memory(t, x, 1);
ptr::copy_memory(x, y, 1);
ptr::copy_memory(y, t, 1);
// y and t now point to the same thing, but we need to completely forget t
// because it's no longer relevant.
cast::forget(tmp);
}
/**
@ -57,10 +106,19 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
* value, without deinitialising or copying either one.
*/
#[inline(always)]
pub fn replace<T>(dest: &mut T, src: T) -> T {
let mut tmp = src;
swap(dest, &mut tmp);
tmp
pub fn replace<T>(dest: &mut T, mut src: T) -> T {
swap(dest, &mut src);
src
}
/**
* Replace the value at a mutable location with a new one, returning the old
* value, without deinitialising or copying either one.
*/
#[inline(always)]
pub unsafe fn replace_ptr<T>(dest: *mut T, mut src: T) -> T {
swap_ptr(dest, ptr::to_mut_unsafe_ptr(&mut src));
src
}
/// A non-copyable dummy type.

View File

@ -29,6 +29,7 @@ use sys;
use uint;
use unstable::intrinsics;
use vec;
use util;
#[cfg(not(test))] use cmp::Equiv;
@ -470,7 +471,7 @@ pub fn shift<T>(v: &mut ~[T]) -> T {
let next_ln = v.len() - 1;
// Save the last element. We're going to overwrite its position
let mut work_elt = v.pop();
let work_elt = v.pop();
// We still should have room to work where what last element was
assert!(capacity(v) >= ln);
// Pretend like we have the original length so we can use
@ -501,16 +502,14 @@ pub fn shift<T>(v: &mut ~[T]) -> T {
// Swap out the element we want from the end
let vp = raw::to_mut_ptr(*v);
let vp = ptr::mut_offset(vp, next_ln - 1);
*vp <-> work_elt;
work_elt
util::replace_ptr(vp, work_elt)
}
}
/// Prepend an element to the vector
pub fn unshift<T>(v: &mut ~[T], x: T) {
let mut vv = ~[x];
*v <-> vv;
let vv = util::replace(v, ~[x]);
v.push_all_move(vv);
}
@ -523,7 +522,7 @@ pub fn insert<T>(v: &mut ~[T], i: uint, x: T) {
v.push(x);
let mut j = len;
while j > i {
v[j] <-> v[j - 1];
swap(*v, j, j - 1);
j -= 1;
}
}
@ -536,7 +535,7 @@ pub fn remove<T>(v: &mut ~[T], i: uint) -> T {
let mut j = i;
while j < len - 1 {
v[j] <-> v[j + 1];
swap(*v, j, j + 1);
j += 1;
}
v.pop()
@ -550,10 +549,9 @@ pub fn consume<T>(mut v: ~[T], f: &fn(uint, v: T)) {
// holes we create in the vector. That ensures that, if the
// iterator fails then we won't try to clean up the consumed
// elements during unwinding
let mut x = intrinsics::init();
let x = intrinsics::init();
let p = ptr::mut_offset(p, i);
x <-> *p;
f(i, x);
f(i, util::replace_ptr(p, x));
}
}
@ -572,10 +570,9 @@ pub fn consume_reverse<T>(mut v: ~[T], f: &fn(uint, v: T)) {
// holes we create in the vector. That ensures that, if the
// iterator fails then we won't try to clean up the consumed
// elements during unwinding
let mut x = intrinsics::init();
let x = intrinsics::init();
let p = ptr::mut_offset(p, i);
x <-> *p;
f(i, x);
f(i, util::replace_ptr(p, x));
}
}
@ -592,8 +589,7 @@ pub fn pop<T>(v: &mut ~[T]) -> T {
}
let valptr = ptr::to_mut_unsafe_ptr(&mut v[ln - 1u]);
unsafe {
let mut val = intrinsics::uninit();
val <-> *valptr;
let val = util::replace_ptr(valptr, intrinsics::uninit());
raw::set_len(v, ln - 1u);
val
}
@ -607,8 +603,7 @@ pub fn pop<T>(v: &mut ~[T]) -> T {
}
let valptr = ptr::to_mut_unsafe_ptr(&mut v[ln - 1u]);
unsafe {
let mut val = intrinsics::init();
val <-> *valptr;
let val = util::replace_ptr(valptr, intrinsics::init());
raw::set_len(v, ln - 1u);
val
}
@ -626,7 +621,7 @@ pub fn swap_remove<T>(v: &mut ~[T], index: uint) -> T {
fail!(fmt!("vec::swap_remove - index %u >= length %u", index, ln));
}
if index < ln - 1 {
v[index] <-> v[ln - 1];
swap(*v, index, ln - 1);
}
v.pop()
}
@ -682,8 +677,8 @@ pub fn push_all_move<T>(v: &mut ~[T], mut rhs: ~[T]) {
unsafe {
do as_mut_buf(rhs) |p, len| {
for uint::range(0, len) |i| {
let mut x = intrinsics::uninit();
x <-> *ptr::mut_offset(p, i);
let x = util::replace_ptr(ptr::mut_offset(p, i),
intrinsics::uninit());
push(&mut *v, x);
}
}
@ -699,8 +694,8 @@ pub fn push_all_move<T>(v: &mut ~[T], mut rhs: ~[T]) {
unsafe {
do as_mut_buf(rhs) |p, len| {
for uint::range(0, len) |i| {
let mut x = intrinsics::init();
x <-> *ptr::mut_offset(p, i);
let x = util::replace_ptr(ptr::mut_offset(p, i),
intrinsics::init());
push(&mut *v, x);
}
}
@ -716,8 +711,7 @@ pub fn truncate<T>(v: &mut ~[T], newlen: uint) {
unsafe {
// This loop is optimized out for non-drop types.
for uint::range(newlen, oldlen) |i| {
let mut dropped = intrinsics::uninit();
dropped <-> *ptr::mut_offset(p, i);
util::replace_ptr(ptr::mut_offset(p, i), intrinsics::uninit());
}
}
}
@ -732,8 +726,7 @@ pub fn truncate<T>(v: &mut ~[T], newlen: uint) {
unsafe {
// This loop is optimized out for non-drop types.
for uint::range(newlen, oldlen) |i| {
let mut dropped = intrinsics::init();
dropped <-> *ptr::mut_offset(p, i);
util::replace_ptr(ptr::mut_offset(p, i), intrinsics::init());
}
}
}
@ -758,14 +751,14 @@ pub fn dedup<T:Eq>(v: &mut ~[T]) {
// last_written < next_to_read < ln
if *ptr::mut_offset(p, next_to_read) ==
*ptr::mut_offset(p, last_written) {
let mut dropped = intrinsics::uninit();
dropped <-> *ptr::mut_offset(p, next_to_read);
util::replace_ptr(ptr::mut_offset(p, next_to_read),
intrinsics::uninit());
} else {
last_written += 1;
// last_written <= next_to_read < ln
if next_to_read != last_written {
*ptr::mut_offset(p, last_written) <->
*ptr::mut_offset(p, next_to_read);
util::swap_ptr(ptr::mut_offset(p, last_written),
ptr::mut_offset(p, next_to_read));
}
}
// last_written <= next_to_read < ln
@ -796,14 +789,14 @@ pub fn dedup<T:Eq>(v: &mut ~[T]) {
// last_written < next_to_read < ln
if *ptr::mut_offset(p, next_to_read) ==
*ptr::mut_offset(p, last_written) {
let mut dropped = intrinsics::init();
dropped <-> *ptr::mut_offset(p, next_to_read);
util::replace_ptr(ptr::mut_offset(p, next_to_read),
intrinsics::init());
} else {
last_written += 1;
// last_written <= next_to_read < ln
if next_to_read != last_written {
*ptr::mut_offset(p, last_written) <->
*ptr::mut_offset(p, next_to_read);
util::swap_ptr(ptr::mut_offset(p, last_written),
ptr::mut_offset(p, next_to_read));
}
}
// last_written <= next_to_read < ln
@ -1028,7 +1021,7 @@ pub fn retain<T>(v: &mut ~[T], f: &fn(t: &T) -> bool) {
if !f(&v[i]) {
deleted += 1;
} else if deleted > 0 {
v[i - deleted] <-> v[i];
swap(*v, i - deleted, i);
}
}
@ -1429,15 +1422,25 @@ pub fn zip<T, U>(mut v: ~[T], mut u: ~[U]) -> ~[(T, U)] {
* * a - The index of the first element
* * b - The index of the second element
*/
#[inline(always)]
pub fn swap<T>(v: &mut [T], a: uint, b: uint) {
v[a] <-> v[b];
unsafe {
// Can't take two mutable loans from one vector, so instead just cast
// them to their raw pointers to do the swap
let pa: *mut T = ptr::to_mut_unsafe_ptr(&mut v[a]);
let pb: *mut T = ptr::to_mut_unsafe_ptr(&mut v[b]);
util::swap_ptr(pa, pb);
}
}
/// Reverse the order of elements in a vector, in place
pub fn reverse<T>(v: &mut [T]) {
let mut i: uint = 0;
let ln = len::<T>(v);
while i < ln / 2 { v[i] <-> v[ln - i - 1]; i += 1; }
while i < ln / 2 {
swap(v, i, ln - i - 1);
i += 1;
}
}
/// Returns a vector with the order of elements reversed
@ -2476,6 +2479,7 @@ pub mod raw {
use sys;
use unstable::intrinsics;
use vec::{UnboxedVecRepr, as_const_buf, as_mut_buf, len, with_capacity};
use util;
/// The internal representation of a (boxed) vector
pub struct VecRepr {
@ -2573,8 +2577,7 @@ pub mod raw {
pub unsafe fn init_elem<T>(v: &mut [T], i: uint, val: T) {
let mut box = Some(val);
do as_mut_buf(v) |p, _len| {
let mut box2 = None;
box2 <-> box;
let box2 = util::replace(&mut box, None);
intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i)),
box2.unwrap());
}

View File

@ -758,10 +758,6 @@ fn check_loans_in_expr<'a>(expr: @ast::expr,
}
match expr.node {
ast::expr_swap(l, r) => {
self.check_assignment(l);
self.check_assignment(r);
}
ast::expr_assign(dest, _) |
ast::expr_assign_op(_, dest, _) => {
self.check_assignment(dest);

View File

@ -698,11 +698,6 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
self.walk_expr(l, in_out, loop_scopes);
}
ast::expr_swap(l, r) => {
self.walk_expr(l, in_out, loop_scopes);
self.walk_expr(r, in_out, loop_scopes);
}
ast::expr_vec(ref exprs, _) => {
self.walk_exprs(*exprs, in_out, loop_scopes)
}

View File

@ -523,7 +523,7 @@ fn visit_expr(expr: @expr, self: @mut IrMaps, vt: vt<@mut IrMaps>) {
expr_binary(*) | expr_addr_of(*) | expr_copy(*) | expr_loop_body(*) |
expr_do_body(*) | expr_cast(*) | expr_unary(*) | expr_break(_) |
expr_again(_) | expr_lit(_) | expr_ret(*) | expr_block(*) |
expr_assign(*) | expr_swap(*) | expr_assign_op(*) | expr_mac(*) |
expr_assign(*) | expr_assign_op(*) | expr_mac(*) |
expr_struct(*) | expr_repeat(*) | expr_paren(*) |
expr_inline_asm(*) => {
visit::visit_expr(expr, self, vt);
@ -1141,21 +1141,6 @@ pub impl Liveness {
self.propagate_through_expr(r, succ)
}
expr_swap(l, r) => {
// see comment on lvalues in
// propagate_through_lvalue_components()
// I count swaps as `used` cause it might be something like:
// foo.bar <-> x
// and I am too lazy to distinguish this case from
// y <-> x
// (where both x, y are unused) just for a warning.
let succ = self.write_lvalue(r, succ, ACC_WRITE|ACC_READ|ACC_USE);
let succ = self.write_lvalue(l, succ, ACC_WRITE|ACC_READ|ACC_USE);
let succ = self.propagate_through_lvalue_components(r, succ);
self.propagate_through_lvalue_components(l, succ)
}
expr_assign_op(_, l, r) => {
// see comment on lvalues in
// propagate_through_lvalue_components()
@ -1533,7 +1518,7 @@ fn check_expr(expr: @expr, self: @Liveness, vt: vt<@Liveness>) {
expr_vstore(*) | expr_vec(*) | expr_tup(*) | expr_log(*) |
expr_binary(*) | expr_copy(*) | expr_loop_body(*) | expr_do_body(*) |
expr_cast(*) | expr_unary(*) | expr_ret(*) | expr_break(*) |
expr_again(*) | expr_lit(_) | expr_block(*) | expr_swap(*) |
expr_again(*) | expr_lit(_) | expr_block(*) |
expr_mac(*) | expr_addr_of(*) | expr_struct(*) | expr_repeat(*) |
expr_paren(*) => {
visit::visit_expr(expr, self, vt);

View File

@ -413,7 +413,7 @@ pub impl mem_categorization_ctxt {
ast::expr_paren(e) => self.cat_expr_unadjusted(e),
ast::expr_addr_of(*) | ast::expr_call(*) | ast::expr_swap(*) |
ast::expr_addr_of(*) | ast::expr_call(*) |
ast::expr_assign(*) | ast::expr_assign_op(*) |
ast::expr_fn_block(*) | ast::expr_ret(*) | ast::expr_loop_body(*) |
ast::expr_do_body(*) | ast::expr_unary(*) |

View File

@ -650,11 +650,6 @@ pub impl VisitContext {
self.consume_expr(count, visitor);
}
expr_swap(lhs, rhs) => {
self.use_expr(lhs, Read, visitor);
self.use_expr(rhs, Read, visitor);
}
expr_loop_body(base) |
expr_do_body(base) => {
self.use_expr(base, comp_mode, visitor);

View File

@ -528,33 +528,6 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block {
return src_datum.store_to_datum(
bcx, src.id, DROP_EXISTING, dst_datum);
}
ast::expr_swap(dst, src) => {
let dst_datum = unpack_datum!(bcx, trans_lvalue(bcx, dst));
let src_datum = unpack_datum!(bcx, trans_lvalue(bcx, src));
// If the source and destination are the same, then don't swap.
// Avoids performing an overlapping memcpy
let dst_datum_ref = dst_datum.to_ref_llval(bcx);
let src_datum_ref = src_datum.to_ref_llval(bcx);
let cmp = ICmp(bcx, lib::llvm::IntEQ,
src_datum_ref,
dst_datum_ref);
let swap_cx = base::sub_block(bcx, "swap");
let next_cx = base::sub_block(bcx, "next");
CondBr(bcx, cmp, next_cx.llbb, swap_cx.llbb);
let scratch = scratch_datum(swap_cx, dst_datum.ty, false);
let swap_cx = dst_datum.move_to_datum(swap_cx, INIT, scratch);
let swap_cx = src_datum.move_to_datum(swap_cx, INIT, dst_datum);
let swap_cx = scratch.move_to_datum(swap_cx, INIT, src_datum);
Br(swap_cx, next_cx.llbb);
return next_cx;
}
ast::expr_assign_op(op, dst, src) => {
return trans_assign_op(bcx, expr, op, dst, src);
}

View File

@ -314,7 +314,7 @@ pub fn mark_for_expr(cx: Context, e: @expr) {
}
}
}
expr_assign(val, _) | expr_swap(val, _) | expr_assign_op(_, val, _) |
expr_assign(val, _) | expr_assign_op(_, val, _) |
expr_ret(Some(val)) => {
node_type_needs(cx, use_repr, val.id);
}

View File

@ -3465,7 +3465,6 @@ pub fn expr_kind(tcx: ctxt,
ast::expr_while(*) |
ast::expr_loop(*) |
ast::expr_assign(*) |
ast::expr_swap(*) |
ast::expr_inline_asm(*) |
ast::expr_assign_op(*) => {
RvalueStmtExpr

View File

@ -2460,20 +2460,6 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
fcx.write_nil(id);
}
}
ast::expr_swap(lhs, rhs) => {
check_assignment(fcx, lhs, rhs, id);
let lhs_ty = fcx.expr_ty(lhs);
let rhs_ty = fcx.expr_ty(rhs);
if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
fcx.write_error(id);
}
else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
fcx.write_bot(id);
}
else {
fcx.write_nil(id);
}
}
ast::expr_if(cond, ref thn, elsopt) => {
check_expr_has_type(fcx, cond, ty::mk_bool());
check_then_else(fcx, thn, elsopt, id, expr.span);

View File

@ -1016,7 +1016,6 @@ pub mod guarantor {
ast::expr_while(*) |
ast::expr_loop(*) |
ast::expr_assign(*) |
ast::expr_swap(*) |
ast::expr_assign_op(*) |
ast::expr_cast(*) |
ast::expr_call(*) |

View File

@ -96,10 +96,6 @@ fn record(repl: Repl, blk: @ast::blk, intr: @token::ident_interner) -> Repl {
match expr.node {
ast::expr_assign(*) |
ast::expr_assign_op(*) |
ast::expr_swap(*) => {
pprust::print_stmt(pp, *stmt);
writer.write_line(~"");
}
_ => {}
}
}

View File

@ -10,6 +10,8 @@
//! A double-ended queue implemented as a circular buffer
use core::util::replace;
static initial_capacity: uint = 32u; // 2^5
pub struct Deque<T> {
@ -142,9 +144,7 @@ fn grow<T>(nelts: uint, lo: uint, elts: &mut [Option<T>]) -> ~[Option<T>] {
let mut rv = ~[];
do rv.grow_fn(nelts + 1) |i| {
let mut element = None;
element <-> elts[(lo + i) % nelts];
element
replace(&mut elts[(lo + i) % nelts], None)
}
rv

View File

@ -26,6 +26,7 @@ use core::cell::Cell;
use core::comm::{PortOne, oneshot, send_one};
use core::pipes::recv;
use core::task;
use core::util::replace;
#[doc = "The future type"]
#[cfg(stage0)]
@ -77,8 +78,7 @@ pub impl<A> Future<A> {
}
}
{
let mut state = Evaluating;
self.state <-> state;
let state = replace(&mut self.state, Evaluating);
match state {
Forced(_) | Evaluating => fail!(~"Logic error."),
Pending(f) => {
@ -108,8 +108,7 @@ pub impl<A> Future<A> {
}
}
{
let mut state = Evaluating;
self.state <-> state;
let state = replace(&mut self.state, Evaluating);
match state {
Forced(_) | Evaluating => fail!(~"Logic error."),
Pending(f) => {

View File

@ -11,6 +11,7 @@
//! A priority queue implemented with a binary heap
use core::old_iter::BaseIter;
use core::util::{replace, swap};
#[abi = "rust-intrinsic"]
extern "rust-intrinsic" mod rusti {
@ -73,7 +74,10 @@ pub impl <T:Ord> PriorityQueue<T> {
/// Pop the greatest item from the queue - fails if empty
fn pop(&mut self) -> T {
let mut item = self.data.pop();
if !self.is_empty() { item <-> self.data[0]; self.siftdown(0); }
if !self.is_empty() {
swap(&mut item, &mut self.data[0]);
self.siftdown(0);
}
item
}
@ -92,7 +96,7 @@ pub impl <T:Ord> PriorityQueue<T> {
/// Optimized version of a push followed by a pop
fn push_pop(&mut self, mut item: T) -> T {
if !self.is_empty() && self.data[0] > item {
item <-> self.data[0];
swap(&mut item, &mut self.data[0]);
self.siftdown(0);
}
item
@ -100,7 +104,7 @@ pub impl <T:Ord> PriorityQueue<T> {
/// Optimized version of a pop followed by a push - fails if empty
fn replace(&mut self, mut item: T) -> T {
item <-> self.data[0];
swap(&mut item, &mut self.data[0]);
self.siftdown(0);
item
}
@ -115,7 +119,7 @@ pub impl <T:Ord> PriorityQueue<T> {
let mut end = q.len();
while end > 1 {
end -= 1;
q.data[end] <-> q.data[0];
vec::swap(q.data, 0, end);
q.siftdown_range(0, end)
}
q.to_vec()
@ -149,8 +153,7 @@ pub impl <T:Ord> PriorityQueue<T> {
while pos > start {
let parent = (pos - 1) >> 1;
if new > self.data[parent] {
let mut x = rusti::uninit();
x <-> self.data[parent];
let x = replace(&mut self.data[parent], rusti::uninit());
rusti::move_val_init(&mut self.data[pos], x);
pos = parent;
loop
@ -169,8 +172,7 @@ pub impl <T:Ord> PriorityQueue<T> {
while pos > start {
let parent = (pos - 1) >> 1;
if new > self.data[parent] {
let mut x = rusti::init();
x <-> self.data[parent];
let x = replace(&mut self.data[parent], rusti::init());
rusti::move_val_init(&mut self.data[pos], x);
pos = parent;
loop
@ -194,8 +196,7 @@ pub impl <T:Ord> PriorityQueue<T> {
if right < end && !(self.data[child] > self.data[right]) {
child = right;
}
let mut x = rusti::uninit();
x <-> self.data[child];
let x = replace(&mut self.data[child], rusti::uninit());
rusti::move_val_init(&mut self.data[pos], x);
pos = child;
child = 2 * pos + 1;
@ -218,8 +219,7 @@ pub impl <T:Ord> PriorityQueue<T> {
if right < end && !(self.data[child] > self.data[right]) {
child = right;
}
let mut x = rusti::init();
x <-> self.data[child];
let x = replace(&mut self.data[child], rusti::init());
rusti::move_val_init(&mut self.data[pos], x);
pos = child;
child = 2 * pos + 1;

View File

@ -17,6 +17,7 @@ destruction. They are restricted to containing `Owned` types in order to prevent
use core::libc::{c_void, size_t, malloc, free};
use core::unstable::intrinsics;
use core::util;
struct RcBox<T> {
value: T,
@ -52,8 +53,7 @@ impl<T: Owned> Drop for Rc<T> {
unsafe {
(*self.ptr).count -= 1;
if (*self.ptr).count == 0 {
let mut x = intrinsics::uninit();
x <-> *self.ptr;
util::replace_ptr(self.ptr, intrinsics::uninit());
free(self.ptr as *c_void)
}
}
@ -67,8 +67,7 @@ impl<T: Owned> Drop for Rc<T> {
unsafe {
(*self.ptr).count -= 1;
if (*self.ptr).count == 0 {
let mut x = intrinsics::init();
x <-> *self.ptr;
util::replace_ptr(self.ptr, intrinsics::init());
free(self.ptr as *c_void)
}
}
@ -111,13 +110,6 @@ mod test_rc {
}
}
#[abi = "rust-intrinsic"]
extern "rust-intrinsic" mod rusti {
fn init<T>() -> T;
#[cfg(not(stage0))]
fn uninit<T>() -> T;
}
#[deriving(Eq)]
enum Borrow {
Mutable,
@ -179,8 +171,7 @@ impl<T: Owned> Drop for RcMut<T> {
unsafe {
(*self.ptr).count -= 1;
if (*self.ptr).count == 0 {
let mut x = rusti::uninit();
x <-> *self.ptr;
util::replace_ptr(self.ptr, intrinsics::uninit());
free(self.ptr as *c_void)
}
}
@ -194,8 +185,7 @@ impl<T: Owned> Drop for RcMut<T> {
unsafe {
(*self.ptr).count -= 1;
if (*self.ptr).count == 0 {
let mut x = rusti::init();
x <-> *self.ptr;
util::replace_ptr(self.ptr, intrinsics::init());
free(self.ptr as *c_void)
}
}

View File

@ -13,6 +13,7 @@
use core::cmp::{Eq, Ord};
use core::vec::len;
use core::vec;
use core::util::swap;
type Le<'self, T> = &'self fn(v1: &T, v2: &T) -> bool;
@ -63,36 +64,36 @@ pub fn merge_sort<T:Copy>(v: &[T], le: Le<T>) -> ~[T] {
#[cfg(stage0)]
fn part<T>(arr: &mut [T], left: uint,
right: uint, pivot: uint, compare_func: Le<T>) -> uint {
arr[pivot] <-> arr[right];
swap(&mut arr[pivot], &mut arr[right]);
let mut storage_index: uint = left;
let mut i: uint = left;
while i < right {
let a: &mut T = &mut arr[i];
let b: &mut T = &mut arr[right];
if compare_func(a, b) {
arr[i] <-> arr[storage_index];
swap(&mut arr[i], &mut arr[storage_index]);
storage_index += 1;
}
i += 1;
}
arr[storage_index] <-> arr[right];
swap(&mut arr[storage_index], &mut arr[right]);
return storage_index;
}
#[cfg(not(stage0))]
fn part<T>(arr: &mut [T], left: uint,
right: uint, pivot: uint, compare_func: Le<T>) -> uint {
arr[pivot] <-> arr[right];
vec::swap(arr, pivot, right);
let mut storage_index: uint = left;
let mut i: uint = left;
while i < right {
if compare_func(&arr[i], &arr[right]) {
arr[i] <-> arr[storage_index];
vec::swap(arr, i, storage_index);
storage_index += 1;
}
i += 1;
}
arr[storage_index] <-> arr[right];
vec::swap(arr, storage_index, right);
return storage_index;
}
@ -136,29 +137,29 @@ fn qsort3<T:Copy + Ord + Eq>(arr: &mut [T], left: int, right: int) {
j -= 1;
}
if i >= j { break; }
arr[i] <-> arr[j];
vec::swap(arr, i as uint, j as uint);
if arr[i] == v {
p += 1;
arr[p] <-> arr[i];
vec::swap(arr, p as uint, i as uint);
}
if v == arr[j] {
q -= 1;
arr[j] <-> arr[q];
vec::swap(arr, j as uint, q as uint);
}
}
arr[i] <-> arr[right];
vec::swap(arr, i as uint, right as uint);
j = i - 1;
i += 1;
let mut k: int = left;
while k < p {
arr[k] <-> arr[j];
vec::swap(arr, k as uint, j as uint);
k += 1;
j -= 1;
if k == len::<T>(arr) as int { break; }
}
k = right - 1;
while k > q {
arr[i] <-> arr[k];
vec::swap(arr, i as uint, k as uint);
k -= 1;
i += 1;
if k == 0 { break; }
@ -273,7 +274,7 @@ fn binarysort<T:Copy + Ord>(array: &mut [T], start: uint) {
fn reverse_slice<T>(v: &mut [T], start: uint, end:uint) {
let mut i = start;
while i < end / 2 {
v[i] <-> v[end - i - 1];
vec::swap(v, i, end - i - 1);
i += 1;
}
}
@ -493,7 +494,7 @@ impl<T:Copy + Ord> MergeState<T> {
let mut len1 = len1;
let mut len2 = len2;
array[dest] <-> array[c2];
vec::swap(array, dest, c2);
dest += 1; c2 += 1; len2 -= 1;
if len2 == 0 {
@ -502,7 +503,7 @@ impl<T:Copy + Ord> MergeState<T> {
}
if len1 == 1 {
shift_vec(array, dest, c2, len2);
array[dest+len2] <-> tmp[c1];
swap(&mut tmp[c1], &mut array[dest+len2]);
return;
}
@ -515,14 +516,14 @@ impl<T:Copy + Ord> MergeState<T> {
loop {
assert!(len1 > 1 && len2 != 0);
if array[c2] < tmp[c1] {
array[dest] <-> array[c2];
vec::swap(array, dest, c2);
dest += 1; c2 += 1; len2 -= 1;
count2 += 1; count1 = 0;
if len2 == 0 {
break_outer = true;
}
} else {
array[dest] <-> tmp[c1];
swap(&mut array[dest], &mut tmp[c1]);
dest += 1; c1 += 1; len1 -= 1;
count1 += 1; count2 = 0;
if len1 == 1 {
@ -548,7 +549,7 @@ impl<T:Copy + Ord> MergeState<T> {
dest += count1; c1 += count1; len1 -= count1;
if len1 <= 1 { break_outer = true; break; }
}
array[dest] <-> array[c2];
vec::swap(array, dest, c2);
dest += 1; c2 += 1; len2 -= 1;
if len2 == 0 { break_outer = true; break; }
@ -561,7 +562,7 @@ impl<T:Copy + Ord> MergeState<T> {
dest += count2; c2 += count2; len2 -= count2;
if len2 == 0 { break_outer = true; break; }
}
array[dest] <-> tmp[c1];
swap(&mut array[dest], &mut tmp[c1]);
dest += 1; c1 += 1; len1 -= 1;
if len1 == 1 { break_outer = true; break; }
min_gallop -= 1;
@ -578,7 +579,7 @@ impl<T:Copy + Ord> MergeState<T> {
if len1 == 1 {
assert!(len2 > 0);
shift_vec(array, dest, c2, len2);
array[dest+len2] <-> tmp[c1];
swap(&mut array[dest+len2], &mut tmp[c1]);
} else if len1 == 0 {
fail!(~"Comparison violates its contract!");
} else {
@ -603,7 +604,7 @@ impl<T:Copy + Ord> MergeState<T> {
let mut len1 = len1;
let mut len2 = len2;
array[dest] <-> array[c1];
vec::swap(array, dest, c1);
dest -= 1; c1 -= 1; len1 -= 1;
if len1 == 0 {
@ -614,7 +615,7 @@ impl<T:Copy + Ord> MergeState<T> {
dest -= len1;
c1 -= len1;
shift_vec(array, dest+1, c1+1, len1);
array[dest] <-> tmp[c2];
swap(&mut array[dest], &mut tmp[c2]);
return;
}
@ -627,14 +628,14 @@ impl<T:Copy + Ord> MergeState<T> {
loop {
assert!(len1 != 0 && len2 > 1);
if tmp[c2] < array[c1] {
array[dest] <-> array[c1];
vec::swap(array, dest, c1);
dest -= 1; c1 -= 1; len1 -= 1;
count1 += 1; count2 = 0;
if len1 == 0 {
break_outer = true;
}
} else {
array[dest] <-> tmp[c2];
swap(&mut array[dest], &mut tmp[c2]);
dest -= 1; c2 -= 1; len2 -= 1;
count2 += 1; count1 = 0;
if len2 == 1 {
@ -663,7 +664,7 @@ impl<T:Copy + Ord> MergeState<T> {
if len1 == 0 { break_outer = true; break; }
}
array[dest] <-> tmp[c2];
swap(&mut array[dest], &mut tmp[c2]);
dest -= 1; c2 -= 1; len2 -= 1;
if len2 == 1 { break_outer = true; break; }
@ -680,7 +681,7 @@ impl<T:Copy + Ord> MergeState<T> {
copy_vec(array, dest+1, tmp.slice(c2+1, c2+1+count2));
if len2 <= 1 { break_outer = true; break; }
}
array[dest] <-> array[c1];
vec::swap(array, dest, c1);
dest -= 1; c1 -= 1; len1 -= 1;
if len1 == 0 { break_outer = true; break; }
min_gallop -= 1;
@ -700,7 +701,7 @@ impl<T:Copy + Ord> MergeState<T> {
dest -= len1;
c1 -= len1;
shift_vec(array, dest+1, c1+1, len1);
array[dest] <-> tmp[c2];
swap(&mut array[dest], &mut tmp[c2]);
} else if len2 == 0 {
fail!(~"Comparison violates its contract!");
} else {
@ -1090,7 +1091,7 @@ mod big_tests {
for 3.times {
let i1 = rng.gen_uint_range(0, n);
let i2 = rng.gen_uint_range(0, n);
arr[i1] <-> arr[i2];
vec::swap(arr, i1, i2);
}
tim_sort(arr); // 3sort
isSorted(arr);
@ -1162,7 +1163,7 @@ mod big_tests {
for 3.times {
let i1 = rng.gen_uint_range(0, n);
let i2 = rng.gen_uint_range(0, n);
arr[i1] <-> arr[i2];
vec::swap(arr, i1, i2);
}
tim_sort(arr); // 3sort
isSorted(arr);

View File

@ -13,6 +13,7 @@
use core::cmp::{Eq, Ord};
use core::vec::len;
use core::vec;
use core::util;
type Le<'self, T> = &'self fn(v1: &T, v2: &T) -> bool;
@ -63,36 +64,36 @@ pub fn merge_sort<T:Copy>(v: &const [T], le: Le<T>) -> ~[T] {
#[cfg(stage0)]
fn part<T>(arr: &mut [T], left: uint,
right: uint, pivot: uint, compare_func: Le<T>) -> uint {
arr[pivot] <-> arr[right];
vec::swap(arr, pivot, right);
let mut storage_index: uint = left;
let mut i: uint = left;
while i < right {
let a: &mut T = &mut arr[i];
let b: &mut T = &mut arr[right];
if compare_func(a, b) {
arr[i] <-> arr[storage_index];
vec::swap(arr, i, storage_index);
storage_index += 1;
}
i += 1;
}
arr[storage_index] <-> arr[right];
vec::swap(arr, storage_index, right);
return storage_index;
}
#[cfg(not(stage0))]
fn part<T>(arr: &mut [T], left: uint,
right: uint, pivot: uint, compare_func: Le<T>) -> uint {
arr[pivot] <-> arr[right];
vec::swap(arr, pivot, right);
let mut storage_index: uint = left;
let mut i: uint = left;
while i < right {
if compare_func(&arr[i], &arr[right]) {
arr[i] <-> arr[storage_index];
vec::swap(arr, i, storage_index);
storage_index += 1;
}
i += 1;
}
arr[storage_index] <-> arr[right];
vec::swap(arr, storage_index, right);
return storage_index;
}
@ -136,29 +137,29 @@ fn qsort3<T:Copy + Ord + Eq>(arr: &mut [T], left: int, right: int) {
j -= 1;
}
if i >= j { break; }
arr[i] <-> arr[j];
vec::swap(arr, i as uint, j as uint);
if arr[i] == v {
p += 1;
arr[p] <-> arr[i];
vec::swap(arr, p as uint, i as uint);
}
if v == arr[j] {
q -= 1;
arr[j] <-> arr[q];
vec::swap(arr, j as uint, q as uint);
}
}
arr[i] <-> arr[right];
vec::swap(arr, i as uint, right as uint);
j = i - 1;
i += 1;
let mut k: int = left;
while k < p {
arr[k] <-> arr[j];
vec::swap(arr, k as uint, j as uint);
k += 1;
j -= 1;
if k == len::<T>(arr) as int { break; }
}
k = right - 1;
while k > q {
arr[i] <-> arr[k];
vec::swap(arr, i as uint, k as uint);
k -= 1;
i += 1;
if k == 0 { break; }
@ -273,7 +274,7 @@ fn binarysort<T:Copy + Ord>(array: &mut [T], start: uint) {
fn reverse_slice<T>(v: &mut [T], start: uint, end:uint) {
let mut i = start;
while i < end / 2 {
v[i] <-> v[end - i - 1];
vec::swap(v, i, end - i - 1);
i += 1;
}
}
@ -493,7 +494,7 @@ impl<T:Copy + Ord> MergeState<T> {
let mut len1 = len1;
let mut len2 = len2;
array[dest] <-> array[c2];
vec::swap(array, dest, c2);
dest += 1; c2 += 1; len2 -= 1;
if len2 == 0 {
@ -502,7 +503,7 @@ impl<T:Copy + Ord> MergeState<T> {
}
if len1 == 1 {
copy_vec(array, dest, array, c2, len2);
array[dest+len2] <-> tmp[c1];
util::swap(&mut array[dest+len2], &mut tmp[c1]);
return;
}
@ -515,14 +516,14 @@ impl<T:Copy + Ord> MergeState<T> {
loop {
assert!(len1 > 1 && len2 != 0);
if array[c2] < tmp[c1] {
array[dest] <-> array[c2];
vec::swap(array, dest, c2);
dest += 1; c2 += 1; len2 -= 1;
count2 += 1; count1 = 0;
if len2 == 0 {
break_outer = true;
}
} else {
array[dest] <-> tmp[c1];
util::swap(&mut array[dest], &mut tmp[c1]);
dest += 1; c1 += 1; len1 -= 1;
count1 += 1; count2 = 0;
if len1 == 1 {
@ -546,7 +547,7 @@ impl<T:Copy + Ord> MergeState<T> {
dest += count1; c1 += count1; len1 -= count1;
if len1 <= 1 { break_outer = true; break; }
}
array[dest] <-> array[c2];
vec::swap(array, dest, c2);
dest += 1; c2 += 1; len2 -= 1;
if len2 == 0 { break_outer = true; break; }
@ -557,7 +558,7 @@ impl<T:Copy + Ord> MergeState<T> {
dest += count2; c2 += count2; len2 -= count2;
if len2 == 0 { break_outer = true; break; }
}
array[dest] <-> tmp[c1];
util::swap(&mut array[dest], &mut tmp[c1]);
dest += 1; c1 += 1; len1 -= 1;
if len1 == 1 { break_outer = true; break; }
min_gallop -= 1;
@ -574,7 +575,7 @@ impl<T:Copy + Ord> MergeState<T> {
if len1 == 1 {
assert!(len2 > 0);
copy_vec(array, dest, array, c2, len2);
array[dest+len2] <-> tmp[c1];
util::swap(&mut array[dest+len2], &mut tmp[c1]);
} else if len1 == 0 {
fail!(~"Comparison violates its contract!");
} else {
@ -599,7 +600,7 @@ impl<T:Copy + Ord> MergeState<T> {
let mut len1 = len1;
let mut len2 = len2;
array[dest] <-> array[c1];
vec::swap(array, dest, c1);
dest -= 1; c1 -= 1; len1 -= 1;
if len1 == 0 {
@ -610,7 +611,7 @@ impl<T:Copy + Ord> MergeState<T> {
dest -= len1;
c1 -= len1;
copy_vec(array, dest+1, array, c1+1, len1);
array[dest] <-> tmp[c2];
util::swap(&mut array[dest], &mut tmp[c2]);
return;
}
@ -623,14 +624,14 @@ impl<T:Copy + Ord> MergeState<T> {
loop {
assert!(len1 != 0 && len2 > 1);
if tmp[c2] < array[c1] {
array[dest] <-> array[c1];
vec::swap(array, dest, c1);
dest -= 1; c1 -= 1; len1 -= 1;
count1 += 1; count2 = 0;
if len1 == 0 {
break_outer = true;
}
} else {
array[dest] <-> tmp[c2];
util::swap(&mut array[dest], &mut tmp[c2]);
dest -= 1; c2 -= 1; len2 -= 1;
count2 += 1; count1 = 0;
if len2 == 1 {
@ -659,7 +660,7 @@ impl<T:Copy + Ord> MergeState<T> {
if len1 == 0 { break_outer = true; break; }
}
array[dest] <-> tmp[c2];
util::swap(&mut array[dest], &mut tmp[c2]);
dest -= 1; c2 -= 1; len2 -= 1;
if len2 == 1 { break_outer = true; break; }
@ -676,7 +677,7 @@ impl<T:Copy + Ord> MergeState<T> {
copy_vec(array, dest+1, tmp, c2+1, count2);
if len2 <= 1 { break_outer = true; break; }
}
array[dest] <-> array[c1];
vec::swap(array, dest, c1);
dest -= 1; c1 -= 1; len1 -= 1;
if len1 == 0 { break_outer = true; break; }
min_gallop -= 1;
@ -696,7 +697,7 @@ impl<T:Copy + Ord> MergeState<T> {
dest -= len1;
c1 -= len1;
copy_vec(array, dest+1, array, c1+1, len1);
array[dest] <-> tmp[c2];
util::swap(&mut array[dest], &mut tmp[c2]);
} else if len2 == 0 {
fail!(~"Comparison violates its contract!");
} else {
@ -1081,7 +1082,7 @@ mod big_tests {
for 3.times {
let i1 = rng.gen_uint_range(0, n);
let i2 = rng.gen_uint_range(0, n);
arr[i1] <-> arr[i2];
vec::swap(arr, i1, i2);
}
tim_sort(arr); // 3sort
isSorted(arr);
@ -1153,7 +1154,7 @@ mod big_tests {
for 3.times {
let i1 = rng.gen_uint_range(0, n);
let i2 = rng.gen_uint_range(0, n);
arr[i1] <-> arr[i2];
vec::swap(arr, i1, i2);
}
tim_sort(arr); // 3sort
isSorted(arr);

View File

@ -13,7 +13,7 @@
//! `TotalOrd`.
use core::iterator::*;
use core::util::replace;
use core::util::{swap, replace};
// This is implemented as an AA tree, which is a simplified variation of
// a red-black tree where where red (horizontal) nodes can only be added
@ -756,8 +756,8 @@ fn mutate_values<'r, K: TotalOrd, V>(node: &'r mut Option<~TreeNode<K, V>>,
fn skew<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>) {
if node.left.map_default(false, |x| x.level == node.level) {
let mut save = node.left.swap_unwrap();
node.left <-> save.right; // save.right now None
*node <-> save;
swap(&mut node.left, &mut save.right); // save.right now None
swap(node, &mut save);
node.right = Some(save);
}
}
@ -768,9 +768,9 @@ fn split<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>) {
if node.right.map_default(false,
|x| x.right.map_default(false, |y| y.level == node.level)) {
let mut save = node.right.swap_unwrap();
node.right <-> save.left; // save.left now None
swap(&mut node.right, &mut save.left); // save.left now None
save.level += 1;
*node <-> save;
swap(node, &mut save);
node.left = Some(save);
}
}
@ -823,14 +823,14 @@ fn insert<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>,
fn remove<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>,
key: &K) -> Option<V> {
fn heir_swap<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>,
child: &mut Option<~TreeNode<K, V>>) {
child: &mut Option<~TreeNode<K, V>>) {
// *could* be done without recursion, but it won't borrow check
for child.each_mut |x| {
if x.right.is_some() {
heir_swap(node, &mut x.right);
} else {
node.key <-> x.key;
node.value <-> x.value;
swap(&mut node.key, &mut x.key);
swap(&mut node.value, &mut x.value);
}
}
}
@ -850,8 +850,8 @@ fn remove<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>,
if left.right.is_some() {
heir_swap(save, &mut left.right);
} else {
save.key <-> left.key;
save.value <-> left.value;
swap(&mut save.key, &mut left.key);
swap(&mut save.value, &mut left.value);
}
save.left = Some(left);
(remove(&mut save.left, key), true)

View File

@ -22,6 +22,7 @@ use core::io;
use core::pipes::recv;
use core::run;
use core::to_bytes;
use core::util::replace;
/**
*
@ -352,9 +353,7 @@ impl TPrep for Prep {
_ => {
let (port, chan) = oneshot();
let mut blk = None;
blk <-> bo;
let blk = blk.unwrap();
let blk = replace(&mut bo, None).unwrap();
let chan = Cell(chan);
do task::spawn {
@ -386,9 +385,7 @@ fn unwrap<T:Owned +
Decodable<json::Decoder>>( // FIXME(#5121)
w: Work<T>) -> T {
let mut ww = w;
let mut s = None;
ww.res <-> s;
let s = replace(&mut ww.res, None);
match s {
None => fail!(),

View File

@ -569,7 +569,6 @@ pub enum expr_ {
expr_copy(@expr),
expr_assign(@expr, @expr),
expr_swap(@expr, @expr),
expr_assign_op(binop, @expr, @expr),
expr_field(@expr, ident, ~[@Ty]),
expr_index(@expr, @expr),

View File

@ -511,9 +511,6 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ {
expr_assign(el, er) => {
expr_assign(fld.fold_expr(el), fld.fold_expr(er))
}
expr_swap(el, er) => {
expr_swap(fld.fold_expr(el), fld.fold_expr(er))
}
expr_assign_op(op, el, er) => {
expr_assign_op(op, fld.fold_expr(el), fld.fold_expr(er))
}

View File

@ -40,6 +40,7 @@ pub enum ObsoleteSyntax {
ObsoleteModeInFnType,
ObsoleteMoveInit,
ObsoleteBinaryMove,
ObsoleteSwap,
ObsoleteUnsafeBlock,
ObsoleteUnenforcedBound,
ObsoleteImplSyntax,
@ -129,6 +130,10 @@ pub impl Parser {
"binary move",
"Write `foo = move bar` instead"
),
ObsoleteSwap => (
"swap",
"Use core::util::{swap, replace} instead"
),
ObsoleteUnsafeBlock => (
"non-standalone unsafe block",
"use an inner `unsafe { ... }` block instead"

View File

@ -26,7 +26,7 @@ use ast::{expr_break, expr_call, expr_cast, expr_copy, expr_do_body};
use ast::{expr_field, expr_fn_block, expr_if, expr_index};
use ast::{expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac};
use ast::{expr_method_call, expr_paren, expr_path, expr_repeat};
use ast::{expr_ret, expr_swap, expr_struct, expr_tup, expr_unary};
use ast::{expr_ret, expr_struct, expr_tup, expr_unary};
use ast::{expr_vec, expr_vstore, expr_vstore_mut_box};
use ast::{expr_vstore_slice, expr_vstore_box};
use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl};
@ -70,7 +70,7 @@ use parse::lexer::reader;
use parse::lexer::TokenAndSpan;
use parse::obsolete::{ObsoleteClassTraits};
use parse::obsolete::{ObsoleteLet, ObsoleteFieldTerminator};
use parse::obsolete::{ObsoleteMoveInit, ObsoleteBinaryMove};
use parse::obsolete::{ObsoleteMoveInit, ObsoleteBinaryMove, ObsoleteSwap};
use parse::obsolete::{ObsoleteSyntax, ObsoleteLowerCaseKindBounds};
use parse::obsolete::{ObsoleteUnsafeBlock, ObsoleteImplSyntax};
use parse::obsolete::{ObsoleteTraitBoundSeparator, ObsoleteMutOwnedPointer};
@ -1849,9 +1849,11 @@ pub impl Parser {
expr_break(None))
}
token::DARROW => {
self.obsolete(*self.span, ObsoleteSwap);
self.bump();
let rhs = self.parse_expr();
self.mk_expr(lo, rhs.span.hi, expr_swap(lhs, rhs))
// Ignore what we get, this is an error anyway
self.parse_expr();
self.mk_expr(lo, self.span.hi, expr_break(None))
}
_ => {
lhs

View File

@ -1328,12 +1328,6 @@ pub fn print_expr(s: @ps, expr: @ast::expr) {
word_space(s, ~"=");
print_expr(s, rhs);
}
ast::expr_swap(lhs, rhs) => {
print_expr(s, lhs);
space(s.s);
word_space(s, ~"<->");
print_expr(s, rhs);
}
ast::expr_assign_op(op, lhs, rhs) => {
print_expr(s, lhs);
space(s.s);

View File

@ -516,10 +516,6 @@ pub fn visit_expr<E: Copy>(ex: @expr, e: E, v: vt<E>) {
(v.visit_expr)(a, e, v);
}
expr_copy(a) => (v.visit_expr)(a, e, v),
expr_swap(a, b) => {
(v.visit_expr)(a, e, v);
(v.visit_expr)(b, e, v);
}
expr_assign_op(_, a, b) => {
(v.visit_expr)(b, e, v);
(v.visit_expr)(a, e, v);

View File

@ -14,6 +14,7 @@ extern mod std;
use std::time::precise_time_s;
use core::rand::RngUtil;
use core::util;
macro_rules! bench (
($id:ident) => (maybe_run_test(argv, stringify!($id).to_owned(), $id))
@ -115,7 +116,7 @@ fn vec_push_all() {
v.push_all(rv);
}
else {
v <-> rv;
util::swap(&mut v, &mut rv);
v.push_all(rv);
}
}

View File

@ -20,6 +20,7 @@ extern mod std;
use core::cell::Cell;
use core::pipes::recv;
use core::util;
use std::time;
use std::future;
@ -42,10 +43,8 @@ fn thread_ring(i: uint,
// Send/Receive lots of messages.
for uint::range(0, count) |j| {
//error!("task %?, iter %?", i, j);
let mut num_chan2 = None;
let mut num_port2 = None;
num_chan2 <-> num_chan;
num_port2 <-> num_port;
let num_chan2 = util::replace(&mut num_chan, None);
let num_port2 = util::replace(&mut num_port, None);
num_chan = Some(ring::client::num(num_chan2.unwrap(), i * j));
let port = num_port2.unwrap();
match recv(port) {

View File

@ -17,6 +17,7 @@ use core::hashmap::HashMap;
use core::io::ReaderUtil;
use core::comm::{stream, Port, Chan};
use core::cmp::Ord;
use core::util;
// given a map, print a sorted version of it
fn sort_and_fmt(mm: &HashMap<~[u8], uint>, total: uint) -> ~str {
@ -159,8 +160,7 @@ fn main() {
let mut from_child = ~[];
let to_child = vec::mapi(sizes, |ii, sz| {
let sz = *sz;
let mut stream = None;
stream <-> streams[ii];
let stream = util::replace(&mut streams[ii], None);
let (from_child_, to_parent_) = stream.unwrap();
from_child.push(from_child_);

View File

@ -1,28 +0,0 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn test1() {
let v: int;
let mut w: int;
v = 1; //~ NOTE prior assignment occurs here
w = 2;
v <-> w; //~ ERROR re-assignment of immutable variable
}
fn test2() {
let v: int;
let mut w: int;
v = 1; //~ NOTE prior assignment occurs here
w = 2;
w <-> v; //~ ERROR re-assignment of immutable variable
}
fn main() {
}

View File

@ -1,16 +0,0 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
let mut x = 3;
let y;
x <-> y; //~ ERROR use of possibly uninitialized variable: `y`
copy x;
}

View File

@ -87,7 +87,7 @@ fn f110() {
fn f120() {
let x = ~[~"hi", ~"ho"];
x[0] <-> x[1];
vec::swap(x, 0, 1);
touch(&x[0]);
touch(&x[1]);
}

View File

@ -1,15 +0,0 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
5 <-> 3;
//~^ ERROR cannot assign
//~^^ ERROR cannot assign
}

View File

@ -8,14 +8,16 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::util;
struct Ints {sum: ~int, values: ~[int]}
fn add_int(x: &mut Ints, v: int) {
*x.sum += v;
let mut values = ~[];
x.values <-> values;
util::swap(&mut values, &mut x.values);
values.push(v);
x.values <-> values;
util::swap(&mut values, &mut x.values);
}
fn iter_ints(x: &Ints, f: &fn(x: &int) -> bool) -> bool {

View File

@ -10,8 +10,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::util;
// tjc: I don't know why
pub mod pipes {
use core::util;
use core::cast::{forget, transmute};
pub struct Stuff<T> {
@ -104,8 +107,7 @@ pub mod pipes {
match old_state {
empty | blocked => { task::yield(); }
full => {
let mut payload = None;
payload <-> (*p).payload;
let payload = util::replace(&mut p.payload, None);
return Some(payload.unwrap())
}
terminated => {
@ -159,10 +161,9 @@ pub mod pipes {
fn finalize(&self) {
unsafe {
if self.p != None {
let mut p = None;
let self_p: &mut Option<*packet<T>> =
cast::transmute(&self.p);
p <-> *self_p;
let p = util::replace(self_p, None);
sender_terminate(p.unwrap())
}
}
@ -171,9 +172,7 @@ pub mod pipes {
pub impl<T:Owned> send_packet<T> {
fn unwrap(&mut self) -> *packet<T> {
let mut p = None;
p <-> self.p;
p.unwrap()
util::replace(&mut self.p, None).unwrap()
}
}
@ -192,10 +191,9 @@ pub mod pipes {
fn finalize(&self) {
unsafe {
if self.p != None {
let mut p = None;
let self_p: &mut Option<*packet<T>> =
cast::transmute(&self.p);
p <-> *self_p;
let p = util::replace(self_p, None);
receiver_terminate(p.unwrap())
}
}
@ -204,9 +202,7 @@ pub mod pipes {
pub impl<T:Owned> recv_packet<T> {
fn unwrap(&mut self) -> *packet<T> {
let mut p = None;
p <-> self.p;
p.unwrap()
util::replace(&mut self.p, None).unwrap()
}
}
@ -225,6 +221,7 @@ pub mod pipes {
pub mod pingpong {
use core::cast;
use core::ptr;
use core::util;
pub struct ping(::pipes::send_packet<pong>);
pub struct pong(::pipes::send_packet<ping>);

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::util;
pub fn main() {
let mut x = 4;
@ -24,6 +26,6 @@ pub fn main() {
}
}
let mut y = 4;
y <-> x;
util::swap(&mut y, &mut x);
}
}

View File

@ -8,7 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::util;
pub fn main() {
let mut x = 3; let mut y = 7;
x <-> y; assert!((x == 7)); assert!((y == 3));
util::swap(&mut x, &mut y);
assert!((x == 7)); assert!((y == 3));
}

View File

@ -8,15 +8,15 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn swap<T>(v: &mut [T], i: int, j: int) { v[i] <-> v[j]; }
use core::util;
pub fn main() {
let mut a: ~[int] = ~[0, 1, 2, 3, 4, 5, 6];
swap(a, 2, 4);
vec::swap(a, 2, 4);
assert!((a[2] == 4));
assert!((a[4] == 2));
let mut n = 42;
n <-> a[0];
util::swap(&mut n, &mut a[0]);
assert!((a[0] == 42));
assert!((n == 0));
}

View File

@ -10,6 +10,8 @@
// Issue #5041 - avoid overlapping memcpy when src and dest of a swap are the same
use core::util;
pub fn main() {
let mut test = TestDescAndFn {
desc: TestDesc {
@ -22,7 +24,10 @@ pub fn main() {
}
fn do_swap(test: &mut TestDescAndFn) {
*test <-> *test;
unsafe {
util::swap_ptr(ptr::to_mut_unsafe_ptr(test),
ptr::to_mut_unsafe_ptr(test));
}
}
pub enum TestName {

View File

@ -8,10 +8,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::util;
pub fn main() {
let mut i = ~100;
let mut j = ~200;
i <-> j;
util::swap(&mut i, &mut j);
assert!(i == ~200);
assert!(j == ~100);
}

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::util;
// Just a grab bag of stuff that you wouldn't want to actually write.
fn strange() -> bool { let _x: bool = return true; }
@ -52,7 +54,7 @@ fn notsure() {
let mut _y = (_x = 0) == (_x = 0);
let mut _z = (_x = 0) < (_x = 0);
let _a = (_x += 0) == (_x = 0);
let _b = (_y <-> _z) == (_y <-> _z);
let _b = util::swap(&mut _y, &mut _z) == util::swap(&mut _y, &mut _z);
}
fn canttouchthis() -> uint {