auto merge of #9989 : luqmana/rust/mut-everywhere, r=alexcrichton

This commit is contained in:
bors 2013-10-22 19:46:09 -07:00
commit 78573149cb
24 changed files with 188 additions and 56 deletions

View File

@ -3395,16 +3395,23 @@ a [temporary](#lvalues-rvalues-and-temporaries), or a local variable.
A _local variable_ (or *stack-local* allocation) holds a value directly,
allocated within the stack's memory. The value is a part of the stack frame.
Local variables are immutable unless declared with `let mut`. The
`mut` keyword applies to all local variables declared within that
declaration (so `let mut (x, y) = ...` declares two mutable variables, `x` and
`y`).
Local variables are immutable unless declared otherwise like: `let mut x = ...`.
Function parameters are immutable unless declared with `mut`. The
`mut` keyword applies only to the following parameter (so `|mut x, y|`
and `fn f(mut x: ~int, y: ~int)` declare one mutable variable `x` and
one immutable variable `y`).
Methods that take either `self` or `~self` can optionally place them in a
mutable slot by prefixing them with `mut` (similar to regular arguments):
~~~
trait Changer {
fn change(mut self) -> Self;
fn modify(mut ~self) -> ~Self;
}
~~~
Local variables are not initialized when allocated; the entire frame worth of
local variables are allocated at once, on frame-entry, in an uninitialized
state. Subsequent statements within a function may or may not initialize the

View File

@ -975,9 +975,9 @@ fn get_explicit_self(item: ebml::Doc) -> ast::explicit_self_ {
let explicit_self_kind = string[0];
match explicit_self_kind as char {
's' => { return ast::sty_static; }
'v' => { return ast::sty_value; }
'v' => { return ast::sty_value(get_mutability(string[1])); }
'@' => { return ast::sty_box(get_mutability(string[1])); }
'~' => { return ast::sty_uniq; }
'~' => { return ast::sty_uniq(get_mutability(string[1])); }
'&' => {
// FIXME(#4846) expl. region
return ast::sty_region(None, get_mutability(string[1]));

View File

@ -662,8 +662,9 @@ fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::explic
sty_static => {
ebml_w.writer.write(&[ 's' as u8 ]);
}
sty_value => {
sty_value(m) => {
ebml_w.writer.write(&[ 'v' as u8 ]);
encode_mutability(ebml_w, m);
}
sty_region(_, m) => {
// FIXME(#4846) encode custom lifetime
@ -674,8 +675,9 @@ fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::explic
ebml_w.writer.write(&[ '@' as u8 ]);
encode_mutability(ebml_w, m);
}
sty_uniq => {
sty_uniq(m) => {
ebml_w.writer.write(&[ '~' as u8 ]);
encode_mutability(ebml_w, m);
}
}

View File

@ -410,7 +410,7 @@ impl tr for ast::Def {
ast::DefMethod(did0.tr(xcx), did1.map(|did1| did1.tr(xcx)))
}
ast::DefSelfTy(nid) => { ast::DefSelfTy(xcx.tr_id(nid)) }
ast::DefSelf(nid) => { ast::DefSelf(xcx.tr_id(nid)) }
ast::DefSelf(nid, m) => { ast::DefSelf(xcx.tr_id(nid), m) }
ast::DefMod(did) => { ast::DefMod(did.tr(xcx)) }
ast::DefForeignMod(did) => { ast::DefForeignMod(did.tr(xcx)) }
ast::DefStatic(did, m) => { ast::DefStatic(did.tr(xcx), m) }

View File

@ -392,7 +392,7 @@ fn visit_fn(v: &mut LivenessVisitor,
match *fk {
visit::fk_method(_, _, method) => {
match method.explicit_self.node {
sty_value | sty_region(*) | sty_box(_) | sty_uniq => {
sty_value(_) | sty_region(*) | sty_box(_) | sty_uniq(_) => {
fn_maps.add_variable(Arg(method.self_id,
special_idents::self_));
}

View File

@ -488,12 +488,12 @@ impl mem_categorization_ctxt {
}
}
ast::DefSelf(self_id) => {
ast::DefSelf(self_id, mutbl) => {
@cmt_ {
id:id,
span:span,
cat:cat_self(self_id),
mutbl: McImmutable,
mutbl: if mutbl { McDeclared } else { McImmutable },
ty:expr_ty
}
}

View File

@ -227,7 +227,7 @@ pub fn moved_variable_node_id_from_def(def: Def) -> Option<NodeId> {
DefBinding(nid, _) |
DefArg(nid, _) |
DefLocal(nid, _) |
DefSelf(nid) => Some(nid),
DefSelf(nid, _) => Some(nid),
_ => None
}

View File

@ -150,7 +150,7 @@ enum Mutability {
enum SelfBinding {
NoSelfBinding,
HasSelfBinding(NodeId)
HasSelfBinding(NodeId, explicit_self)
}
impl Visitor<()> for Resolver {
@ -3799,8 +3799,12 @@ impl Resolver {
NoSelfBinding => {
// Nothing to do.
}
HasSelfBinding(self_node_id) => {
let def_like = DlDef(DefSelf(self_node_id));
HasSelfBinding(self_node_id, explicit_self) => {
let mutable = match explicit_self.node {
sty_uniq(m) | sty_value(m) if m == MutMutable => true,
_ => false
};
let def_like = DlDef(DefSelf(self_node_id, mutable));
*function_value_rib.self_binding = Some(def_like);
}
}
@ -3937,7 +3941,7 @@ impl Resolver {
// we only have self ty if it is a non static method
let self_binding = match method.explicit_self.node {
sty_static => { NoSelfBinding }
_ => { HasSelfBinding(method.self_id) }
_ => { HasSelfBinding(method.self_id, method.explicit_self) }
};
self.resolve_function(rib_kind,

View File

@ -1099,7 +1099,7 @@ pub fn trans_local_var(bcx: @mut Block, def: ast::Def) -> Datum {
ast::DefLocal(nid, _) | ast::DefBinding(nid, _) => {
take_local(bcx, bcx.fcx.lllocals, nid)
}
ast::DefSelf(nid) => {
ast::DefSelf(nid, _) => {
let self_info: ValSelfData = match bcx.fcx.llself {
Some(ref self_info) => *self_info,
None => {

View File

@ -144,7 +144,7 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::DefId)
debug!("calling inline trans_fn with self_ty {}",
ty_to_str(ccx.tcx, self_ty));
match mth.explicit_self.node {
ast::sty_value => impl_self(self_ty, ty::ByRef),
ast::sty_value(_) => impl_self(self_ty, ty::ByRef),
_ => impl_self(self_ty, ty::ByCopy),
}
}

View File

@ -120,7 +120,7 @@ pub fn trans_method(ccx: @mut CrateContext,
debug!("calling trans_fn with self_ty {}",
self_ty.repr(ccx.tcx));
match method.explicit_self.node {
ast::sty_value => impl_self(self_ty, ty::ByRef),
ast::sty_value(_) => impl_self(self_ty, ty::ByRef),
_ => impl_self(self_ty, ty::ByCopy),
}
}

View File

@ -672,7 +672,7 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:RegionScope + Clone + 'static>(
{
match self_info.explicit_self.node {
ast::sty_static => None,
ast::sty_value => {
ast::sty_value(_) => {
Some(self_info.untransformed_self_ty)
}
ast::sty_region(ref lifetime, mutability) => {
@ -689,7 +689,7 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:RegionScope + Clone + 'static>(
ty::mt {ty: self_info.untransformed_self_ty,
mutbl: mutability}))
}
ast::sty_uniq => {
ast::sty_uniq(_) => {
Some(ty::mk_uniq(this.tcx(),
ty::mt {ty: self_info.untransformed_self_ty,
mutbl: ast::MutImmutable}))

View File

@ -1082,7 +1082,7 @@ impl<'self> LookupContext<'self> {
ast::sty_static => {
self.bug(~"static method for object type receiver");
}
ast::sty_value => {
ast::sty_value(_) => {
ty::mk_err() // error reported in `enforce_object_limitations()`
}
ast::sty_region(*) | ast::sty_box(*) | ast::sty_uniq(*) => {
@ -1141,7 +1141,7 @@ impl<'self> LookupContext<'self> {
through an object");
}
ast::sty_value => { // reason (a) above
ast::sty_value(_) => { // reason (a) above
self.tcx().sess.span_err(
self.expr.span,
"cannot call a method with a by-value receiver \
@ -1198,7 +1198,7 @@ impl<'self> LookupContext<'self> {
false
}
sty_value => {
sty_value(_) => {
rcvr_matches_ty(self.fcx, rcvr_ty, candidate)
}
@ -1236,7 +1236,7 @@ impl<'self> LookupContext<'self> {
}
}
sty_uniq => {
sty_uniq(_) => {
debug!("(is relevant?) explicit self is a unique pointer");
match ty::get(rcvr_ty).sty {
ty::ty_uniq(mt) => {
@ -1369,7 +1369,7 @@ impl<'self> LookupContext<'self> {
pub fn get_mode_from_explicit_self(explicit_self: ast::explicit_self_) -> SelfMode {
match explicit_self {
sty_value => ty::ByRef,
sty_value(_) => ty::ByRef,
_ => ty::ByCopy,
}
}

View File

@ -3254,7 +3254,7 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt,
defn: ast::Def)
-> ty_param_bounds_and_ty {
match defn {
ast::DefArg(nid, _) | ast::DefLocal(nid, _) | ast::DefSelf(nid) |
ast::DefArg(nid, _) | ast::DefLocal(nid, _) | ast::DefSelf(nid, _) |
ast::DefBinding(nid, _) => {
let typ = fcx.local_ty(sp, nid);
return no_params(typ);

View File

@ -58,7 +58,7 @@ fn encl_region_of_def(fcx: @mut FnCtxt, def: ast::Def) -> ty::Region {
let tcx = fcx.tcx();
match def {
DefLocal(node_id, _) | DefArg(node_id, _) |
DefSelf(node_id) | DefBinding(node_id, _) => {
DefSelf(node_id, _) | DefBinding(node_id, _) => {
tcx.region_maps.encl_region(node_id)
}
DefUpvar(_, subdef, closure_id, body_id) => {

View File

@ -388,8 +388,8 @@ impl Clean<SelfTy> for ast::explicit_self {
fn clean(&self) -> SelfTy {
match self.node {
ast::sty_static => SelfStatic,
ast::sty_value => SelfValue,
ast::sty_uniq => SelfOwned,
ast::sty_value(_) => SelfValue,
ast::sty_uniq(_) => SelfOwned,
ast::sty_region(lt, mt) => SelfBorrowed(lt.clean(), mt.clean()),
ast::sty_box(mt) => SelfManaged(mt.clean()),
}
@ -1171,7 +1171,7 @@ fn resolve_type(path: Path, tpbs: Option<~[TyParamBound]>,
let (def_id, kind) = match *d {
ast::DefFn(i, _) => (i, TypeFunction),
ast::DefSelf(i) | ast::DefSelfTy(i) => return Self(i),
ast::DefSelf(i, _) | ast::DefSelfTy(i) => return Self(i),
ast::DefTy(i) => (i, TypeEnum),
ast::DefTrait(i) => {
debug!("saw DefTrait in def_to_id");

View File

@ -227,7 +227,7 @@ pub enum MethodProvenance {
pub enum Def {
DefFn(DefId, purity),
DefStaticMethod(/* method */ DefId, MethodProvenance, purity),
DefSelf(NodeId),
DefSelf(NodeId, bool /* is_mutbl */),
DefSelfTy(/* trait id */ NodeId),
DefMod(DefId),
DefForeignMod(DefId),
@ -921,10 +921,10 @@ pub enum ret_style {
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
pub enum explicit_self_ {
sty_static, // no self
sty_value, // `self`
sty_region(Option<Lifetime>, Mutability), // `&'lt self`
sty_value(Mutability), // `self`
sty_region(Option<Lifetime>, Mutability), // `&'lt self`
sty_box(Mutability), // `@self`
sty_uniq // `~self`
sty_uniq(Mutability) // `~self`
}
pub type explicit_self = Spanned<explicit_self_>;

View File

@ -66,7 +66,7 @@ pub fn def_id_of_def(d: Def) -> DefId {
DefUse(id) | DefStruct(id) | DefTrait(id) | DefMethod(id, _) => {
id
}
DefArg(id, _) | DefLocal(id, _) | DefSelf(id) | DefSelfTy(id)
DefArg(id, _) | DefLocal(id, _) | DefSelf(id, _) | DefSelfTy(id)
| DefUpvar(id, _, _, _) | DefBinding(id, _) | DefRegion(id)
| DefTyParamBinder(id) | DefLabel(id) => {
local_def(id)

View File

@ -240,13 +240,13 @@ pub fn get_explicit_self(cx: @ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
let self_path = cx.expr_self(span);
match *self_ptr {
None => {
(self_path, respan(span, ast::sty_value))
(self_path, respan(span, ast::sty_value(ast::MutImmutable)))
}
Some(ref ptr) => {
let self_ty = respan(
span,
match *ptr {
Send => ast::sty_uniq,
Send => ast::sty_uniq(ast::MutImmutable),
Managed(mutbl) => ast::sty_box(mutbl),
Borrowed(ref lt, mutbl) => {
let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s)));

View File

@ -3438,15 +3438,11 @@ impl Parser {
// parse the argument list and result type of a function
// that may have a self type.
fn parse_fn_decl_with_self(
&self,
parse_arg_fn:
&fn(&Parser) -> arg
) -> (explicit_self, fn_decl) {
fn maybe_parse_explicit_self(
cnstr: &fn(v: Mutability) -> ast::explicit_self_,
p: &Parser
) -> ast::explicit_self_ {
fn parse_fn_decl_with_self(&self, parse_arg_fn: &fn(&Parser) -> arg)
-> (explicit_self, fn_decl) {
fn maybe_parse_explicit_self(cnstr: &fn(v: Mutability) -> ast::explicit_self_,
p: &Parser) -> ast::explicit_self_ {
// We need to make sure it isn't a type
if p.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) ||
((p.look_ahead(1, |t| token::is_keyword(keywords::Const, t)) ||
@ -3524,25 +3520,39 @@ impl Parser {
self.span_err(*self.last_span,
"mutability declaration not allowed here");
}
sty_uniq
sty_uniq(MutImmutable)
}, self)
}
token::IDENT(*) if self.is_self_ident() => {
self.bump();
sty_value
sty_value(MutImmutable)
}
token::BINOP(token::STAR) => {
// Possibly "*self" or "*mut self" -- not supported. Try to avoid
// emitting cryptic "unexpected token" errors.
self.bump();
if self.token_is_mutability(self.token) {
self.bump();
}
let mutability = if self.token_is_mutability(self.token) {
self.parse_mutability()
} else { MutImmutable };
if self.is_self_ident() {
self.span_err(*self.span, "cannot pass self by unsafe pointer");
self.bump();
}
sty_value
sty_value(mutability)
}
_ if self.token_is_mutability(self.token) &&
self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) => {
let mutability = self.parse_mutability();
self.expect_self_ident();
sty_value(mutability)
}
_ if self.token_is_mutability(self.token) &&
self.look_ahead(1, |t| *t == token::TILDE) &&
self.look_ahead(2, |t| token::is_keyword(keywords::Self, t)) => {
let mutability = self.parse_mutability();
self.bump();
self.expect_self_ident();
sty_uniq(mutability)
}
_ => {
sty_static

View File

@ -1686,8 +1686,14 @@ pub fn explicit_self_to_str(explicit_self: &ast::explicit_self_, intr: @ident_in
pub fn print_explicit_self(s: @ps, explicit_self: ast::explicit_self_) -> bool {
match explicit_self {
ast::sty_static => { return false; }
ast::sty_value => { word(s.s, "self"); }
ast::sty_uniq => { word(s.s, "~self"); }
ast::sty_value(m) => {
print_mutability(s, m);
word(s.s, "self");
}
ast::sty_uniq(m) => {
print_mutability(s, m);
word(s.s, "~self");
}
ast::sty_region(ref lt, m) => {
word(s.s, "&");
print_opt_lifetime(s, lt);

View File

@ -0,0 +1,30 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct X {
a: int
}
trait Changer {
fn change(mut self) -> Self;
}
impl Changer for X {
fn change(mut self) -> X {
self.a = 55;
self
}
}
pub fn main() {
let x = X { a: 32 };
let new_x = x.change();
assert_eq!(new_x.a, 55);
}

View File

@ -0,0 +1,43 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct X {
a: int
}
trait Changer {
fn change(mut self) -> Self {
self.set_to(55);
self
}
fn change_again(mut ~self) -> ~Self {
self.set_to(45);
self
}
fn set_to(&mut self, a: int);
}
impl Changer for X {
fn set_to(&mut self, a: int) {
self.a = a;
}
}
pub fn main() {
let x = X { a: 32 };
let new_x = x.change();
assert_eq!(new_x.a, 55);
let x = ~new_x;
let new_x = x.change_again();
assert_eq!(new_x.a, 45);
}

View File

@ -0,0 +1,30 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct X {
a: int
}
trait Changer {
fn change(mut ~self) -> ~Self;
}
impl Changer for X {
fn change(mut ~self) -> ~X {
self.a = 55;
self
}
}
pub fn main() {
let x = ~X { a: 32 };
let new_x = x.change();
assert_eq!(new_x.a, 55);
}