提交 f9b54541 编写于 作者: P Patrick Walton 提交者: Corey Richardson

librustc: Disallow "mut" from distributing over bindings.

This is the backwards-incompatible part of per-binding-site "mut".
上级 1c0aa784
......@@ -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).
......@@ -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.
......@@ -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.
......@@ -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.
......
......@@ -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;
......@@ -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
......
......@@ -59,7 +59,8 @@ fn rot(r: int, x: u32) -> u32 {
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) +
......
......@@ -415,7 +415,9 @@ enum State {
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 //
......
......@@ -380,7 +380,10 @@ fn div_mod_floor_inner(a: BigUint, b: BigUint) -> (BigUint, 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
......@@ -442,7 +445,8 @@ fn div_estimate(a: &BigUint, b: &BigUint, n: uint)
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;
......
......@@ -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
......
......@@ -139,12 +139,14 @@ fn compute_info(&self,
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);
......
......@@ -178,12 +178,14 @@ fn compute_info(&self,
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 = ~[];
......
......@@ -360,8 +360,9 @@ fn x86_64_ty(ty: 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);
......
......@@ -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)
......
......@@ -907,9 +907,12 @@ fn trans_index(bcx: block,
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
......
......@@ -771,7 +771,9 @@ fn read_lines(&self) -> ~[~str] {
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;
......@@ -787,7 +789,8 @@ fn read_le_int_n(&self, nbytes: uint) -> i64 {
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;
......
......@@ -400,7 +400,8 @@ fn div_rem(&self, other: &$T) -> ($T,$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;
......
......@@ -237,7 +237,8 @@ fn div_mod_floor(&self, other: &$T) -> ($T,$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;
......
......@@ -720,7 +720,8 @@ fn init(&mut self, use_rsl: bool) {
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;
......
......@@ -89,7 +89,8 @@ fn zero_case<R:Rng>(rng: &mut R, u: f64) -> f64 {
// 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 {
......
......@@ -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;
......@@ -359,7 +361,8 @@ fn read_le_int_n(&mut self, nbytes: uint) -> i64 {
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;
......
......@@ -473,6 +473,31 @@ enum LengthLimit {
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
*/
......@@ -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;
......@@ -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);
......
......@@ -636,7 +636,9 @@ fn make_child_wrapper(child: *rust_task, child_arc: TaskGroupArc,
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
......
......@@ -53,8 +53,9 @@ fn to_str(&self) -> ~str {
impl<A:ToStr+Hash+Eq, B:ToStr+Hash+Eq> ToStr for HashMap<A, B> {
#[inline]
fn to_str(&self) -> ~str {
let mut (acc, first) = (~"{", true);
for self.iter().advance |(key, value)| {
let mut acc = ~"{";
let mut first = true;
for self.iter().advance |key, value| {
if first {
first = false;
}
......@@ -73,7 +74,8 @@ fn to_str(&self) -> ~str {
impl<A:ToStr+Hash+Eq> ToStr for HashSet<A> {
#[inline]
fn to_str(&self) -> ~str {
let mut (acc, first) = (~"{", true);
let mut acc = ~"{";
let mut first = true;
for self.iter().advance |element| {
if first {
first = false;
......@@ -121,7 +123,8 @@ fn to_str(&self) -> ~str {
impl<'self,A:ToStr> ToStr for &'self [A] {
#[inline]
fn to_str(&self) -> ~str {
let mut (acc, first) = (~"[", true);
let mut acc = ~"[";
let mut first = true;
for self.iter().advance |elt| {
if first {
first = false;
......@@ -139,7 +142,8 @@ fn to_str(&self) -> ~str {
impl<A:ToStr> ToStr for ~[A] {
#[inline]
fn to_str(&self) -> ~str {
let mut (acc, first) = (~"[", true);
let mut acc = ~"[";
let mut first = true;
for self.iter().advance |elt| {
if first {
first = false;
......@@ -157,7 +161,8 @@ fn to_str(&self) -> ~str {
impl<A:ToStr> ToStr for @[A] {
#[inline]
fn to_str(&self) -> ~str {
let mut (acc, first) = (~"[", true);
let mut acc = ~"[";
let mut first = true;
for self.iter().advance |elt| {
if first {
first = false;
......
......@@ -348,7 +348,8 @@ pub fn consume_reverse<T>(mut v: ~[T], f: &fn(uint, v: T)) {
pub fn dedup<T:Eq>(v: &mut ~[T]) {
unsafe {
if v.len() < 1 { return; }
let mut (last_written, next_to_read) = (0, 1);
let mut last_written = 0;
let mut next_to_read = 1;
do as_const_buf(*v) |p, ln| {
// We have a mutable reference to v, so we can make arbitrary
// changes. (cf. push and pop)
......@@ -798,7 +799,8 @@ pub fn bsearch_elem<T:TotalOrd>(v: &[T], x: &T) -> Option<uint> {
* Convert a vector of pairs into a pair of vectors, by reference. As unzip().
*/
pub fn unzip_slice<T:Copy,U:Copy>(v: &[(T, U)]) -> (~[T], ~[U]) {
let mut (ts, us) = (~[], ~[]);
let mut ts = ~[];
let mut us = ~[];
for v.iter().advance |p| {
let (t, u) = copy *p;
ts.push(t);
......@@ -816,7 +818,8 @@ pub fn unzip_slice<T:Copy,U:Copy>(v: &[(T, U)]) -> (~[T], ~[U]) {
* of the i-th tuple of the input vector.
*/
pub fn unzip<T,U>(v: ~[(T, U)]) -> (~[T], ~[U]) {
let mut (ts, us) = (~[], ~[]);
let mut ts = ~[];
let mut us = ~[];
do consume(v) |_i, p| {
let (t, u) = p;
ts.push(t);
......
......@@ -619,6 +619,15 @@ pub enum Privacy {
Public
}
/// Returns true if the given pattern consists solely of an identifier
/// and false otherwise.
pub fn pat_is_ident(pat: @ast::pat) -> bool {
match pat.node {
ast::pat_ident(*) => true,
_ => false,
}
}
// HYGIENE FUNCTIONS
/// Construct an identifier with the given name and an empty context:
......
......@@ -62,6 +62,7 @@ pub enum ObsoleteSyntax {
ObsoleteFixedLengthVectorType,
ObsoleteNamedExternModule,
ObsoleteMultipleLocalDecl,
ObsoleteMutWithMultipleBindings,
}
impl to_bytes::IterBytes for ObsoleteSyntax {
......@@ -223,6 +224,11 @@ pub fn obsolete(&self, sp: span, kind: ObsoleteSyntax) {
"instead of e.g. `let a = 1, b = 2`, write \
`let (a, b) = (1, 2)`."
),
ObsoleteMutWithMultipleBindings => (
"`mut` with multiple bindings",
"use multiple local declarations instead of e.g. `let mut \
(x, y) = ...`."
),
};
self.report(sp, kind, kind_str, desc);
......
......@@ -83,7 +83,8 @@
use parse::obsolete::{ObsoletePurity, ObsoleteStaticMethod};
use parse::obsolete::{ObsoleteConstItem, ObsoleteFixedLengthVectorType};
use parse::obsolete::{ObsoleteNamedExternModule, ObsoleteMultipleLocalDecl};
use parse::token::{can_begin_expr, get_ident_interner, ident_to_str, is_ident, is_ident_or_path};
use parse::obsolete::{ObsoleteMutWithMultipleBindings};
use parse::token::{can_begin_expr, get_ident_interner, is_ident, is_ident_or_path};
use parse::token::{is_plain_ident, INTERPOLATED, keywords, special_idents, token_to_binop};
use parse::token;
use parse::{new_sub_parser_from_file, next_node_id, ParseSess};
......@@ -821,6 +822,11 @@ pub fn parse_arg_general(&self, require_name: bool) -> arg {
self.parse_arg_mode();
is_mutbl = self.eat_keyword(keywords::Mut);
let pat = self.parse_pat();
if is_mutbl && !ast_util::pat_is_ident(pat) {
self.obsolete(*self.span, ObsoleteMutWithMultipleBindings)
}
self.expect(&token::COLON);
pat
} else {
......@@ -2560,6 +2566,11 @@ fn parse_pat_ident(&self,
fn parse_local(&self, is_mutbl: bool) -> @local {
let lo = self.span.lo;
let pat = self.parse_pat();
if is_mutbl && !ast_util::pat_is_ident(pat) {
self.obsolete(*self.span, ObsoleteMutWithMultipleBindings)
}
let mut ty = @Ty {
id: self.get_id(),
node: ty_infer,
......@@ -4420,7 +4431,8 @@ fn parse_items_and_view_items(&self,
let mut attrs = vec::append(first_item_attrs,
self.parse_outer_attributes());
// First, parse view items.
let mut (view_items, items) = (~[], ~[]);
let mut view_items = ~[];
let mut items = ~[];
let mut done = false;
// I think this code would probably read better as a single
// loop with a mutable three-state-variable (for extern mods,
......
......@@ -23,7 +23,10 @@ fn main() {
for range(0, h) |y| {
let y = y as f64;
for range(0, w) |x| {
let mut (Zr, Zi, Tr, Ti) = (0f64, 0f64, 0f64, 0f64);
let mut Zr = 0f64;
let mut Zi = 0f64;
let mut Tr = 0f64;
let mut Ti = 0f64;
let Cr = 2.0 * (x as f64) / (w as f64) - 1.5;
let Ci = 2.0 * (y as f64) / (h as f64) - 1.0;
......
......@@ -2,7 +2,7 @@ struct Foo {
f: @mut int,
}
impl Drop for Foo { //~ ERROR cannot implement a destructor on a struct that is not Send
impl Drop for Foo { //~ ERROR cannot implement a destructor on a structure that does not satisfy Send
fn drop(&self) {
*self.f = 10;
}
......
......@@ -12,7 +12,7 @@ fn foo(_x: @uint) {}
fn main() {
let x = @3u;
let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Owned`
let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Owned`
let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Owned`
let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Send`
let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Send`
let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Send`
}
......@@ -32,7 +32,7 @@ fn foo(x: Port<()>) -> foo {
let x = Cell::new(foo(Port(@())));
do task::spawn {
let y = x.take(); //~ ERROR does not fulfill `Owned`
let y = x.take(); //~ ERROR does not fulfill `Send`
error!(y);
}
}
......@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[non_owned]
#[non_sendable]
enum Foo { A }
fn bar<T: Send>(_: T) {}
......
......@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[non_owned]
#[non_sendable]
struct Foo { a: int }
fn bar<T: Send>(_: T) {}
......
......@@ -13,7 +13,9 @@ struct A { a: int }
pub fn main() {
let u = X {x: 10, y: @A {a: 20}};
let mut X {x: x, y: @A {a: a}} = u;
let X {x: x, y: @A {a: a}} = u;
let mut x = x;
let mut a = a;
x = 100;
a = 100;
assert_eq!(x, 100);
......
......@@ -22,7 +22,9 @@
)
pub fn main() {
let mut (p, c) = oneshot::init();
let (p, c) = oneshot::init();
let mut p = p;
let mut c = c;
assert!(!pipes::peek(&mut p));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册