diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index aa1c4c1eb7ec..ca1912c83476 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -975,7 +975,7 @@ 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; } '&' => { diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 9f40593a93ae..0f5ce06a7daa 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 diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 294bbcb46f7b..3d7f28b8b30b 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 6c53fc1602f2..a235d7395a6d 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 37e89e58fa56..eb03027ad71f 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 1ed517c95129..5001614647a8 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 { 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 b480aaac1acb..4c5d2f86a1b2 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_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 238b15fe5979..56f1e0478410 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 a5be9a3ca5e1..d9f7cdeeb2ef 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 a8c18c721671..61384c72efa2 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 ccda6bbaf9d1..e703f6da4168 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( { 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) => { diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index f6efd3aa5ad1..b48e1f7fcf15 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) } @@ -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 eddf8aa51850..4514564ff1f6 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 06a130594623..09fc7b5c15c3 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 6ee7f8c17274..90fc71aa8635 100644 --- a/src/librustdoc/clean.rs +++ b/src/librustdoc/clean.rs @@ -388,7 +388,7 @@ impl Clean for ast::explicit_self { fn clean(&self) -> SelfTy { match self.node { ast::sty_static => SelfStatic, - ast::sty_value => SelfValue, + 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 01033e829f6a..6631924239d3 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,8 +921,8 @@ pub enum ret_style { #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] pub enum explicit_self_ { sty_static, // no self - sty_value, // `self` - sty_region(Option, Mutability), // `&'lt self` + sty_value(Mutability), // `self` + sty_region(Option, Mutability), // `&'lt self` sty_box(Mutability), // `@self` sty_uniq // `~self` } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index bdebc9872e69..1d9d5512ff42 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 83c73e3d85f2..a9fdafc80141 100644 --- a/src/libsyntax/ext/deriving/ty.rs +++ b/src/libsyntax/ext/deriving/ty.rs @@ -240,7 +240,7 @@ pub fn get_explicit_self(cx: @ExtCtxt, span: Span, self_ptr: &Option) 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( diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ed6019e1a55a..133934a746a1 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)) || @@ -3529,20 +3525,26 @@ impl Parser { } 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) } _ => { sty_static diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index b245bd75ace7..9ce28e4d55a8 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1686,7 +1686,10 @@ 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_value(m) => { + print_mutability(s, m); + word(s.s, "self"); + } ast::sty_uniq => { word(s.s, "~self"); } ast::sty_region(ref lt, m) => { word(s.s, "&");