Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow mut on self/~self like other args. #9989

Merged
merged 4 commits into from
Oct 23, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions doc/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]));
Expand Down
6 changes: 4 additions & 2 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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_));
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/moves.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
12 changes: 8 additions & 4 deletions src/librustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ enum Mutability {

enum SelfBinding {
NoSelfBinding,
HasSelfBinding(NodeId)
HasSelfBinding(NodeId, explicit_self)
}

impl Visitor<()> for Resolver {
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/meth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand All @@ -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}))
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/middle/typeck/check/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(*) => {
Expand Down Expand Up @@ -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 \
Expand Down Expand Up @@ -1198,7 +1198,7 @@ impl<'self> LookupContext<'self> {
false
}

sty_value => {
sty_value(_) => {
rcvr_matches_ty(self.fcx, rcvr_ty, candidate)
}

Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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,
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/typeck/check/regionck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
6 changes: 3 additions & 3 deletions src/librustdoc/clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
}
Expand Down Expand Up @@ -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");
Expand Down
8 changes: 4 additions & 4 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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_>;
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/ast_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/ext/deriving/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
Expand Down
40 changes: 25 additions & 15 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)) ||
Expand Down Expand Up @@ -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
Expand Down
10 changes: 8 additions & 2 deletions src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading