Skip to content

Remove the '<->' operator #6260

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 1 addition & 30 deletions doc/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -2015,7 +1986,7 @@ as
== !=
&&
||
= <->
=
~~~~

Operators at the same precedence level are evaluated left-to-right.
Expand Down
4 changes: 3 additions & 1 deletion doc/tutorial-ffi.md
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -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)
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/libcore/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

use cast::transmute_mut;
use prelude::*;
use util::replace;

/*
A dynamic, mutable location.
Expand Down Expand Up @@ -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.
Expand Down
29 changes: 11 additions & 18 deletions src/libcore/comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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))
}
}
Expand All @@ -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);
Expand All @@ -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
Expand All @@ -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);
Expand All @@ -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
}
}
Expand Down Expand Up @@ -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() {
Expand All @@ -281,7 +276,7 @@ impl<T:Owned> GenericPort<T> for PortSet<T> {
}
}
}
ports <-> *self_ports;
*self_ports = ports;
result
}
}
Expand Down Expand Up @@ -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())
}
}
Expand All @@ -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())
}
}
Expand Down
24 changes: 8 additions & 16 deletions src/libcore/hashmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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)
},
};
Expand All @@ -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);
}
Expand Down Expand Up @@ -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)
}
}
Expand Down
29 changes: 9 additions & 20 deletions src/libcore/pipes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ use unstable::intrinsics;
use ptr;
use task;
use vec;
use util::replace;

static SPIN_COUNT: uint = 0;

Expand Down Expand Up @@ -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())
},
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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())
}
}
Expand All @@ -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 {
Expand All @@ -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()
}
}

Expand All @@ -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())
}
}
Expand All @@ -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()
}
}

Expand Down
Loading