Skip to content

Commit

Permalink
librustc: Disallow "mut" from distributing over bindings.
Browse files Browse the repository at this point in the history
This is the backwards-incompatible part of per-binding-site "mut".
  • Loading branch information
pcwalton authored and emberian committed Jun 28, 2013
1 parent 1c0aa78 commit f9b5454
Show file tree
Hide file tree
Showing 32 changed files with 190 additions and 50 deletions.
14 changes: 7 additions & 7 deletions doc/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -2862,13 +2862,13 @@ call to the method `make_string`.
Types in Rust are categorized into kinds, based on various properties of the components of the type.
The kinds are:

`Const`
`Freeze`
: Types of this kind are deeply immutable;
they contain no mutable memory locations directly or indirectly via pointers.
`Owned`
`Send`
: Types of this kind can be safely sent between tasks.
This kind includes scalars, owning pointers, owned closures, and
structural types containing only other owned types. All `Owned` types are `Static`.
structural types containing only other owned types. All `Send` types are `Static`.
`Static`
: Types of this kind do not contain any borrowed pointers;
this can be a useful guarantee for code that breaks borrowing assumptions using [`unsafe` operations](#unsafe-functions).
Expand All @@ -2882,7 +2882,7 @@ The kinds are:
trait provides a single method `finalize` that takes no parameters, and is run
when values of the type are dropped. Such a method is called a "destructor",
and are always executed in "top-down" order: a value is completely destroyed
before any of the values it owns run their destructors. Only `Owned` types
before any of the values it owns run their destructors. Only `Send` types
that do not implement `Copy` can implement `Drop`.

> **Note:** The `finalize` method may be renamed in future versions of Rust.
Expand Down Expand Up @@ -2968,10 +2968,10 @@ frame they are allocated within.
A task owns all memory it can *safely* reach through local variables,
as well as managed, owning and borrowed pointers.

When a task sends a value that has the `Owned` trait to another task,
When a task sends a value that has the `Send` trait to another task,
it loses ownership of the value sent and can no longer refer to it.
This is statically guaranteed by the combined use of "move semantics",
and the compiler-checked _meaning_ of the `Owned` trait:
and the compiler-checked _meaning_ of the `Send` trait:
it is only instantiated for (transitively) sendable kinds of data constructor and pointers,
never including managed or borrowed pointers.

Expand Down Expand Up @@ -3116,7 +3116,7 @@ These include:
- read-only and read-write shared variables with various safe mutual exclusion patterns
- simple locks and semaphores

When such facilities carry values, the values are restricted to the [`Owned` type-kind](#type-kinds).
When such facilities carry values, the values are restricted to the [`Send` type-kind](#type-kinds).
Restricting communication interfaces to this kind ensures that no borrowed or managed pointers move between tasks.
Thus access to an entire data structure can be mediated through its owning "root" value;
no further locking or copying is required to avoid data races within the substructure of such a value.
Expand Down
4 changes: 2 additions & 2 deletions doc/tutorial-ffi.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ pub struct Unique<T> {
priv ptr: *mut T
}
impl<T: Owned> Unique<T> {
impl<T: Send> Unique<T> {
pub fn new(value: T) -> Unique<T> {
unsafe {
let ptr = malloc(std::sys::size_of::<T>() as size_t) as *mut T;
Expand All @@ -182,7 +182,7 @@ impl<T: Owned> Unique<T> {
}
#[unsafe_destructor]
impl<T: Owned> Drop for Unique<T> {
impl<T: Send> Drop for Unique<T> {
fn drop(&self) {
unsafe {
let x = intrinsics::init(); // dummy value to swap in
Expand Down
3 changes: 2 additions & 1 deletion src/libextra/md4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ pub fn md4(msg: &[u8]) -> Quad {
while i < e {
let (aa, bb, cc, dd) = (a, b, c, d);

let mut (j, base) = (0u, i);
let mut j = 0u;
let mut base = i;
while j < 16u {
x[j] = (msg[base] as u32) + (msg[base + 1u] as u32 << 8u32) +
(msg[base + 2u] as u32 << 16u32) +
Expand Down
4 changes: 3 additions & 1 deletion src/libextra/net_url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,9 @@ fn get_authority(rawurl: &str) ->
let mut port = None;

let mut colon_count = 0;
let mut (pos, begin, end) = (0, 2, len);
let mut pos = 0;
let mut begin = 2;
let mut end = len;

for rawurl.iter().enumerate().advance |(i,c)| {
if i < 2 { loop; } // ignore the leading //
Expand Down
8 changes: 6 additions & 2 deletions src/libextra/num/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,10 @@ impl Integer for BigUint {
let mut d = Zero::zero::<BigUint>();
let mut n = 1;
while m >= b {
let mut (d0, d_unit, b_unit) = div_estimate(&m, &b, n);
let (d0, d_unit, b_unit) = div_estimate(&m, &b, n);
let mut d0 = d0;
let mut d_unit = d_unit;
let mut b_unit = b_unit;
let mut prod = b * d0;
while prod > m {
// FIXME(#6050): overloaded operators force moves with generic types
Expand Down Expand Up @@ -442,7 +445,8 @@ impl Integer for BigUint {

fn gcd(&self, other: &BigUint) -> BigUint {
// Use Euclid's algorithm
let mut (m, n) = (copy *self, copy *other);
let mut m = copy *self;
let mut n = copy *other;
while !m.is_zero() {
let temp = m;
m = n % temp;
Expand Down
4 changes: 3 additions & 1 deletion src/libextra/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ pub fn recv_timeout<T:Copy + Send>(iotask: &IoTask,
msecs: uint,
wait_po: &Port<T>)
-> Option<T> {
let mut (timeout_po, timeout_ch) = stream::<()>();
let (timeout_po, timeout_ch) = stream::<()>();
let mut timeout_po = timeout_po;
let mut timeout_ch = timeout_ch;
delayed_send(iotask, msecs, &timeout_ch, ());

// XXX: Workaround due to ports and channels not being &mut. They should
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/middle/trans/cabi_arm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,14 @@ impl ABIInfo for ARM_ABIInfo {
attrs.push(attr);
}

let mut (ret_ty, ret_attr) = if ret_def {
let (ret_ty, ret_attr) = if ret_def {
classify_ret_ty(rty)
} else {
(LLVMType { cast: false, ty: Type::void() }, None)
};

let mut ret_ty = ret_ty;

let sret = ret_attr.is_some();
if sret {
arg_tys.unshift(ret_ty);
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/middle/trans/cabi_mips.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,12 +178,14 @@ impl ABIInfo for MIPS_ABIInfo {
atys: &[Type],
rty: Type,
ret_def: bool) -> FnType {
let mut (ret_ty, ret_attr) = if ret_def {
let (ret_ty, ret_attr) = if ret_def {
classify_ret_ty(rty)
} else {
(LLVMType { cast: false, ty: Type::void() }, None)
};

let mut ret_ty = ret_ty;

let sret = ret_attr.is_some();
let mut arg_tys = ~[];
let mut attrs = ~[];
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/middle/trans/cabi_x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,9 @@ fn x86_64_tys(atys: &[Type],
arg_tys.push(ty);
attrs.push(attr);
}
let mut (ret_ty, ret_attr) = x86_64_ty(rty, |cls| cls.is_ret_bysret(),
let (ret_ty, ret_attr) = x86_64_ty(rty, |cls| cls.is_ret_bysret(),
StructRetAttribute);
let mut ret_ty = ret_ty;
let sret = ret_attr.is_some();
if sret {
arg_tys = vec::append(~[ret_ty], arg_tys);
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/middle/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,9 +319,10 @@ pub fn trans_fn_ref_with_vtables(
// Should be either intra-crate or inlined.
assert_eq!(def_id.crate, ast::local_crate);

let mut (val, must_cast) =
let (val, must_cast) =
monomorphize::monomorphic_fn(ccx, def_id, &substs,
vtables, opt_impl_did, Some(ref_id));
let mut val = val;
if must_cast && ref_id != 0 {
// Monotype of the REFERENCE to the function (type params
// are subst'd)
Expand Down
5 changes: 4 additions & 1 deletion src/librustc/middle/trans/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -907,9 +907,12 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
let scaled_ix = Mul(bcx, ix_val, vt.llunit_size);
base::maybe_name_value(bcx.ccx(), scaled_ix, "scaled_ix");

let mut (bcx, base, len) =
let (bcx, base, len) =
base_datum.get_vec_base_and_len(bcx, index_expr.span,
index_expr.id, 0);
let mut bcx = bcx;
let mut base = base;
let mut len = len;

if ty::type_is_str(base_ty) {
// acccount for null terminator in the case of string
Expand Down
7 changes: 5 additions & 2 deletions src/libstd/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,9 @@ impl<T:Reader> ReaderUtil for T {
fn read_le_uint_n(&self, nbytes: uint) -> u64 {
assert!(nbytes > 0 && nbytes <= 8);

let mut (val, pos, i) = (0u64, 0, nbytes);
let mut val = 0u64;
let mut pos = 0;
let mut i = nbytes;
while i > 0 {
val += (self.read_u8() as u64) << pos;
pos += 8;
Expand All @@ -787,7 +789,8 @@ impl<T:Reader> ReaderUtil for T {
fn read_be_uint_n(&self, nbytes: uint) -> u64 {
assert!(nbytes > 0 && nbytes <= 8);

let mut (val, i) = (0u64, nbytes);
let mut val = 0u64;
let mut i = nbytes;
while i > 0 {
i -= 1;
val += (self.read_u8() as u64) << i * 8;
Expand Down
3 changes: 2 additions & 1 deletion src/libstd/num/int_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,8 @@ impl Integer for $T {
#[inline]
fn gcd(&self, other: &$T) -> $T {
// Use Euclid's algorithm
let mut (m, n) = (*self, *other);
let mut m = *self;
let mut n = *other;
while m != 0 {
let temp = m;
m = n % temp;
Expand Down
3 changes: 2 additions & 1 deletion src/libstd/num/uint_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,8 @@ impl Integer for $T {
#[inline]
fn gcd(&self, other: &$T) -> $T {
// Use Euclid's algorithm
let mut (m, n) = (*self, *other);
let mut m = *self;
let mut n = *other;
while m != 0 {
let temp = m;
m = n % temp;
Expand Down
3 changes: 2 additions & 1 deletion src/libstd/rand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,8 @@ impl IsaacRng {
fn isaac(&mut self) {
self.c += 1;
// abbreviations
let mut (a, b) = (self.a, self.b + self.c);
let mut a = self.a;
let mut b = self.b + self.c;

static midpoint: uint = RAND_SIZE as uint / 2;

Expand Down
3 changes: 2 additions & 1 deletion src/libstd/rand/distributions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ impl Rand for StandardNormal {
// do-while, so the condition should be true on the first
// run, they get overwritten anyway (0 < 1, so these are
// good).
let mut (x, y) = (1.0, 0.0);
let mut x = 1.0;
let mut y = 0.0;

// XXX infinities?
while -2.0*y < x * x {
Expand Down
7 changes: 5 additions & 2 deletions src/libstd/rt/io/extensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,9 @@ impl<T: Reader> ReaderByteConversions for T {
fn read_le_uint_n(&mut self, nbytes: uint) -> u64 {
assert!(nbytes > 0 && nbytes <= 8);

let mut (val, pos, i) = (0u64, 0, nbytes);
let mut val = 0u64;
let mut pos = 0;
let mut i = nbytes;
while i > 0 {
val += (self.read_u8() as u64) << pos;
pos += 8;
Expand All @@ -359,7 +361,8 @@ impl<T: Reader> ReaderByteConversions for T {
fn read_be_uint_n(&mut self, nbytes: uint) -> u64 {
assert!(nbytes > 0 && nbytes <= 8);

let mut (val, i) = (0u64, nbytes);
let mut val = 0u64;
let mut i = nbytes;
while i > 0 {
i -= 1;
val += (self.read_u8() as u64) << i * 8;
Expand Down
70 changes: 69 additions & 1 deletion src/libstd/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,31 @@ pub fn each_split_within<'a>(ss: &'a str,
return cont;
}

/**
* Replace all occurrences of one string with another
*
* # Arguments
*
* * s - The string containing substrings to replace
* * from - The string to replace
* * to - The replacement string
*
* # Return value
*
* The original string with all occurances of `from` replaced with `to`
*/
pub fn replace(s: &str, from: &str, to: &str) -> ~str {
let mut result = ~"";
let mut last_end = 0;
for s.matches_index_iter(from).advance |(start, end)| {
result.push_str(unsafe{raw::slice_bytes(s, last_end, start)});
result.push_str(to);
last_end = end;
}
result.push_str(unsafe{raw::slice_bytes(s, last_end, s.len())});
result
}

/*
Section: Comparing strings
*/
Expand Down Expand Up @@ -631,6 +656,48 @@ pub fn with_capacity(capacity: uint) -> ~str {
buf
}

/**
* As char_len but for a slice of a string
*
* # Arguments
*
* * s - A valid string
* * start - The position inside `s` where to start counting in bytes
* * end - The position where to stop counting
*
* # Return value
*
* The number of Unicode characters in `s` between the given indices.
*/
pub fn count_chars(s: &str, start: uint, end: uint) -> uint {
assert!(s.is_char_boundary(start));
assert!(s.is_char_boundary(end));
let mut i = start;
let mut len = 0u;
while i < end {
let next = s.char_range_at(i).next;
len += 1u;
i = next;
}
return len;
}

/// Counts the number of bytes taken by the first `n` chars in `s`
/// starting from `start`.
pub fn count_bytes<'b>(s: &'b str, start: uint, n: uint) -> uint {
assert!(is_char_boundary(s, start));
let mut end = start;
let mut cnt = n;
let l = s.len();
while cnt > 0u {
assert!(end < l);
let next = s.char_range_at(end).next;
cnt -= 1u;
end = next;
}
end - start
}

/// Given a first byte, determine how many bytes are in this UTF-8 character
pub fn utf8_char_width(b: u8) -> uint {
let byte: uint = b as uint;
Expand Down Expand Up @@ -737,7 +804,8 @@ pub mod raw {

/// Create a Rust string from a null-terminated *u8 buffer
pub unsafe fn from_buf(buf: *u8) -> ~str {
let mut (curr, i) = (buf, 0u);
let mut curr = buf;
let mut i = 0u;
while *curr != 0u8 {
i += 1u;
curr = ptr::offset(buf, i);
Expand Down
4 changes: 3 additions & 1 deletion src/libstd/task/spawn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,9 @@ fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) {
let child_data = Cell::new((notify_chan, child_arc, ancestors));
let result: ~fn() = || {
// Agh. Get move-mode items into the closure. FIXME (#2829)
let mut (notify_chan, child_arc, ancestors) = child_data.take();
let (notify_chan, child_arc, ancestors) = child_data.take();
let mut child_arc = child_arc;
let mut ancestors = ancestors;
// Child task runs this code.

// Even if the below code fails to kick the child off, we must
Expand Down
Loading

0 comments on commit f9b5454

Please sign in to comment.