return self.make_sub_span(span, result)
}
if bracket_count == 0 &&
- (ts.tok.is_ident() || ts.tok.is_keyword(keywords::Self)) {
+ (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) {
result = Some(ts.sp);
}
return None;
}
if bracket_count == 0 &&
- (ts.tok.is_ident() || ts.tok.is_keyword(keywords::Self)) {
+ (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) {
return self.make_sub_span(span, Some(ts.sp));
}
generics: LifetimeBounds::empty(),
explicit_self: borrowed_explicit_self(),
args: Vec::new(),
- ret_ty: Self,
+ ret_ty: Self_,
attributes: attrs,
combine_substructure: combine_substructure(box |c, s, sub| {
cs_clone("Clone", c, s, sub)
ret_ty: Literal(Path::new_(
pathvec_std!(cx, core::result::Result),
None,
- vec!(box Self, box Literal(Path::new_(
+ vec!(box Self_, box Literal(Path::new_(
vec!["__D", "Error"], None, vec![], false
))),
true
generics: LifetimeBounds::empty(),
explicit_self: None,
args: Vec::new(),
- ret_ty: Self,
+ ret_ty: Self_,
attributes: attrs,
combine_substructure: combine_substructure(box |a, b, c| {
default_substructure(a, b, c)
use parse::token::special_idents;
use ptr::P;
-use self::ty::{LifetimeBounds, Path, Ptr, PtrTy, Self, Ty};
+use self::ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty};
pub mod ty;
pub type_ident: Ident,
/// ident of the method
pub method_ident: Ident,
- /// dereferenced access to any `Self` or `Ptr(Self, _)` arguments
+ /// dereferenced access to any `Self_` or `Ptr(Self_, _)` arguments
pub self_args: &'a [P<Expr>],
/// verbatim access to any other arguments
pub nonself_args: &'a [P<Expr>],
match *ty {
// for static methods, just treat any Self
// arguments as a normal arg
- Self if nonstatic => {
+ Self_ if nonstatic => {
self_args.push(arg_expr);
}
- Ptr(box Self, _) if nonstatic => {
+ Ptr(box Self_, _) if nonstatic => {
self_args.push(cx.expr_deref(trait_.span, arg_expr))
}
_ => {
/// A type. Supports pointers, Self, and literals
#[derive(Clone)]
pub enum Ty<'a> {
- Self,
+ Self_,
/// &/Box/ Ty
Ptr(Box<Ty<'a>>, PtrTy<'a>),
/// mod::mod::Type<[lifetime], [Params...]>, including a plain type
}
pub fn borrowed_self<'r>() -> Ty<'r> {
- borrowed(box Self)
+ borrowed(box Self_)
}
pub fn nil_ty<'r>() -> Ty<'r> {
}
}
Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) }
- Self => {
+ Self_ => {
cx.ty_path(self.to_path(cx, span, self_ty, self_generics))
}
Tuple(ref fields) => {
self_generics: &Generics)
-> ast::Path {
match *self {
- Self => {
+ Self_ => {
let self_params = self_generics.ty_params.map(|ty_param| {
cx.ty_ident(span, ty_param.ident)
});
args: vec!(Literal(path!(i64))),
ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option),
None,
- vec!(box Self),
+ vec!(box Self_),
true)),
// #[inline] liable to cause code-bloat
attributes: attrs.clone(),
args: vec!(Literal(path!(u64))),
ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option),
None,
- vec!(box Self),
+ vec!(box Self_),
true)),
// #[inline] liable to cause code-bloat
attributes: attrs,
Ptr(box Literal(Path::new_local("R")),
Borrowed(None, ast::MutMutable))
),
- ret_ty: Self,
+ ret_ty: Self_,
attributes: Vec::new(),
combine_substructure: combine_substructure(box |a, b, c| {
rand_substructure(a, b, c)
let keyword_checking_token =
&token::Ident(keyword_checking_ident, token::Plain);
let last_bpos = self.last_pos;
- if keyword_checking_token.is_keyword(token::keywords::Self) {
+ if keyword_checking_token.is_keyword(token::keywords::SelfValue) {
self.err_span_(start,
last_bpos,
"invalid lifetime name: 'self \
}
}
+ pub fn parse_ident_or_self_type(&mut self) -> ast::Ident {
+ if self.is_self_type_ident() {
+ self.expect_self_type_ident()
+ } else {
+ self.parse_ident()
+ }
+ }
+
pub fn parse_path_list_item(&mut self) -> ast::PathListItem {
let lo = self.span.lo;
let node = if self.eat_keyword_noexpect(keywords::Mod) {
let span = self.last_span;
self.span_warn(span, "deprecated syntax; use the `self` keyword now");
ast::PathListMod { id: ast::DUMMY_NODE_ID }
- } else if self.eat_keyword(keywords::Self) {
+ } else if self.eat_keyword(keywords::SelfValue) {
ast::PathListMod { id: ast::DUMMY_NODE_ID }
} else {
let ident = self.parse_ident();
let mut segments = Vec::new();
loop {
// First, parse an identifier.
- let identifier = self.parse_ident();
+ let identifier = self.parse_ident_or_self_type();
// Parse types, optionally.
let parameters = if self.eat_lt() {
let mut segments = Vec::new();
loop {
// First, parse an identifier.
- let identifier = self.parse_ident();
+ let identifier = self.parse_ident_or_self_type();
// If we do not see a `::`, stop.
if !self.eat(&token::ModSep) {
let mut segments = Vec::new();
loop {
// First, parse an identifier.
- let identifier = self.parse_ident();
+ let identifier = self.parse_ident_or_self_type();
// Assemble and push the result.
segments.push(ast::PathSegment {
token::BinOp(token::Or) | token::OrOr => {
return self.parse_lambda_expr(CaptureByRef);
},
- // FIXME #13626: Should be able to stick in
- // token::SELF_KEYWORD_NAME
token::Ident(id @ ast::Ident {
- name: ast::Name(token::SELF_KEYWORD_NAME_NUM),
+ name: token::SELF_KEYWORD_NAME,
ctxt: _
}, token::Plain) => {
self.bump();
&& self.token != token::ModSep)
|| self.token.is_keyword(keywords::True)
|| self.token.is_keyword(keywords::False) {
- // Parse an expression pattern or exp .. exp.
+ // Parse an expression pattern or exp ... exp.
//
// These expressions are limited to literals (possibly
// preceded by unary-minus) or identifiers.
enum_path.segments.len() == 1 &&
enum_path.segments[0].parameters.is_empty()
{
- // it could still be either an enum
- // or an identifier pattern, resolve
- // will sort it out:
- pat = PatIdent(BindByValue(MutImmutable),
- codemap::Spanned{
- span: enum_path.span,
- node: enum_path.segments[0]
- .identifier},
- None);
+ // NB: If enum_path is a single identifier,
+ // this should not be reachable due to special
+ // handling further above.
+ //
+ // However, previously a PatIdent got emitted
+ // here, so we preserve the branch just in case.
+ //
+ // A rewrite of the logic in this function
+ // would probably make this obvious.
+ self.span_bug(enum_path.span,
+ "ident only path should have been covered already");
} else {
pat = PatEnum(enum_path, Some(args));
}
}
}
+ fn is_self_type_ident(&mut self) -> bool {
+ match self.token {
+ token::Ident(id, token::Plain) => id.name == special_idents::type_self.name,
+ _ => false
+ }
+ }
+
+ fn expect_self_type_ident(&mut self) -> ast::Ident {
+ match self.token {
+ token::Ident(id, token::Plain) if id.name == special_idents::type_self.name => {
+ self.bump();
+ id
+ },
+ _ => {
+ let token_str = self.this_token_to_string();
+ self.fatal(&format!("expected `Self`, found `{}`",
+ token_str)[])
+ }
+ }
+ }
+
/// Parse the argument list and result type of a function
/// that may have a self type.
fn parse_fn_decl_with_self<F>(&mut self, parse_arg_fn: F) -> (ExplicitSelf, P<FnDecl>) where
//
// We already know that the current token is `&`.
- if this.look_ahead(1, |t| t.is_keyword(keywords::Self)) {
+ if this.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) {
this.bump();
SelfRegion(None, MutImmutable, this.expect_self_ident())
} else if this.look_ahead(1, |t| t.is_mutability()) &&
- this.look_ahead(2, |t| t.is_keyword(keywords::Self)) {
+ this.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) {
this.bump();
let mutability = this.parse_mutability();
SelfRegion(None, mutability, this.expect_self_ident())
} else if this.look_ahead(1, |t| t.is_lifetime()) &&
- this.look_ahead(2, |t| t.is_keyword(keywords::Self)) {
+ this.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) {
this.bump();
let lifetime = this.parse_lifetime();
SelfRegion(Some(lifetime), MutImmutable, this.expect_self_ident())
} else if this.look_ahead(1, |t| t.is_lifetime()) &&
this.look_ahead(2, |t| t.is_mutability()) &&
- this.look_ahead(3, |t| t.is_keyword(keywords::Self)) {
+ this.look_ahead(3, |t| t.is_keyword(keywords::SelfValue)) {
this.bump();
let lifetime = this.parse_lifetime();
let mutability = this.parse_mutability();
SelfValue(self_ident)
}
} else if self.token.is_mutability() &&
- self.look_ahead(1, |t| t.is_keyword(keywords::Self)) {
+ self.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) {
mutbl_self = self.parse_mutability();
let self_ident = self.expect_self_ident();
n == SELF_KEYWORD_NAME
|| n == STATIC_KEYWORD_NAME
|| n == SUPER_KEYWORD_NAME
+ || n == SELF_TYPE_KEYWORD_NAME
|| STRICT_KEYWORD_START <= n
&& n <= RESERVED_KEYWORD_FINAL
},
n == SELF_KEYWORD_NAME
|| n == STATIC_KEYWORD_NAME
|| n == SUPER_KEYWORD_NAME
+ || n == SELF_TYPE_KEYWORD_NAME
|| STRICT_KEYWORD_START <= n
&& n <= STRICT_KEYWORD_FINAL
},
pub const SELF_KEYWORD_NAME: ast::Name = ast::Name(SELF_KEYWORD_NAME_NUM);
const STATIC_KEYWORD_NAME: ast::Name = ast::Name(STATIC_KEYWORD_NAME_NUM);
const SUPER_KEYWORD_NAME: ast::Name = ast::Name(SUPER_KEYWORD_NAME_NUM);
+const SELF_TYPE_KEYWORD_NAME: ast::Name = ast::Name(SELF_TYPE_KEYWORD_NAME_NUM);
pub const SELF_KEYWORD_NAME_NUM: u32 = 1;
const STATIC_KEYWORD_NAME_NUM: u32 = 2;
const SUPER_KEYWORD_NAME_NUM: u32 = 3;
+const SELF_TYPE_KEYWORD_NAME_NUM: u32 = 10;
// NB: leaving holes in the ident table is bad! a different ident will get
// interned with the id from the hole, but it will be between the min and max
(7, clownshoe_abi, "__rust_abi");
(8, opaque, "<opaque>");
(9, unnamed_field, "<unnamed_field>");
- (10, type_self, "Self");
+ (super::SELF_TYPE_KEYWORD_NAME_NUM, type_self, "Self");
(11, prelude_import, "prelude_import");
}
(32, Return, "return");
// Static and Self are also special idents (prefill de-dupes)
(super::STATIC_KEYWORD_NAME_NUM, Static, "static");
- (super::SELF_KEYWORD_NAME_NUM, Self, "self");
+ (super::SELF_KEYWORD_NAME_NUM, SelfValue, "self");
+ (super::SELF_TYPE_KEYWORD_NAME_NUM, SelfType, "Self");
(33, Struct, "struct");
(super::SUPER_KEYWORD_NAME_NUM, Super, "super");
(34, True, "true");
--- /dev/null
+// Copyright 2015 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 Self;
+//~^ ERROR expected identifier, found keyword `Self`
+
+struct Bar<'Self>;
+//~^ ERROR invalid lifetime name
+
+pub fn main() {
+ let Self = 5;
+ //~^ ERROR expected identifier, found keyword `Self`
+
+ match 15 {
+ Self => (),
+ //~^ ERROR expected identifier, found keyword `Self`
+ ref Self => (),
+ //~^ ERROR expected identifier, found keyword `Self`
+ mut Self => (),
+ //~^ ERROR expected identifier, found keyword `Self`
+ ref mut Self => (),
+ //~^ ERROR expected identifier, found keyword `Self`
+ Self!() => (),
+ //~^ ERROR expected identifier, found keyword `Self`
+ Foo { x: Self } => (),
+ //~^ ERROR expected identifier, found keyword `Self`
+ Foo { Self } => (),
+ //~^ ERROR expected identifier, found keyword `Self`
+ }
+}
+
+use self::Self as Foo;
+//~^ ERROR expected identifier, found keyword `Self`
+
+use std::option::Option as Self;
+//~^ ERROR expected identifier, found keyword `Self`
+
+extern crate Self;
+//~^ ERROR expected identifier, found keyword `Self`
+
+trait Self {}
+//~^ ERROR expected identifier, found keyword `Self`