]> git.lizzy.rs Git - rust.git/commitdiff
Made `Self` a keyword.
authorMarvin Löbel <loebel.marvin@gmail.com>
Tue, 10 Feb 2015 13:55:45 +0000 (14:55 +0100)
committerMarvin Löbel <loebel.marvin@gmail.com>
Thu, 12 Feb 2015 21:04:31 +0000 (22:04 +0100)
It is only allowed in paths now, where it will either work inside a `trait`
or `impl` item, or not resolve outside of it.

[breaking-change]

Closes #22137

12 files changed:
src/librustc_trans/save/span_utils.rs
src/libsyntax/ext/deriving/clone.rs
src/libsyntax/ext/deriving/decodable.rs
src/libsyntax/ext/deriving/default.rs
src/libsyntax/ext/deriving/generic/mod.rs
src/libsyntax/ext/deriving/generic/ty.rs
src/libsyntax/ext/deriving/primitive.rs
src/libsyntax/ext/deriving/rand.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/test/compile-fail/self_type_keyword.rs [new file with mode: 0644]

index a724cdc0229d2f465af8865f8cd1ae42951dda33..223d46e4e4a93ebbb902c7f1d49fecfa031b77b6 100644 (file)
@@ -101,7 +101,7 @@ pub fn span_for_last_ident(&self, span: Span) -> Option<Span> {
                 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 @@ pub fn span_for_first_ident(&self, span: Span) -> Option<Span> {
                 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));
             }
 
index 9f009ad4d7869ed6e6721eb46bb70b8730fe8c90..518fbcc80ee95fc8c4b248b55da91c9bc8be585e 100644 (file)
@@ -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)
index f003a3453e15e578ba88034727b75d4c5654a593..ab0f64e823f9c197427ee0c27d2725da419b7551 100644 (file)
@@ -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
index 9b76f4b1658f0d47edfb82fadaaf0a32a8c4f735..c10975a2d32eb94e370aa0271267a472b6e5048a 100644 (file)
@@ -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)
index d9242417e047511fc4cd982a4869e01d86f75a48..f878cb5ca8b78ff74377b6817bf6311a392b7885 100644 (file)
 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 @@ fn split_self_nonself_args(&self,
             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))
                 }
                 _ => {
index bbca5c599b1c1199d12695cf1bcea9a61954ebb7..ec13b86a8ae2eb0fff69558347e72486d617ad62 100644 (file)
@@ -87,7 +87,7 @@ pub fn to_path(&self,
 /// 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 @@ pub fn to_ty(&self,
                 }
             }
             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 @@ pub fn to_path(&self,
                    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)
                 });
index bf742263c6d8774561efae0158c53a59db5755fb..22c87d978c9e5aa2771d3971e71b2c155693527a 100644 (file)
@@ -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,
index 4c3678d9572da8a91e80a9154c155d2357f2f6a4..029b65351081967166e2793c802ce152d16c8bab 100644 (file)
@@ -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)
index ecc39925a40c55b495c459b032279c178a05d3a6..1a4afa4957c5a61e1322fbc253a143e19324c1af 100644 (file)
@@ -1122,7 +1122,7 @@ fn next_token_inner(&mut self) -> token::Token {
                 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 \
index fd2f0685cab8386d3bf6cf59cd176547f869fdee..d2133f033356751b47b97d9a21fc47300a11632a 100644 (file)
@@ -516,13 +516,21 @@ pub fn parse_ident(&mut self) -> ast::Ident {
         }
     }
 
+    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 @@ pub fn parse_path_segments_without_colons(&mut self) -> Vec<ast::PathSegment> {
         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 @@ pub fn parse_path_segments_with_colons(&mut self) -> Vec<ast::PathSegment> {
         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 @@ pub fn parse_path_segments_without_types(&mut self) -> Vec<ast::PathSegment> {
         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 @@ pub fn parse_bottom_expr(&mut self) -> P<Expr> {
             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 @@ pub fn parse_pat(&mut self) -> P<Pat> {
               && 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 @@ pub fn parse_pat(&mut self) -> P<Pat> {
                                   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 @@ fn expect_self_ident(&mut self) -> ast::Ident {
         }
     }
 
+    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
@@ -4396,22 +4425,22 @@ fn maybe_parse_borrowed_explicit_self(this: &mut Parser)
             //
             // 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 @@ fn maybe_parse_borrowed_explicit_self(this: &mut Parser)
                         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();
 
index 45f4f044ea4d1ff7502cecf0fbed90c9e880eb6a..5e67b7cf1f38aee96535b216cac5c3ae1a4f76bf 100644 (file)
@@ -300,6 +300,7 @@ pub fn is_any_keyword(&self) -> bool {
                    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 @@ pub fn is_strict_keyword(&self) -> bool {
                    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 @@ fn mk_fresh_ident_interner() -> IdentInterner {
 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 @@ pub mod special_idents {
         (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 @@ pub mod 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");
diff --git a/src/test/compile-fail/self_type_keyword.rs b/src/test/compile-fail/self_type_keyword.rs
new file mode 100644 (file)
index 0000000..6f5aeea
--- /dev/null
@@ -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`