about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-10-22 19:46:09 -0700
committerbors <bors@rust-lang.org>2013-10-22 19:46:09 -0700
commit78573149cbeb0d0b626d128a8950f1220ed551ad (patch)
treeeb8c74945054822c9c9b4afea428ebd2970561a9
parent22a5ebdc6b13089d2322d9944bdec1507d21eec2 (diff)
parentb2b2095eaf2e71b1b60797a96c097572928f001c (diff)
downloadrust-78573149cbeb0d0b626d128a8950f1220ed551ad.tar.gz
rust-78573149cbeb0d0b626d128a8950f1220ed551ad.zip
auto merge of #9989 : luqmana/rust/mut-everywhere, r=alexcrichton
-rw-r--r--doc/rust.md15
-rw-r--r--src/librustc/metadata/decoder.rs4
-rw-r--r--src/librustc/metadata/encoder.rs6
-rw-r--r--src/librustc/middle/astencode.rs2
-rw-r--r--src/librustc/middle/liveness.rs2
-rw-r--r--src/librustc/middle/mem_categorization.rs4
-rw-r--r--src/librustc/middle/moves.rs2
-rw-r--r--src/librustc/middle/resolve.rs12
-rw-r--r--src/librustc/middle/trans/expr.rs2
-rw-r--r--src/librustc/middle/trans/inline.rs2
-rw-r--r--src/librustc/middle/trans/meth.rs2
-rw-r--r--src/librustc/middle/typeck/astconv.rs4
-rw-r--r--src/librustc/middle/typeck/check/method.rs10
-rw-r--r--src/librustc/middle/typeck/check/mod.rs2
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs2
-rw-r--r--src/librustdoc/clean.rs6
-rw-r--r--src/libsyntax/ast.rs8
-rw-r--r--src/libsyntax/ast_util.rs2
-rw-r--r--src/libsyntax/ext/deriving/ty.rs4
-rw-r--r--src/libsyntax/parse/parser.rs40
-rw-r--r--src/libsyntax/print/pprust.rs10
-rw-r--r--src/test/run-pass/by-value-self-in-mut-slot.rs30
-rw-r--r--src/test/run-pass/self-in-mut-slot-default-method.rs43
-rw-r--r--src/test/run-pass/uniq-self-in-mut-slot.rs30
24 files changed, 188 insertions, 56 deletions
diff --git a/doc/rust.md b/doc/rust.md
index fd2da43a037..40a3bc12798 100644
--- a/doc/rust.md
+++ b/doc/rust.md
@@ -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
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index aa1c4c1eb7e..10232730329 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -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]));
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 9f40593a93a..bae0dcc2a52 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -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);
         }
     }
 
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 294bbcb46f7..3d7f28b8b30 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -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) }
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 6c53fc1602f..71934c9f2a7 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -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_));
                 }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 37e89e58fa5..eb03027ad71 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -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
             }
           }
diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs
index 1ed517c9512..5001614647a 100644
--- a/src/librustc/middle/moves.rs
+++ b/src/librustc/middle/moves.rs
@@ -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
     }
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index b480aaac1ac..ee36b807ac7 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -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,
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 238b15fe597..56f1e047841 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -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 => {
diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs
index a5be9a3ca5e..d9f7cdeeb2e 100644
--- a/src/librustc/middle/trans/inline.rs
+++ b/src/librustc/middle/trans/inline.rs
@@ -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),
                       }
                   }
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index a8c18c72167..61384c72efa 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -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),
         }
       }
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index ccda6bbaf9d..dd0c6c12a69 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -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}))
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index f6efd3aa5ad..af1d5ce3cc6 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -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,
     }
 }
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index eddf8aa5185..4514564ff1f 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -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);
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 06a13059462..09fc7b5c15c 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -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) => {
diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs
index 6ee7f8c1727..dd1ad8263da 100644
--- a/src/librustdoc/clean.rs
+++ b/src/librustdoc/clean.rs
@@ -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");
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 01033e829f6..372f1950c1d 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -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_>;
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index bdebc9872e6..1d9d5512ff4 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -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)
diff --git a/src/libsyntax/ext/deriving/ty.rs b/src/libsyntax/ext/deriving/ty.rs
index 83c73e3d85f..c60259304ae 100644
--- a/src/libsyntax/ext/deriving/ty.rs
+++ b/src/libsyntax/ext/deriving/ty.rs
@@ -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)));
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index ed6019e1a55..605e259cf0c 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -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
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index b245bd75ace..0e330da31e6 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -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);
diff --git a/src/test/run-pass/by-value-self-in-mut-slot.rs b/src/test/run-pass/by-value-self-in-mut-slot.rs
new file mode 100644
index 00000000000..aa88004cd11
--- /dev/null
+++ b/src/test/run-pass/by-value-self-in-mut-slot.rs
@@ -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);
+}
diff --git a/src/test/run-pass/self-in-mut-slot-default-method.rs b/src/test/run-pass/self-in-mut-slot-default-method.rs
new file mode 100644
index 00000000000..08d10fd1170
--- /dev/null
+++ b/src/test/run-pass/self-in-mut-slot-default-method.rs
@@ -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);
+}
diff --git a/src/test/run-pass/uniq-self-in-mut-slot.rs b/src/test/run-pass/uniq-self-in-mut-slot.rs
new file mode 100644
index 00000000000..7c2f5221176
--- /dev/null
+++ b/src/test/run-pass/uniq-self-in-mut-slot.rs
@@ -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);
+}