carry self ident forward through re-parsing
formerly, the self identifier was being discarded during parsing, which stymies hygiene. The best fix here seems to be to attach a self identifier to ExplicitSelf_, a change that rippled through the rest of the compiler, but without any obvious damage.
This commit is contained in:
parent
69c27546ee
commit
19e718b34d
15 changed files with 114 additions and 80 deletions
|
@ -739,10 +739,11 @@ fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ {
|
||||||
let explicit_self_kind = string.as_bytes()[0];
|
let explicit_self_kind = string.as_bytes()[0];
|
||||||
match explicit_self_kind as char {
|
match explicit_self_kind as char {
|
||||||
's' => ast::SelfStatic,
|
's' => ast::SelfStatic,
|
||||||
'v' => ast::SelfValue,
|
'v' => ast::SelfValue(special_idents::self_),
|
||||||
'~' => ast::SelfUniq,
|
'~' => ast::SelfUniq(special_idents::self_),
|
||||||
// FIXME(#4846) expl. region
|
// 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)
|
_ => fail!("unknown self type code: `{}`", explicit_self_kind as char)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -628,10 +628,10 @@ fn encode_explicit_self(ebml_w: &mut Encoder, explicit_self: ast::ExplicitSelf_)
|
||||||
|
|
||||||
// Encode the base self type.
|
// Encode the base self type.
|
||||||
match explicit_self {
|
match explicit_self {
|
||||||
SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); }
|
SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); }
|
||||||
SelfValue => { ebml_w.writer.write(&[ 'v' as u8 ]); }
|
SelfValue(_) => { ebml_w.writer.write(&[ 'v' as u8 ]); }
|
||||||
SelfUniq => { ebml_w.writer.write(&[ '~' as u8 ]); }
|
SelfUniq(_) => { ebml_w.writer.write(&[ '~' as u8 ]); }
|
||||||
SelfRegion(_, m) => {
|
SelfRegion(_, m, _) => {
|
||||||
// FIXME(#4846) encode custom lifetime
|
// FIXME(#4846) encode custom lifetime
|
||||||
ebml_w.writer.write(&['&' as u8]);
|
ebml_w.writer.write(&['&' as u8]);
|
||||||
encode_mutability(ebml_w, m);
|
encode_mutability(ebml_w, m);
|
||||||
|
|
|
@ -502,12 +502,15 @@ fn emit_vtable_methods(bcx: &Block,
|
||||||
ExprId(0),
|
ExprId(0),
|
||||||
substs.clone(),
|
substs.clone(),
|
||||||
vtables.clone());
|
vtables.clone());
|
||||||
if m.explicit_self == ast::SelfValue {
|
match m.explicit_self {
|
||||||
fn_ref = trans_unboxing_shim(bcx,
|
ast::SelfValue(_) => {
|
||||||
fn_ref,
|
fn_ref = trans_unboxing_shim(bcx,
|
||||||
&*m,
|
fn_ref,
|
||||||
m_id,
|
&*m,
|
||||||
substs.clone());
|
m_id,
|
||||||
|
substs.clone());
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
fn_ref
|
fn_ref
|
||||||
}
|
}
|
||||||
|
|
|
@ -938,10 +938,10 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
|
||||||
let self_ty = opt_self_info.and_then(|self_info| {
|
let self_ty = opt_self_info.and_then(|self_info| {
|
||||||
match self_info.explicit_self.node {
|
match self_info.explicit_self.node {
|
||||||
ast::SelfStatic => None,
|
ast::SelfStatic => None,
|
||||||
ast::SelfValue => {
|
ast::SelfValue(_) => {
|
||||||
Some(self_info.untransformed_self_ty)
|
Some(self_info.untransformed_self_ty)
|
||||||
}
|
}
|
||||||
ast::SelfRegion(ref lifetime, mutability) => {
|
ast::SelfRegion(ref lifetime, mutability, _) => {
|
||||||
let region =
|
let region =
|
||||||
opt_ast_region_to_region(this, &rb,
|
opt_ast_region_to_region(this, &rb,
|
||||||
self_info.explicit_self.span,
|
self_info.explicit_self.span,
|
||||||
|
@ -950,7 +950,7 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
|
||||||
ty::mt {ty: self_info.untransformed_self_ty,
|
ty::mt {ty: self_info.untransformed_self_ty,
|
||||||
mutbl: mutability}))
|
mutbl: mutability}))
|
||||||
}
|
}
|
||||||
ast::SelfUniq => {
|
ast::SelfUniq(_) => {
|
||||||
Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty))
|
Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,12 +270,12 @@ fn construct_transformed_self_ty_for_object(
|
||||||
ast::SelfStatic => {
|
ast::SelfStatic => {
|
||||||
tcx.sess.span_bug(span, "static method for object type receiver");
|
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,
|
let tr = ty::mk_trait(tcx, trait_def_id, obj_substs,
|
||||||
ty::empty_builtin_bounds());
|
ty::empty_builtin_bounds());
|
||||||
ty::mk_uniq(tcx, tr)
|
ty::mk_uniq(tcx, tr)
|
||||||
}
|
}
|
||||||
ast::SelfRegion(..) | ast::SelfUniq => {
|
ast::SelfRegion(..) | ast::SelfUniq(..) => {
|
||||||
let transformed_self_ty = *method_ty.fty.sig.inputs.get(0);
|
let transformed_self_ty = *method_ty.fty.sig.inputs.get(0);
|
||||||
match ty::get(transformed_self_ty).sty {
|
match ty::get(transformed_self_ty).sty {
|
||||||
ty::ty_rptr(r, mt) => { // must be SelfRegion
|
ty::ty_rptr(r, mt) => { // must be SelfRegion
|
||||||
|
@ -1227,7 +1227,7 @@ impl<'a> LookupContext<'a> {
|
||||||
through an object");
|
through an object");
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::SelfValue | ast::SelfRegion(..) | ast::SelfUniq => {}
|
ast::SelfValue(_) | ast::SelfRegion(..) | ast::SelfUniq(_) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reason (a) above
|
// reason (a) above
|
||||||
|
@ -1296,7 +1296,7 @@ impl<'a> LookupContext<'a> {
|
||||||
self.report_statics == ReportStaticMethods
|
self.report_statics == ReportStaticMethods
|
||||||
}
|
}
|
||||||
|
|
||||||
SelfValue => {
|
SelfValue(_) => {
|
||||||
debug!("(is relevant?) explicit self is by-value");
|
debug!("(is relevant?) explicit self is by-value");
|
||||||
match ty::get(rcvr_ty).sty {
|
match ty::get(rcvr_ty).sty {
|
||||||
ty::ty_uniq(typ) => {
|
ty::ty_uniq(typ) => {
|
||||||
|
@ -1319,7 +1319,7 @@ impl<'a> LookupContext<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SelfRegion(_, m) => {
|
SelfRegion(_, m, _) => {
|
||||||
debug!("(is relevant?) explicit self is a region");
|
debug!("(is relevant?) explicit self is a region");
|
||||||
match ty::get(rcvr_ty).sty {
|
match ty::get(rcvr_ty).sty {
|
||||||
ty::ty_rptr(_, mt) => {
|
ty::ty_rptr(_, mt) => {
|
||||||
|
@ -1339,7 +1339,7 @@ impl<'a> LookupContext<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SelfUniq => {
|
SelfUniq(_) => {
|
||||||
debug!("(is relevant?) explicit self is a unique pointer");
|
debug!("(is relevant?) explicit self is a unique pointer");
|
||||||
match ty::get(rcvr_ty).sty {
|
match ty::get(rcvr_ty).sty {
|
||||||
ty::ty_uniq(typ) => {
|
ty::ty_uniq(typ) => {
|
||||||
|
|
|
@ -947,16 +947,16 @@ impl<'a> Rebuilder<'a> {
|
||||||
-> Option<ast::ExplicitSelf_> {
|
-> Option<ast::ExplicitSelf_> {
|
||||||
match expl_self_opt {
|
match expl_self_opt {
|
||||||
Some(expl_self) => match expl_self {
|
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) {
|
Some(lt) => if region_names.contains(<.name) {
|
||||||
return Some(ast::SelfRegion(Some(lifetime), muta));
|
return Some(ast::SelfRegion(Some(lifetime), muta, id));
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
let anon = self.cur_anon.get();
|
let anon = self.cur_anon.get();
|
||||||
self.inc_and_offset_cur_anon(1);
|
self.inc_and_offset_cur_anon(1);
|
||||||
if anon_nums.contains(&anon) {
|
if anon_nums.contains(&anon) {
|
||||||
self.track_anon(anon);
|
self.track_anon(anon);
|
||||||
return Some(ast::SelfRegion(Some(lifetime), muta));
|
return Some(ast::SelfRegion(Some(lifetime), muta, id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -775,9 +775,9 @@ impl Clean<SelfTy> for ast::ExplicitSelf_ {
|
||||||
fn clean(&self) -> SelfTy {
|
fn clean(&self) -> SelfTy {
|
||||||
match *self {
|
match *self {
|
||||||
ast::SelfStatic => SelfStatic,
|
ast::SelfStatic => SelfStatic,
|
||||||
ast::SelfValue => SelfValue,
|
ast::SelfValue(_) => SelfValue,
|
||||||
ast::SelfUniq => SelfOwned,
|
ast::SelfUniq(_) => SelfOwned,
|
||||||
ast::SelfRegion(lt, mt) => SelfBorrowed(lt.clean(), mt.clean()),
|
ast::SelfRegion(lt, mt, _) => SelfBorrowed(lt.clean(), mt.clean()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use codemap::{Span, Spanned, DUMMY_SP};
|
||||||
use abi::Abi;
|
use abi::Abi;
|
||||||
use ast_util;
|
use ast_util;
|
||||||
use owned_slice::OwnedSlice;
|
use owned_slice::OwnedSlice;
|
||||||
use parse::token::{InternedString, special_idents, str_to_ident};
|
use parse::token::{InternedString, str_to_ident};
|
||||||
use parse::token;
|
use parse::token;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -824,8 +824,8 @@ pub struct Arg {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Arg {
|
impl Arg {
|
||||||
pub fn new_self(span: Span, mutability: Mutability) -> Arg {
|
pub fn new_self(span: Span, mutability: Mutability, self_ident: Ident) -> Arg {
|
||||||
let path = Spanned{span:span,node:special_idents::self_};
|
let path = Spanned{span:span,node:self_ident};
|
||||||
Arg {
|
Arg {
|
||||||
// HACK(eddyb) fake type for the self argument.
|
// HACK(eddyb) fake type for the self argument.
|
||||||
ty: P(Ty {
|
ty: P(Ty {
|
||||||
|
@ -874,12 +874,13 @@ pub enum RetStyle {
|
||||||
Return, // everything else
|
Return, // everything else
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents the kind of 'self' associated with a method
|
||||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
|
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
|
||||||
pub enum ExplicitSelf_ {
|
pub enum ExplicitSelf_ {
|
||||||
SelfStatic, // no self
|
SelfStatic, // no self
|
||||||
SelfValue, // `self`
|
SelfValue(Ident), // `self`
|
||||||
SelfRegion(Option<Lifetime>, Mutability), // `&'lt self`, `&'lt mut self`
|
SelfRegion(Option<Lifetime>, Mutability, Ident), // `&'lt self`, `&'lt mut self`
|
||||||
SelfUniq // `~self`
|
SelfUniq(Ident), // `~self`
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ExplicitSelf = Spanned<ExplicitSelf_>;
|
pub type ExplicitSelf = Spanned<ExplicitSelf_>;
|
||||||
|
|
|
@ -191,6 +191,7 @@ use codemap;
|
||||||
use codemap::Span;
|
use codemap::Span;
|
||||||
use owned_slice::OwnedSlice;
|
use owned_slice::OwnedSlice;
|
||||||
use parse::token::InternedString;
|
use parse::token::InternedString;
|
||||||
|
use parse::token::special_idents;
|
||||||
|
|
||||||
use self::ty::*;
|
use self::ty::*;
|
||||||
|
|
||||||
|
@ -617,7 +618,8 @@ impl<'a> MethodDef<'a> {
|
||||||
|
|
||||||
let self_arg = match explicit_self.node {
|
let self_arg = match explicit_self.node {
|
||||||
ast::SelfStatic => None,
|
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 = {
|
||||||
let args = arg_types.move_iter().map(|(name, ty)| {
|
let args = arg_types.move_iter().map(|(name, ty)| {
|
||||||
|
|
|
@ -19,6 +19,7 @@ use ext::base::ExtCtxt;
|
||||||
use ext::build::AstBuilder;
|
use ext::build::AstBuilder;
|
||||||
use codemap::{Span,respan};
|
use codemap::{Span,respan};
|
||||||
use owned_slice::OwnedSlice;
|
use owned_slice::OwnedSlice;
|
||||||
|
use parse::token::special_idents;
|
||||||
|
|
||||||
use std::gc::Gc;
|
use std::gc::Gc;
|
||||||
|
|
||||||
|
@ -244,22 +245,23 @@ impl<'a> LifetimeBounds<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
|
pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
|
||||||
-> (Gc<Expr>, ast::ExplicitSelf) {
|
-> (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);
|
let self_path = cx.expr_self(span);
|
||||||
match *self_ptr {
|
match *self_ptr {
|
||||||
None => {
|
None => {
|
||||||
(self_path, respan(span, ast::SelfValue))
|
(self_path, respan(span, ast::SelfValue(special_idents::self_)))
|
||||||
}
|
}
|
||||||
Some(ref ptr) => {
|
Some(ref ptr) => {
|
||||||
let self_ty = respan(
|
let self_ty = respan(
|
||||||
span,
|
span,
|
||||||
match *ptr {
|
match *ptr {
|
||||||
Send => ast::SelfUniq,
|
Send => ast::SelfUniq(special_idents::self_),
|
||||||
Borrowed(ref lt, mutbl) => {
|
Borrowed(ref lt, mutbl) => {
|
||||||
let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name));
|
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);
|
let self_expr = cx.expr_deref(span, self_path);
|
||||||
|
|
|
@ -1501,8 +1501,8 @@ mod test {
|
||||||
0)
|
0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// macro_rules in method position
|
// macro_rules in method position. Sadly, unimplemented.
|
||||||
#[test] fn macro_in_method_posn(){
|
#[ignore] #[test] fn macro_in_method_posn(){
|
||||||
expand_crate_str(
|
expand_crate_str(
|
||||||
"macro_rules! my_method (() => fn thirteen(&self) -> int {13})
|
"macro_rules! my_method (() => fn thirteen(&self) -> int {13})
|
||||||
struct A;
|
struct A;
|
||||||
|
@ -1510,6 +1510,19 @@ mod test {
|
||||||
fn f(){A.thirteen;}".to_string());
|
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
|
// run one of the renaming tests
|
||||||
fn run_renaming_test(t: &RenamingTest, test_idx: uint) {
|
fn run_renaming_test(t: &RenamingTest, test_idx: uint) {
|
||||||
let invalid_name = token::special_idents::invalid.name;
|
let invalid_name = token::special_idents::invalid.name;
|
||||||
|
|
|
@ -334,9 +334,9 @@ pub trait Folder {
|
||||||
|
|
||||||
fn fold_explicit_self_(&mut self, es: &ExplicitSelf_) -> ExplicitSelf_ {
|
fn fold_explicit_self_(&mut self, es: &ExplicitSelf_) -> ExplicitSelf_ {
|
||||||
match *es {
|
match *es {
|
||||||
SelfStatic | SelfValue | SelfUniq => *es,
|
SelfStatic | SelfValue(_) | SelfUniq(_) => *es,
|
||||||
SelfRegion(ref lifetime, m) => {
|
SelfRegion(ref lifetime, m, id) => {
|
||||||
SelfRegion(fold_opt_lifetime(lifetime, self), m)
|
SelfRegion(fold_opt_lifetime(lifetime, self), m, id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3748,13 +3748,18 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expect_self_ident(&mut self) {
|
fn expect_self_ident(&mut self) -> ast::Ident {
|
||||||
if !self.is_self_ident() {
|
match self.token {
|
||||||
let token_str = self.this_token_to_string();
|
token::IDENT(id, false) if id.name == special_idents::self_.name => {
|
||||||
self.fatal(format!("expected `self` but found `{}`",
|
self.bump();
|
||||||
token_str).as_slice())
|
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
|
// parse the argument list and result type of a function
|
||||||
|
@ -3774,24 +3779,21 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
if this.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) {
|
if this.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) {
|
||||||
this.bump();
|
this.bump();
|
||||||
this.expect_self_ident();
|
SelfRegion(None, MutImmutable, this.expect_self_ident())
|
||||||
SelfRegion(None, MutImmutable)
|
|
||||||
} else if this.look_ahead(1, |t| Parser::token_is_mutability(t)) &&
|
} else if this.look_ahead(1, |t| Parser::token_is_mutability(t)) &&
|
||||||
this.look_ahead(2,
|
this.look_ahead(2,
|
||||||
|t| token::is_keyword(keywords::Self,
|
|t| token::is_keyword(keywords::Self,
|
||||||
t)) {
|
t)) {
|
||||||
this.bump();
|
this.bump();
|
||||||
let mutability = this.parse_mutability();
|
let mutability = this.parse_mutability();
|
||||||
this.expect_self_ident();
|
SelfRegion(None, mutability, this.expect_self_ident())
|
||||||
SelfRegion(None, mutability)
|
|
||||||
} else if this.look_ahead(1, |t| Parser::token_is_lifetime(t)) &&
|
} else if this.look_ahead(1, |t| Parser::token_is_lifetime(t)) &&
|
||||||
this.look_ahead(2,
|
this.look_ahead(2,
|
||||||
|t| token::is_keyword(keywords::Self,
|
|t| token::is_keyword(keywords::Self,
|
||||||
t)) {
|
t)) {
|
||||||
this.bump();
|
this.bump();
|
||||||
let lifetime = this.parse_lifetime();
|
let lifetime = this.parse_lifetime();
|
||||||
this.expect_self_ident();
|
SelfRegion(Some(lifetime), MutImmutable, this.expect_self_ident())
|
||||||
SelfRegion(Some(lifetime), MutImmutable)
|
|
||||||
} else if this.look_ahead(1, |t| Parser::token_is_lifetime(t)) &&
|
} else if this.look_ahead(1, |t| Parser::token_is_lifetime(t)) &&
|
||||||
this.look_ahead(2, |t| {
|
this.look_ahead(2, |t| {
|
||||||
Parser::token_is_mutability(t)
|
Parser::token_is_mutability(t)
|
||||||
|
@ -3801,8 +3803,7 @@ impl<'a> Parser<'a> {
|
||||||
this.bump();
|
this.bump();
|
||||||
let lifetime = this.parse_lifetime();
|
let lifetime = this.parse_lifetime();
|
||||||
let mutability = this.parse_mutability();
|
let mutability = this.parse_mutability();
|
||||||
this.expect_self_ident();
|
SelfRegion(Some(lifetime), mutability, this.expect_self_ident())
|
||||||
SelfRegion(Some(lifetime), mutability)
|
|
||||||
} else {
|
} else {
|
||||||
SelfStatic
|
SelfStatic
|
||||||
}
|
}
|
||||||
|
@ -3822,15 +3823,13 @@ impl<'a> Parser<'a> {
|
||||||
// We need to make sure it isn't a type
|
// We need to make sure it isn't a type
|
||||||
if self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) {
|
if self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) {
|
||||||
self.bump();
|
self.bump();
|
||||||
self.expect_self_ident();
|
SelfUniq(self.expect_self_ident())
|
||||||
SelfUniq
|
|
||||||
} else {
|
} else {
|
||||||
SelfStatic
|
SelfStatic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
token::IDENT(..) if self.is_self_ident() => {
|
token::IDENT(..) if self.is_self_ident() => {
|
||||||
self.bump();
|
SelfValue(self.expect_self_ident())
|
||||||
SelfValue
|
|
||||||
}
|
}
|
||||||
token::BINOP(token::STAR) => {
|
token::BINOP(token::STAR) => {
|
||||||
// Possibly "*self" or "*mut self" -- not supported. Try to avoid
|
// Possibly "*self" or "*mut self" -- not supported. Try to avoid
|
||||||
|
@ -3844,29 +3843,32 @@ impl<'a> Parser<'a> {
|
||||||
self.span_err(span, "cannot pass self by unsafe pointer");
|
self.span_err(span, "cannot pass self by unsafe pointer");
|
||||||
self.bump();
|
self.bump();
|
||||||
}
|
}
|
||||||
SelfValue
|
// error case, making bogus self ident:
|
||||||
|
SelfValue(special_idents::self_)
|
||||||
}
|
}
|
||||||
_ if Parser::token_is_mutability(&self.token) &&
|
_ if Parser::token_is_mutability(&self.token) &&
|
||||||
self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) => {
|
self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) => {
|
||||||
mutbl_self = self.parse_mutability();
|
mutbl_self = self.parse_mutability();
|
||||||
self.expect_self_ident();
|
SelfValue(self.expect_self_ident())
|
||||||
SelfValue
|
|
||||||
}
|
}
|
||||||
_ if Parser::token_is_mutability(&self.token) &&
|
_ if Parser::token_is_mutability(&self.token) &&
|
||||||
self.look_ahead(1, |t| *t == token::TILDE) &&
|
self.look_ahead(1, |t| *t == token::TILDE) &&
|
||||||
self.look_ahead(2, |t| token::is_keyword(keywords::Self, t)) => {
|
self.look_ahead(2, |t| token::is_keyword(keywords::Self, t)) => {
|
||||||
mutbl_self = self.parse_mutability();
|
mutbl_self = self.parse_mutability();
|
||||||
self.bump();
|
self.bump();
|
||||||
self.expect_self_ident();
|
SelfUniq(self.expect_self_ident())
|
||||||
SelfUniq
|
|
||||||
}
|
}
|
||||||
_ => SelfStatic
|
_ => SelfStatic
|
||||||
};
|
};
|
||||||
|
|
||||||
let explicit_self_sp = mk_sp(lo, self.span.hi);
|
let explicit_self_sp = mk_sp(lo, self.span.hi);
|
||||||
|
|
||||||
// If we parsed a self type, expect a comma before the argument list.
|
// shared fall-through for the three cases below. borrowing prevents simply
|
||||||
let fn_inputs = if explicit_self != SelfStatic {
|
// 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 {
|
match self.token {
|
||||||
token::COMMA => {
|
token::COMMA => {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
@ -3876,11 +3878,11 @@ impl<'a> Parser<'a> {
|
||||||
sep,
|
sep,
|
||||||
parse_arg_fn
|
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
|
fn_inputs
|
||||||
}
|
}
|
||||||
token::RPAREN => {
|
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();
|
let token_str = self.this_token_to_string();
|
||||||
|
@ -3888,11 +3890,21 @@ impl<'a> Parser<'a> {
|
||||||
token_str).as_slice())
|
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);
|
self.expect(&token::RPAREN);
|
||||||
|
|
||||||
let hi = self.span.hi;
|
let hi = self.span.hi;
|
||||||
|
|
|
@ -1967,13 +1967,13 @@ impl<'a> State<'a> {
|
||||||
try!(self.print_mutability(mutbl));
|
try!(self.print_mutability(mutbl));
|
||||||
match explicit_self {
|
match explicit_self {
|
||||||
ast::SelfStatic => { return Ok(false); }
|
ast::SelfStatic => { return Ok(false); }
|
||||||
ast::SelfValue => {
|
ast::SelfValue(_) => {
|
||||||
try!(word(&mut self.s, "self"));
|
try!(word(&mut self.s, "self"));
|
||||||
}
|
}
|
||||||
ast::SelfUniq => {
|
ast::SelfUniq(_) => {
|
||||||
try!(word(&mut self.s, "~self"));
|
try!(word(&mut self.s, "~self"));
|
||||||
}
|
}
|
||||||
ast::SelfRegion(ref lt, m) => {
|
ast::SelfRegion(ref lt, m, _) => {
|
||||||
try!(word(&mut self.s, "&"));
|
try!(word(&mut self.s, "&"));
|
||||||
try!(self.print_opt_lifetime(lt));
|
try!(self.print_opt_lifetime(lt));
|
||||||
try!(self.print_mutability(m));
|
try!(self.print_mutability(m));
|
||||||
|
|
|
@ -202,8 +202,8 @@ pub fn walk_explicit_self<E: Clone, V: Visitor<E>>(visitor: &mut V,
|
||||||
explicit_self: &ExplicitSelf,
|
explicit_self: &ExplicitSelf,
|
||||||
env: E) {
|
env: E) {
|
||||||
match explicit_self.node {
|
match explicit_self.node {
|
||||||
SelfStatic | SelfValue | SelfUniq => {}
|
SelfStatic | SelfValue(_) | SelfUniq(_) => {},
|
||||||
SelfRegion(ref lifetime, _) => {
|
SelfRegion(ref lifetime, _, _) => {
|
||||||
visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime, env)
|
visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime, env)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue