let explicit_self_kind = string.as_bytes()[0];
match explicit_self_kind as char {
's' => ast::SelfStatic,
- 'v' => ast::SelfValue,
- '~' => ast::SelfUniq,
+ 'v' => ast::SelfValue(special_idents::self_),
+ '~' => ast::SelfUniq(special_idents::self_),
// FIXME(#4846) expl. region
- '&' => ast::SelfRegion(None, get_mutability(string.as_bytes()[1])),
+ '&' => ast::SelfRegion(None, get_mutability(string.as_bytes()[1]),
+ special_idents::self_),
_ => fail!("unknown self type code: `{}`", explicit_self_kind as char)
}
}
// Encode the base self type.
match explicit_self {
- SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); }
- SelfValue => { ebml_w.writer.write(&[ 'v' as u8 ]); }
- SelfUniq => { ebml_w.writer.write(&[ '~' as u8 ]); }
- SelfRegion(_, m) => {
+ SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); }
+ SelfValue(_) => { ebml_w.writer.write(&[ 'v' as u8 ]); }
+ SelfUniq(_) => { ebml_w.writer.write(&[ '~' as u8 ]); }
+ SelfRegion(_, m, _) => {
// FIXME(#4846) encode custom lifetime
ebml_w.writer.write(&['&' as u8]);
encode_mutability(ebml_w, m);
ExprId(0),
substs.clone(),
vtables.clone());
- if m.explicit_self == ast::SelfValue {
- fn_ref = trans_unboxing_shim(bcx,
- fn_ref,
- &*m,
- m_id,
- substs.clone());
+ match m.explicit_self {
+ ast::SelfValue(_) => {
+ fn_ref = trans_unboxing_shim(bcx,
+ fn_ref,
+ &*m,
+ m_id,
+ substs.clone());
+ },
+ _ => {}
}
fn_ref
}
let self_ty = opt_self_info.and_then(|self_info| {
match self_info.explicit_self.node {
ast::SelfStatic => None,
- ast::SelfValue => {
+ ast::SelfValue(_) => {
Some(self_info.untransformed_self_ty)
}
- ast::SelfRegion(ref lifetime, mutability) => {
+ ast::SelfRegion(ref lifetime, mutability, _) => {
let region =
opt_ast_region_to_region(this, &rb,
self_info.explicit_self.span,
ty::mt {ty: self_info.untransformed_self_ty,
mutbl: mutability}))
}
- ast::SelfUniq => {
+ ast::SelfUniq(_) => {
Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty))
}
}
ast::SelfStatic => {
tcx.sess.span_bug(span, "static method for object type receiver");
}
- ast::SelfValue => {
+ ast::SelfValue(_) => {
let tr = ty::mk_trait(tcx, trait_def_id, obj_substs,
ty::empty_builtin_bounds());
ty::mk_uniq(tcx, tr)
}
- ast::SelfRegion(..) | ast::SelfUniq => {
+ ast::SelfRegion(..) | ast::SelfUniq(..) => {
let transformed_self_ty = *method_ty.fty.sig.inputs.get(0);
match ty::get(transformed_self_ty).sty {
ty::ty_rptr(r, mt) => { // must be SelfRegion
through an object");
}
- ast::SelfValue | ast::SelfRegion(..) | ast::SelfUniq => {}
+ ast::SelfValue(_) | ast::SelfRegion(..) | ast::SelfUniq(_) => {}
}
// reason (a) above
self.report_statics == ReportStaticMethods
}
- SelfValue => {
+ SelfValue(_) => {
debug!("(is relevant?) explicit self is by-value");
match ty::get(rcvr_ty).sty {
ty::ty_uniq(typ) => {
}
}
- SelfRegion(_, m) => {
+ SelfRegion(_, m, _) => {
debug!("(is relevant?) explicit self is a region");
match ty::get(rcvr_ty).sty {
ty::ty_rptr(_, mt) => {
}
}
- SelfUniq => {
+ SelfUniq(_) => {
debug!("(is relevant?) explicit self is a unique pointer");
match ty::get(rcvr_ty).sty {
ty::ty_uniq(typ) => {
-> Option<ast::ExplicitSelf_> {
match expl_self_opt {
Some(expl_self) => match expl_self {
- ast::SelfRegion(lt_opt, muta) => match lt_opt {
+ ast::SelfRegion(lt_opt, muta, id) => match lt_opt {
Some(lt) => if region_names.contains(<.name) {
- return Some(ast::SelfRegion(Some(lifetime), muta));
+ return Some(ast::SelfRegion(Some(lifetime), muta, id));
},
None => {
let anon = self.cur_anon.get();
self.inc_and_offset_cur_anon(1);
if anon_nums.contains(&anon) {
self.track_anon(anon);
- return Some(ast::SelfRegion(Some(lifetime), muta));
+ return Some(ast::SelfRegion(Some(lifetime), muta, id));
}
}
},
fn clean(&self) -> SelfTy {
match *self {
ast::SelfStatic => SelfStatic,
- ast::SelfValue => SelfValue,
- ast::SelfUniq => SelfOwned,
- ast::SelfRegion(lt, mt) => SelfBorrowed(lt.clean(), mt.clean()),
+ ast::SelfValue(_) => SelfValue,
+ ast::SelfUniq(_) => SelfOwned,
+ ast::SelfRegion(lt, mt, _) => SelfBorrowed(lt.clean(), mt.clean()),
}
}
}
use abi::Abi;
use ast_util;
use owned_slice::OwnedSlice;
-use parse::token::{InternedString, special_idents, str_to_ident};
+use parse::token::{InternedString, str_to_ident};
use parse::token;
use std::fmt;
}
impl Arg {
- pub fn new_self(span: Span, mutability: Mutability) -> Arg {
- let path = Spanned{span:span,node:special_idents::self_};
+ pub fn new_self(span: Span, mutability: Mutability, self_ident: Ident) -> Arg {
+ let path = Spanned{span:span,node:self_ident};
Arg {
// HACK(eddyb) fake type for the self argument.
ty: P(Ty {
Return, // everything else
}
+/// Represents the kind of 'self' associated with a method
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
pub enum ExplicitSelf_ {
- SelfStatic, // no self
- SelfValue, // `self`
- SelfRegion(Option<Lifetime>, Mutability), // `&'lt self`, `&'lt mut self`
- SelfUniq // `~self`
+ SelfStatic, // no self
+ SelfValue(Ident), // `self`
+ SelfRegion(Option<Lifetime>, Mutability, Ident), // `&'lt self`, `&'lt mut self`
+ SelfUniq(Ident), // `~self`
}
pub type ExplicitSelf = Spanned<ExplicitSelf_>;
use codemap::Span;
use owned_slice::OwnedSlice;
use parse::token::InternedString;
+use parse::token::special_idents;
use self::ty::*;
let self_arg = match explicit_self.node {
ast::SelfStatic => None,
- _ => Some(ast::Arg::new_self(trait_.span, ast::MutImmutable))
+ // creating fresh self id
+ _ => Some(ast::Arg::new_self(trait_.span, ast::MutImmutable, special_idents::self_))
};
let args = {
let args = arg_types.move_iter().map(|(name, ty)| {
use ext::build::AstBuilder;
use codemap::{Span,respan};
use owned_slice::OwnedSlice;
+use parse::token::special_idents;
use std::gc::Gc;
}
}
-
pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
-> (Gc<Expr>, ast::ExplicitSelf) {
+ // this constructs a fresh `self` path, which will match the fresh `self` binding
+ // created below.
let self_path = cx.expr_self(span);
match *self_ptr {
None => {
- (self_path, respan(span, ast::SelfValue))
+ (self_path, respan(span, ast::SelfValue(special_idents::self_)))
}
Some(ref ptr) => {
let self_ty = respan(
span,
match *ptr {
- Send => ast::SelfUniq,
+ Send => ast::SelfUniq(special_idents::self_),
Borrowed(ref lt, mutbl) => {
let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name));
- ast::SelfRegion(lt, mutbl)
+ ast::SelfRegion(lt, mutbl, special_idents::self_)
}
});
let self_expr = cx.expr_deref(span, self_path);
0)
}
- // macro_rules in method position
- #[test] fn macro_in_method_posn(){
+ // macro_rules in method position. Sadly, unimplemented.
+ #[ignore] #[test] fn macro_in_method_posn(){
expand_crate_str(
"macro_rules! my_method (() => fn thirteen(&self) -> int {13})
struct A;
fn f(){A.thirteen;}".to_string());
}
+ // another nested macro
+ // expands to impl Entries {fn size_hint(&self_1) {self_1;}
+ #[test] fn item_macro_workaround(){
+ run_renaming_test(
+ &("macro_rules! item { ($i:item) => {$i}}
+ struct Entries;
+ macro_rules! iterator_impl {
+ () => { item!( impl Entries { fn size_hint(&self) { self;}})}}
+ iterator_impl! { }",
+ vec!(vec!(0)), true),
+ 0)
+ }
+
// run one of the renaming tests
fn run_renaming_test(t: &RenamingTest, test_idx: uint) {
let invalid_name = token::special_idents::invalid.name;
fn fold_explicit_self_(&mut self, es: &ExplicitSelf_) -> ExplicitSelf_ {
match *es {
- SelfStatic | SelfValue | SelfUniq => *es,
- SelfRegion(ref lifetime, m) => {
- SelfRegion(fold_opt_lifetime(lifetime, self), m)
+ SelfStatic | SelfValue(_) | SelfUniq(_) => *es,
+ SelfRegion(ref lifetime, m, id) => {
+ SelfRegion(fold_opt_lifetime(lifetime, self), m, id)
}
}
}
}
}
- fn expect_self_ident(&mut self) {
- if !self.is_self_ident() {
- let token_str = self.this_token_to_string();
- self.fatal(format!("expected `self` but found `{}`",
- token_str).as_slice())
+ fn expect_self_ident(&mut self) -> ast::Ident {
+ match self.token {
+ token::IDENT(id, false) if id.name == special_idents::self_.name => {
+ self.bump();
+ id
+ },
+ _ => {
+ let token_str = self.this_token_to_string();
+ self.fatal(format!("expected `self` but found `{}`",
+ token_str).as_slice())
+ }
}
- self.bump();
}
// parse the argument list and result type of a function
if this.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) {
this.bump();
- this.expect_self_ident();
- SelfRegion(None, MutImmutable)
+ SelfRegion(None, MutImmutable, this.expect_self_ident())
} else if this.look_ahead(1, |t| Parser::token_is_mutability(t)) &&
this.look_ahead(2,
|t| token::is_keyword(keywords::Self,
t)) {
this.bump();
let mutability = this.parse_mutability();
- this.expect_self_ident();
- SelfRegion(None, mutability)
+ SelfRegion(None, mutability, this.expect_self_ident())
} else if this.look_ahead(1, |t| Parser::token_is_lifetime(t)) &&
this.look_ahead(2,
|t| token::is_keyword(keywords::Self,
t)) {
this.bump();
let lifetime = this.parse_lifetime();
- this.expect_self_ident();
- SelfRegion(Some(lifetime), MutImmutable)
+ SelfRegion(Some(lifetime), MutImmutable, this.expect_self_ident())
} else if this.look_ahead(1, |t| Parser::token_is_lifetime(t)) &&
this.look_ahead(2, |t| {
Parser::token_is_mutability(t)
this.bump();
let lifetime = this.parse_lifetime();
let mutability = this.parse_mutability();
- this.expect_self_ident();
- SelfRegion(Some(lifetime), mutability)
+ SelfRegion(Some(lifetime), mutability, this.expect_self_ident())
} else {
SelfStatic
}
// We need to make sure it isn't a type
if self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) {
self.bump();
- self.expect_self_ident();
- SelfUniq
+ SelfUniq(self.expect_self_ident())
} else {
SelfStatic
}
}
token::IDENT(..) if self.is_self_ident() => {
- self.bump();
- SelfValue
+ SelfValue(self.expect_self_ident())
}
token::BINOP(token::STAR) => {
// Possibly "*self" or "*mut self" -- not supported. Try to avoid
self.span_err(span, "cannot pass self by unsafe pointer");
self.bump();
}
- SelfValue
+ // error case, making bogus self ident:
+ SelfValue(special_idents::self_)
}
_ if Parser::token_is_mutability(&self.token) &&
self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) => {
mutbl_self = self.parse_mutability();
- self.expect_self_ident();
- SelfValue
+ SelfValue(self.expect_self_ident())
}
_ if Parser::token_is_mutability(&self.token) &&
self.look_ahead(1, |t| *t == token::TILDE) &&
self.look_ahead(2, |t| token::is_keyword(keywords::Self, t)) => {
mutbl_self = self.parse_mutability();
self.bump();
- self.expect_self_ident();
- SelfUniq
+ SelfUniq(self.expect_self_ident())
}
_ => SelfStatic
};
let explicit_self_sp = mk_sp(lo, self.span.hi);
- // If we parsed a self type, expect a comma before the argument list.
- let fn_inputs = if explicit_self != SelfStatic {
+ // shared fall-through for the three cases below. borrowing prevents simply
+ // writing this as a closure
+ macro_rules! parse_remaining_arguments {
+ ($self_id:ident) =>
+ {
+ // If we parsed a self type, expect a comma before the argument list.
match self.token {
token::COMMA => {
self.bump();
sep,
parse_arg_fn
);
- fn_inputs.unshift(Arg::new_self(explicit_self_sp, mutbl_self));
+ fn_inputs.unshift(Arg::new_self(explicit_self_sp, mutbl_self, $self_id));
fn_inputs
}
token::RPAREN => {
- vec!(Arg::new_self(explicit_self_sp, mutbl_self))
+ vec!(Arg::new_self(explicit_self_sp, mutbl_self, $self_id))
}
_ => {
let token_str = self.this_token_to_string();
token_str).as_slice())
}
}
- } else {
- let sep = seq_sep_trailing_disallowed(token::COMMA);
- self.parse_seq_to_before_end(&token::RPAREN, sep, parse_arg_fn)
+ }
+ }
+
+ let fn_inputs = match explicit_self {
+ SelfStatic => {
+ let sep = seq_sep_trailing_disallowed(token::COMMA);
+ self.parse_seq_to_before_end(&token::RPAREN, sep, parse_arg_fn)
+ }
+ SelfValue(id) => parse_remaining_arguments!(id),
+ SelfRegion(_,_,id) => parse_remaining_arguments!(id),
+ SelfUniq(id) => parse_remaining_arguments!(id)
+
};
+
self.expect(&token::RPAREN);
let hi = self.span.hi;
try!(self.print_mutability(mutbl));
match explicit_self {
ast::SelfStatic => { return Ok(false); }
- ast::SelfValue => {
+ ast::SelfValue(_) => {
try!(word(&mut self.s, "self"));
}
- ast::SelfUniq => {
+ ast::SelfUniq(_) => {
try!(word(&mut self.s, "~self"));
}
- ast::SelfRegion(ref lt, m) => {
+ ast::SelfRegion(ref lt, m, _) => {
try!(word(&mut self.s, "&"));
try!(self.print_opt_lifetime(lt));
try!(self.print_mutability(m));
explicit_self: &ExplicitSelf,
env: E) {
match explicit_self.node {
- SelfStatic | SelfValue | SelfUniq => {}
- SelfRegion(ref lifetime, _) => {
+ SelfStatic | SelfValue(_) | SelfUniq(_) => {},
+ SelfRegion(ref lifetime, _, _) => {
visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime, env)
}
}