Remove by-mutable-ref mode from the compiler

and test cases. Closes #3513
This commit is contained in:
Tim Chevalier 2012-10-05 22:07:53 -07:00
parent 05999290e2
commit f96a2a2ca1
26 changed files with 59 additions and 95 deletions

View file

@ -2784,14 +2784,12 @@ aside a copy of that value to refer to. If this is not semantically safe (for
example, if the referred-to value contains mutable fields), it will reject the
program. If the compiler deems copying the value expensive, it will warn.
A function can be declared to take an argument by mutable reference. This
allows the function to write to the slot that the reference refers to.
An example function that accepts an value by mutable reference:
A function with an argument of type `&mut T`, for some type `T`, can write to
the slot that its argument refers to. An example of such a function is:
~~~~~~~~
fn incr(&i: int) {
i = i + 1;
fn incr(i: &mut int) {
*i = *i + 1;
}
~~~~~~~~

View file

@ -574,7 +574,7 @@ impl<T:cmp::Eq> inferable<T> : cmp::Eq {
// "resolved" mode: the real modes.
#[auto_serialize]
enum rmode { by_ref, by_val, by_mutbl_ref, by_move, by_copy }
enum rmode { by_ref, by_val, by_move, by_copy }
impl rmode : to_bytes::IterBytes {
pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {

View file

@ -22,7 +22,8 @@ pub enum ObsoleteSyntax {
ObsoleteClassMethod,
ObsoleteClassTraits,
ObsoletePrivSection,
ObsoleteModeInFnType
ObsoleteModeInFnType,
ObsoleteByMutRefMode
}
impl ObsoleteSyntax : cmp::Eq {
@ -94,6 +95,10 @@ impl parser : ObsoleteReporter {
"to use a (deprecated) mode in a fn type, you should \
give the argument an explicit name (like `&&v: int`)"
),
ObsoleteByMutRefMode => (
"by-mutable-reference mode",
"Declare an argument of type &mut T instead"
),
};
self.report(sp, kind, kind_str, desc);

View file

@ -20,13 +20,13 @@ use obsolete::{
ObsoleteLowerCaseKindBounds, ObsoleteLet,
ObsoleteFieldTerminator, ObsoleteStructCtor,
ObsoleteWith, ObsoleteClassMethod, ObsoleteClassTraits,
ObsoleteModeInFnType
ObsoleteModeInFnType, ObsoleteByMutRefMode
};
use ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
bind_by_ref, bind_by_implicit_ref, bind_by_value, bind_by_move,
bitand, bitor, bitxor, blk, blk_check_mode, bound_const,
bound_copy, bound_send, bound_trait, bound_owned, box, by_copy,
by_move, by_mutbl_ref, by_ref, by_val, capture_clause,
by_move, by_ref, by_val, capture_clause,
capture_item, cdir_dir_mod, cdir_src_mod, cdir_view_item,
class_immutable, class_mutable,
crate, crate_cfg, crate_directive, decl, decl_item, decl_local,
@ -570,9 +570,10 @@ impl parser {
fn parse_arg_mode() -> mode {
if self.eat(token::BINOP(token::AND)) {
self.span_fatal(copy self.last_span,
~"Obsolete syntax has no effect");
expl(by_mutbl_ref)
self.obsolete(copy self.span,
ObsoleteByMutRefMode);
// Bogus mode, but doesn't matter since it's an error
expl(by_ref)
} else if self.eat(token::BINOP(token::MINUS)) {
expl(by_move)
} else if self.eat(token::ANDAND) {

View file

@ -1688,7 +1688,6 @@ fn print_fn_block_args(s: ps, decl: ast::fn_decl,
fn mode_to_str(m: ast::mode) -> ~str {
match m {
ast::expl(ast::by_mutbl_ref) => ~"&",
ast::expl(ast::by_move) => ~"-",
ast::expl(ast::by_ref) => ~"&&",
ast::expl(ast::by_val) => ~"++",

View file

@ -394,7 +394,6 @@ fn parse_arg(st: @pstate, conv: conv_did) -> ty::arg {
fn parse_mode(st: @pstate) -> ast::mode {
let m = ast::expl(match next(st) {
'&' => ast::by_mutbl_ref,
'-' => ast::by_move,
'+' => ast::by_copy,
'=' => ast::by_ref,

View file

@ -333,7 +333,6 @@ fn enc_arg(w: io::Writer, cx: @ctxt, arg: ty::arg) {
fn enc_mode(w: io::Writer, cx: @ctxt, m: mode) {
match ty::resolved_mode(cx.tcx, m) {
by_mutbl_ref => w.write_char('&'),
by_move => w.write_char('-'),
by_copy => w.write_char('+'),
by_ref => w.write_char('='),

View file

@ -529,7 +529,7 @@ impl check_loan_ctxt {
ast::by_move => {
self.check_move_out(*arg);
}
ast::by_mutbl_ref | ast::by_ref |
ast::by_ref |
ast::by_copy | ast::by_val => {
}
}

View file

@ -115,10 +115,6 @@ fn req_loans_in_expr(ex: @ast::expr,
let scope_r = ty::re_scope(ex.id);
for vec::each2(args, arg_tys) |arg, arg_ty| {
match ty::resolved_mode(self.tcx(), arg_ty.mode) {
ast::by_mutbl_ref => {
let arg_cmt = self.bccx.cat_expr(*arg);
self.guarantee_valid(arg_cmt, m_mutbl, scope_r);
}
ast::by_ref => {
let arg_cmt = self.bccx.cat_expr(*arg);
self.guarantee_valid(arg_cmt, m_imm, scope_r);

View file

@ -323,7 +323,7 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
for ty::ty_fn_args(ty::expr_ty(cx.tcx, f)).each |arg_t| {
match ty::arg_mode(cx.tcx, *arg_t) {
by_copy => maybe_copy(cx, args[i], None),
by_ref | by_val | by_mutbl_ref | by_move => ()
by_ref | by_val | by_move => ()
}
i += 1u;
}
@ -335,7 +335,7 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
Some(ref mme) => {
match ty::arg_mode(cx.tcx, mme.self_arg) {
by_copy => maybe_copy(cx, lhs, None),
by_ref | by_val | by_mutbl_ref | by_move => ()
by_ref | by_val | by_move => ()
}
}
_ => ()
@ -465,14 +465,7 @@ fn check_imm_free_var(cx: ctx, def: def, sp: span) {
cx.tcx.sess.span_err(sp, msg);
}
}
def_arg(_, mode) => {
match ty::resolved_mode(cx.tcx, mode) {
by_ref | by_val | by_move | by_copy => { /* ok */ }
by_mutbl_ref => {
cx.tcx.sess.span_err(sp, msg);
}
}
}
def_arg(*) => { /* ok */ }
def_upvar(_, def1, _, _) => {
check_imm_free_var(cx, *def1, sp);
}

View file

@ -398,7 +398,7 @@ impl IrMaps {
(*v).push(id);
}
Arg(_, _, by_ref) | Arg(_, _, by_mutbl_ref) |
Arg(_, _, by_ref) |
Arg(_, _, by_val) | Self | Field(_) | ImplicitRet |
Local(LocalInfo {kind: FromMatch(bind_by_implicit_ref), _}) => {
debug!("--but it is not owned");
@ -919,7 +919,7 @@ impl Liveness {
// inputs passed by & mode should be considered live on exit:
for decl.inputs.each |arg| {
match ty::resolved_mode(self.tcx, arg.mode) {
by_mutbl_ref | by_ref | by_val => {
by_ref | by_val => {
// These are "non-owned" modes, so register a read at
// the end. This will prevent us from moving out of
// such variables but also prevent us from registering
@ -1573,7 +1573,7 @@ fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) {
let targs = ty::ty_fn_args(ty::expr_ty(self.tcx, f));
for vec::each2(args, targs) |arg_expr, arg_ty| {
match ty::resolved_mode(self.tcx, arg_ty.mode) {
by_val | by_copy | by_ref | by_mutbl_ref => {}
by_val | by_copy | by_ref => {}
by_move => {
self.check_move_from_expr(*arg_expr, vt);
}
@ -1865,24 +1865,7 @@ impl @Liveness {
fn warn_about_unused_args(sp: span, decl: fn_decl, entry_ln: LiveNode) {
for decl.inputs.each |arg| {
let var = self.variable(arg.id, arg.ty.span);
match ty::resolved_mode(self.tcx, arg.mode) {
by_mutbl_ref => {
// for mutable reference arguments, something like
// x = 1;
// is not worth warning about, as it has visible
// side effects outside the fn.
match self.assigned_on_entry(entry_ln, var) {
Some(_) => { /*ok*/ }
None => {
// but if it is not written, it ought to be used
self.warn_about_unused(sp, entry_ln, var);
}
}
}
by_val | by_ref | by_move | by_copy => {
self.warn_about_unused(sp, entry_ln, var);
}
}
self.warn_about_unused(sp, entry_ln, var);
}
}

View file

@ -523,9 +523,6 @@ impl &mem_categorization_ctxt {
// m: mutability of the argument
// lp: loan path, must be none for aliasable things
let {m,lp} = match ty::resolved_mode(self.tcx, mode) {
ast::by_mutbl_ref => {
{m: m_mutbl, lp: None}
}
ast::by_move | ast::by_copy => {
{m: m_imm, lp: Some(@lp_arg(vid))}
}

View file

@ -1503,7 +1503,7 @@ fn copy_args_to_allocas(fcx: fn_ctxt,
// the event it's not truly needed.
let llarg;
match ty::resolved_mode(tcx, arg_ty.mode) {
ast::by_ref | ast::by_mutbl_ref => {
ast::by_ref => {
llarg = raw_llarg;
}
ast::by_move | ast::by_copy => {

View file

@ -592,7 +592,7 @@ fn trans_arg_expr(bcx: block,
DoAutorefArg => { val = arg_datum.to_ref_llval(bcx); }
DontAutorefArg => {
match arg_mode {
ast::by_ref | ast::by_mutbl_ref => {
ast::by_ref => {
val = arg_datum.to_ref_llval(bcx);
}

View file

@ -154,7 +154,7 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id,
typeck::method_trait(_, off, vstore) => {
trans_trait_callee(bcx, callee_id, off, self, vstore)
}
typeck::method_self(_, off) => {
typeck::method_self(*) => {
bcx.tcx().sess.span_bug(self.span, ~"self method call");
}
}

View file

@ -210,7 +210,6 @@ impl reflector {
ast::expl(e) => match e {
ast::by_ref => 1u,
ast::by_val => 2u,
ast::by_mutbl_ref => 3u,
ast::by_move => 4u,
ast::by_copy => 5u
}

View file

@ -53,7 +53,7 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
by_val | by_move | by_copy => {
type_needs(cx, use_repr, arg.ty);
}
by_ref | by_mutbl_ref => {}
by_ref => {}
}
}
}

View file

@ -144,7 +144,7 @@ mod map_reduce {
fn start_mappers<K1: Copy Send, K2: Hash IterBytes Eq Const Copy Send,
V: Copy Send>(
map: &mapper<K1, K2, V>,
&ctrls: ~[ctrl_proto::server::open<K2, V>],
ctrls: &mut ~[ctrl_proto::server::open<K2, V>],
inputs: &~[K1])
-> ~[joinable_task]
{
@ -213,9 +213,9 @@ mod map_reduce {
let mut is_done = false;
fn get<V: Copy Send>(p: Port<reduce_proto<V>>,
&ref_count: int, &is_done: bool)
ref_count: &mut int, is_done: &mut bool)
-> Option<V> {
while !is_done || ref_count > 0 {
while !*is_done || *ref_count > 0 {
match recv(p) {
emit_val(v) => {
// error!("received %d", v);
@ -223,16 +223,16 @@ mod map_reduce {
}
done => {
// error!("all done");
is_done = true;
*is_done = true;
}
addref => { ref_count += 1; }
release => { ref_count -= 1; }
addref => { *ref_count += 1; }
release => { *ref_count -= 1; }
}
}
return None;
}
(*reduce)(&key, || get(p, ref_count, is_done) );
(*reduce)(&key, || get(p, &mut ref_count, &mut is_done) );
}
fn map_reduce<K1: Copy Send, K2: Hash IterBytes Eq Const Copy Send, V: Copy Send>(
@ -246,7 +246,7 @@ mod map_reduce {
// to do the rest.
let reducers = map::HashMap();
let mut tasks = start_mappers(&map, ctrl, &inputs);
let mut tasks = start_mappers(&map, &mut ctrl, &inputs);
let mut num_mappers = vec::len(inputs) as int;
while num_mappers > 0 {

View file

@ -1,11 +1,9 @@
#[forbid(deprecated_mode)];
fn foo(_f: fn(&i: int)) { //~ ERROR explicit mode
//~^ WARNING Obsolete syntax has no effect
fn foo(_f: fn(&i: int)) { //~ ERROR by-mutable-reference mode
}
type Bar = fn(&i: int); //~ ERROR explicit mode
//~^ WARNING Obsolete syntax has no effect
type Bar = fn(&i: int); //~ ERROR by-mutable-reference mode
fn main() {
}

View file

@ -1,11 +1,8 @@
//error-pattern: mismatched types
//error-pattern: by-mutable-reference mode
fn bad(&a: int) {
}
// unnamed argument &int is now parsed x: &int
// it's not parsed &x: int anymore
fn called(f: fn(&int)) {
}

View file

@ -1,10 +1,10 @@
// xfail-fast
#[legacy_modes];
fn f1(a: {mut x: int}, &b: int, -c: int) -> int {
let r = a.x + b + c;
fn f1(a: {mut x: int}, b: &mut int, -c: int) -> int {
let r = a.x + *b + c;
a.x = 0;
b = 10;
*b = 10;
return r;
}
@ -12,7 +12,7 @@ fn f2(a: int, f: fn(int)) -> int { f(1); return a; }
fn main() {
let mut a = {mut x: 1}, b = 2, c = 3;
assert (f1(a, b, c) == 6);
assert (f1(a, &mut b, c) == 6);
assert (a.x == 0);
assert (b == 10);
assert (f2(a.x, |x| a.x = 50 ) == 0);

View file

@ -1,15 +1,15 @@
fn f(i: int, &called: bool) {
fn f(i: int, called: &mut bool) {
assert i == 10;
called = true;
*called = true;
}
fn g(f: extern fn(int, &v: bool), &called: bool) {
fn g(f: extern fn(int, v: &mut bool), called: &mut bool) {
f(10, called);
}
fn main() {
let mut called = false;
let h = f;
g(h, called);
g(h, &mut called);
assert called == true;
}

View file

@ -1,12 +1,12 @@
fn incr(&x: int) -> bool { x += 1; assert (false); return false; }
fn incr(x: &mut int) -> bool { *x += 1; assert (false); return false; }
fn main() {
let x = 1 == 2 || 3 == 3;
assert (x);
let mut y: int = 10;
log(debug, x || incr(y));
log(debug, x || incr(&mut y));
assert (y == 10);
if true && x { assert (true); } else { assert (false); }
}

View file

@ -3,13 +3,13 @@
// -*- rust -*-
extern mod std;
fn grow(&v: ~[int]) { v += ~[1]; }
fn grow(v: &mut ~[int]) { *v += ~[1]; }
fn main() {
let mut v: ~[int] = ~[];
grow(v);
grow(v);
grow(v);
grow(&mut v);
grow(&mut v);
grow(&mut v);
let len = vec::len::<int>(v);
log(debug, len);
assert (len == 3 as uint);

View file

@ -1,9 +1,9 @@
fn f(&i: ~int) {
i = ~200;
fn f(i: &mut ~int) {
*i = ~200;
}
fn main() {
let mut i = ~100;
f(i);
f(&mut i);
assert *i == 200;
}

View file

@ -4,10 +4,10 @@
// -*- rust -*-
type point = {x: int, y: int, mut z: int};
fn f(&p: point) { p.z = 13; }
fn f(p: &mut point) { p.z = 13; }
fn main() {
let mut x: point = {x: 10, y: 11, mut z: 12};
f(x);
f(&mut x);
assert (x.z == 13);
}