Skip to content

Made Self a keyword. #22158

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 14, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/librustc_trans/save/span_utils.rs
Original file line number Diff line number Diff line change
@@ -101,7 +101,7 @@ impl<'a> SpanUtils<'a> {
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);
}

@@ -124,7 +124,7 @@ impl<'a> SpanUtils<'a> {
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));
}

2 changes: 1 addition & 1 deletion src/libsyntax/ext/deriving/clone.rs
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ pub fn expand_deriving_clone<F>(cx: &mut ExtCtxt,
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)
2 changes: 1 addition & 1 deletion src/libsyntax/ext/deriving/decodable.rs
Original file line number Diff line number Diff line change
@@ -76,7 +76,7 @@ fn expand_deriving_decodable_imp<F>(cx: &mut ExtCtxt,
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
2 changes: 1 addition & 1 deletion src/libsyntax/ext/deriving/default.rs
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ pub fn expand_deriving_default<F>(cx: &mut ExtCtxt,
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)
8 changes: 4 additions & 4 deletions src/libsyntax/ext/deriving/generic/mod.rs
Original file line number Diff line number Diff line change
@@ -207,7 +207,7 @@ use parse::token::InternedString;
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;

@@ -261,7 +261,7 @@ pub struct Substructure<'a> {
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>],
@@ -679,10 +679,10 @@ impl<'a> MethodDef<'a> {
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))
}
_ => {
8 changes: 4 additions & 4 deletions src/libsyntax/ext/deriving/generic/ty.rs
Original file line number Diff line number Diff line change
@@ -87,7 +87,7 @@ impl<'a> Path<'a> {
/// 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
@@ -109,7 +109,7 @@ pub fn borrowed_explicit_self<'r>() -> Option<Option<PtrTy<'r>>> {
}

pub fn borrowed_self<'r>() -> Ty<'r> {
borrowed(box Self)
borrowed(box Self_)
}

pub fn nil_ty<'r>() -> Ty<'r> {
@@ -149,7 +149,7 @@ impl<'a> Ty<'a> {
}
}
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) => {
@@ -168,7 +168,7 @@ impl<'a> Ty<'a> {
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)
});
4 changes: 2 additions & 2 deletions src/libsyntax/ext/deriving/primitive.rs
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@ pub fn expand_deriving_from_primitive<F>(cx: &mut ExtCtxt,
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(),
@@ -56,7 +56,7 @@ pub fn expand_deriving_from_primitive<F>(cx: &mut ExtCtxt,
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,
2 changes: 1 addition & 1 deletion src/libsyntax/ext/deriving/rand.rs
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ pub fn expand_deriving_rand<F>(cx: &mut ExtCtxt,
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)
2 changes: 1 addition & 1 deletion src/libsyntax/parse/lexer/mod.rs
Original file line number Diff line number Diff line change
@@ -1122,7 +1122,7 @@ impl<'a> StringReader<'a> {
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 \
73 changes: 51 additions & 22 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
@@ -516,13 +516,21 @@ impl<'a> Parser<'a> {
}
}

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();
@@ -1797,7 +1805,7 @@ impl<'a> Parser<'a> {
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() {
@@ -1850,7 +1858,7 @@ impl<'a> Parser<'a> {
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) {
@@ -1895,7 +1903,7 @@ impl<'a> Parser<'a> {
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 {
@@ -2166,10 +2174,8 @@ impl<'a> Parser<'a> {
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();
@@ -3411,7 +3417,7 @@ impl<'a> Parser<'a> {
&& 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.
@@ -3532,15 +3538,17 @@ impl<'a> Parser<'a> {
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));
}
@@ -4380,6 +4388,27 @@ impl<'a> Parser<'a> {
}
}

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 `{}`",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's no test for this error message

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, this error message can not actually trigger right now, its just there because I copied the two parser functions for the self keyword.

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
@@ -4396,22 +4425,22 @@ impl<'a> Parser<'a> {
//
// 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();
@@ -4466,7 +4495,7 @@ impl<'a> Parser<'a> {
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();

9 changes: 7 additions & 2 deletions src/libsyntax/parse/token.rs
Original file line number Diff line number Diff line change
@@ -300,6 +300,7 @@ impl Token {
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
},
@@ -317,6 +318,7 @@ impl Token {
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
},
@@ -488,10 +490,12 @@ macro_rules! declare_special_idents_and_keywords {(
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
@@ -514,7 +518,7 @@ declare_special_idents_and_keywords! {
(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");
}

@@ -545,7 +549,8 @@ declare_special_idents_and_keywords! {
(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");
49 changes: 49 additions & 0 deletions src/test/compile-fail/self_type_keyword.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// 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`