librustc: Disallow "mut" from distributing over bindings.

This is the backwards-incompatible part of per-binding-site "mut".
This commit is contained in:
Patrick Walton 2013-06-06 18:54:14 -07:00 committed by Corey Richardson
parent 1c0aa78481
commit f9b54541ee
32 changed files with 190 additions and 50 deletions

View file

@ -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) +

View file

@ -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 //

View file

@ -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
@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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 = ~[];

View file

@ -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);

View file

@ -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)

View file

@ -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

View file

@ -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;
@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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 {

View file

@ -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 @@ 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;

View file

@ -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
*/
@ -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);

View file

@ -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

View file

@ -53,8 +53,9 @@ impl<A:ToStr> ToStr for (A,) {
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 @@ impl<A:ToStr+Hash+Eq, B:ToStr+Hash+Eq> ToStr for HashMap<A, B> {
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 @@ impl<A:ToStr,B:ToStr,C:ToStr> ToStr for (A, B, C) {
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 @@ impl<'self,A:ToStr> ToStr for &'self [A] {
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 @@ impl<A:ToStr> ToStr for ~[A] {
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;

View file

@ -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);

View file

@ -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:

View file

@ -62,6 +62,7 @@ pub enum ObsoleteSyntax {
ObsoleteFixedLengthVectorType,
ObsoleteNamedExternModule,
ObsoleteMultipleLocalDecl,
ObsoleteMutWithMultipleBindings,
}
impl to_bytes::IterBytes for ObsoleteSyntax {
@ -223,6 +224,11 @@ impl Parser {
"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);

View file

@ -83,7 +83,8 @@ use parse::obsolete::{ObsoleteLifetimeNotation, ObsoleteConstManagedPointer};
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 @@ impl Parser {
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 @@ impl Parser {
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 @@ impl Parser {
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,

View file

@ -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;

View file

@ -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;
}

View file

@ -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`
}

View file

@ -32,7 +32,7 @@ fn main() {
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);
}
}

View file

@ -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) {}

View file

@ -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) {}

View file

@ -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);

View file

@ -22,7 +22,9 @@ proto! oneshot (
)
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));