Auto merge of #22158 - Kimundi:the_lonely_uppercase_keyword, r=pnkfelix
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
This commit is contained in:
commit
b63cee4a11
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -207,7 +207,7 @@
|
||||
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))
|
||||
}
|
||||
_ => {
|
||||
|
@ -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)
|
||||
});
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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 \
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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");
|
||||
|
49
src/test/compile-fail/self_type_keyword.rs
Normal file
49
src/test/compile-fail/self_type_keyword.rs
Normal file
@ -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`
|
Loading…
Reference in New Issue
Block a user