Auto merge of #59655 - Zoxc:symbols, r=petrochenkov
Use a proc macro to declare preallocated symbols r? @petrochenkov
This commit is contained in:
commit
fcf850f34a
@ -3387,6 +3387,7 @@ dependencies = [
|
||||
"arena 0.0.0",
|
||||
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_macros 0.1.0",
|
||||
"scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serialize 0.0.0",
|
||||
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -8,7 +8,7 @@ use crate::ty::TyCtxt;
|
||||
use crate::hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax::ast::{Attribute, MetaItem, MetaItemKind};
|
||||
use syntax_pos::Span;
|
||||
use syntax_pos::{Span, symbols};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
|
||||
use rustc_macros::HashStable;
|
||||
use errors::DiagnosticId;
|
||||
@ -51,12 +51,12 @@ impl<'a, 'tcx> LibFeatureCollector<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option<Symbol>, Span)> {
|
||||
let stab_attrs = vec!["stable", "unstable", "rustc_const_unstable"];
|
||||
let stab_attrs = [symbols::stable, symbols::unstable, symbols::rustc_const_unstable];
|
||||
|
||||
// Find a stability attribute (i.e., `#[stable (..)]`, `#[unstable (..)]`,
|
||||
// `#[rustc_const_unstable (..)]`).
|
||||
if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| {
|
||||
attr.check_name(stab_attr)
|
||||
attr.check_name(**stab_attr)
|
||||
}) {
|
||||
let meta_item = attr.meta();
|
||||
if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta_item {
|
||||
|
@ -599,7 +599,7 @@ impl<'a, 'tcx> FindAllAttrs<'a, 'tcx> {
|
||||
|
||||
fn is_active_attr(&mut self, attr: &Attribute) -> bool {
|
||||
for attr_name in &self.attr_names {
|
||||
if attr.check_name(attr_name) && check_config(self.tcx, attr) {
|
||||
if attr.check_name(*attr_name) && check_config(self.tcx, attr) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
|
||||
|
||||
let plugin_attributes = cx.sess().plugin_attributes.borrow_mut();
|
||||
for &(ref name, ty) in plugin_attributes.iter() {
|
||||
if ty == AttributeType::Whitelisted && attr.check_name(&name) {
|
||||
if ty == AttributeType::Whitelisted && attr.check_name(&**name) {
|
||||
debug!("{:?} (plugin attr) is whitelisted with ty {:?}", name, ty);
|
||||
break;
|
||||
}
|
||||
|
@ -9,10 +9,16 @@ use proc_macro::TokenStream;
|
||||
|
||||
mod hash_stable;
|
||||
mod query;
|
||||
mod symbols;
|
||||
|
||||
#[proc_macro]
|
||||
pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||
query::rustc_queries(input)
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn symbols(input: TokenStream) -> TokenStream {
|
||||
symbols::symbols(input)
|
||||
}
|
||||
|
||||
decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
|
||||
|
163
src/librustc_macros/src/symbols.rs
Normal file
163
src/librustc_macros/src/symbols.rs
Normal file
@ -0,0 +1,163 @@
|
||||
use proc_macro::TokenStream;
|
||||
use syn::{
|
||||
Token, Ident, LitStr,
|
||||
braced, parse_macro_input,
|
||||
};
|
||||
use syn::parse::{Result, Parse, ParseStream};
|
||||
use syn;
|
||||
use std::collections::HashSet;
|
||||
use quote::quote;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
mod kw {
|
||||
syn::custom_keyword!(Keywords);
|
||||
syn::custom_keyword!(Other);
|
||||
}
|
||||
|
||||
struct Keyword {
|
||||
name: Ident,
|
||||
value: LitStr,
|
||||
}
|
||||
|
||||
impl Parse for Keyword {
|
||||
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
||||
let name = input.parse()?;
|
||||
input.parse::<Token![:]>()?;
|
||||
let value = input.parse()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
|
||||
Ok(Keyword {
|
||||
name,
|
||||
value,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct Symbol(Ident);
|
||||
|
||||
impl Parse for Symbol {
|
||||
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
||||
let ident: Ident = input.parse()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
|
||||
Ok(Symbol(ident))
|
||||
}
|
||||
}
|
||||
|
||||
/// A type used to greedily parse another type until the input is empty.
|
||||
struct List<T>(Vec<T>);
|
||||
|
||||
impl<T: Parse> Parse for List<T> {
|
||||
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
||||
let mut list = Vec::new();
|
||||
while !input.is_empty() {
|
||||
list.push(input.parse()?);
|
||||
}
|
||||
Ok(List(list))
|
||||
}
|
||||
}
|
||||
|
||||
struct Input {
|
||||
keywords: List<Keyword>,
|
||||
symbols: List<Symbol>,
|
||||
}
|
||||
|
||||
impl Parse for Input {
|
||||
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
||||
input.parse::<kw::Keywords>()?;
|
||||
let content;
|
||||
braced!(content in input);
|
||||
let keywords = content.parse()?;
|
||||
|
||||
input.parse::<kw::Other>()?;
|
||||
let content;
|
||||
braced!(content in input);
|
||||
let symbols = content.parse()?;
|
||||
|
||||
Ok(Input {
|
||||
keywords,
|
||||
symbols,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn symbols(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as Input);
|
||||
|
||||
let mut keyword_stream = quote! {};
|
||||
let mut symbols_stream = quote! {};
|
||||
let mut prefill_stream = quote! {};
|
||||
let mut from_str_stream = quote! {};
|
||||
let mut counter = 0u32;
|
||||
let mut keys = HashSet::<String>::new();
|
||||
|
||||
let mut check_dup = |str: &str| {
|
||||
if !keys.insert(str.to_string()) {
|
||||
panic!("Symbol `{}` is duplicated", str);
|
||||
}
|
||||
};
|
||||
|
||||
for keyword in &input.keywords.0 {
|
||||
let name = &keyword.name;
|
||||
let value = &keyword.value;
|
||||
check_dup(&value.value());
|
||||
prefill_stream.extend(quote! {
|
||||
#value,
|
||||
});
|
||||
keyword_stream.extend(quote! {
|
||||
pub const #name: Keyword = Keyword {
|
||||
ident: Ident::with_empty_ctxt(super::Symbol::new(#counter))
|
||||
};
|
||||
});
|
||||
from_str_stream.extend(quote! {
|
||||
#value => Ok(#name),
|
||||
});
|
||||
counter += 1;
|
||||
}
|
||||
|
||||
for symbol in &input.symbols.0 {
|
||||
let value = &symbol.0;
|
||||
let value_str = value.to_string();
|
||||
check_dup(&value_str);
|
||||
prefill_stream.extend(quote! {
|
||||
#value_str,
|
||||
});
|
||||
symbols_stream.extend(quote! {
|
||||
pub const #value: Symbol = Symbol::new(#counter);
|
||||
});
|
||||
counter += 1;
|
||||
}
|
||||
|
||||
TokenStream::from(quote! {
|
||||
macro_rules! keywords {
|
||||
() => {
|
||||
#keyword_stream
|
||||
|
||||
impl std::str::FromStr for Keyword {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, ()> {
|
||||
match s {
|
||||
#from_str_stream
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! symbols {
|
||||
() => {
|
||||
#symbols_stream
|
||||
}
|
||||
}
|
||||
|
||||
impl Interner {
|
||||
pub fn fresh() -> Self {
|
||||
Interner::prefill(&[
|
||||
#prefill_stream
|
||||
])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
@ -68,6 +68,18 @@ pub struct Path {
|
||||
pub segments: Vec<PathSegment>,
|
||||
}
|
||||
|
||||
impl PartialEq<Symbol> for Path {
|
||||
fn eq(&self, symbol: &Symbol) -> bool {
|
||||
self.segments.len() == 1 && {
|
||||
let name = self.segments[0].ident.name;
|
||||
// Make sure these symbols are pure strings
|
||||
debug_assert!(!symbol.is_gensymed());
|
||||
debug_assert!(!name.is_gensymed());
|
||||
name == *symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<&'a str> for Path {
|
||||
fn eq(&self, string: &&'a str) -> bool {
|
||||
self.segments.len() == 1 && self.segments[0].ident.name == *string
|
||||
|
@ -81,7 +81,10 @@ impl NestedMetaItem {
|
||||
}
|
||||
|
||||
/// Returns `true` if this list item is a MetaItem with a name of `name`.
|
||||
pub fn check_name(&self, name: &str) -> bool {
|
||||
pub fn check_name<T>(&self, name: T) -> bool
|
||||
where
|
||||
Path: PartialEq<T>,
|
||||
{
|
||||
self.meta_item().map_or(false, |meta_item| meta_item.check_name(name))
|
||||
}
|
||||
|
||||
@ -151,7 +154,10 @@ impl Attribute {
|
||||
/// attribute is marked as used.
|
||||
///
|
||||
/// To check the attribute name without marking it used, use the `path` field directly.
|
||||
pub fn check_name(&self, name: &str) -> bool {
|
||||
pub fn check_name<T>(&self, name: T) -> bool
|
||||
where
|
||||
Path: PartialEq<T>,
|
||||
{
|
||||
let matches = self.path == name;
|
||||
if matches {
|
||||
mark_used(self);
|
||||
@ -244,7 +250,10 @@ impl MetaItem {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_name(&self, name: &str) -> bool {
|
||||
pub fn check_name<T>(&self, name: T) -> bool
|
||||
where
|
||||
Path: PartialEq<T>,
|
||||
{
|
||||
self.path == name
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ use crate::tokenstream::TokenTree;
|
||||
use errors::{DiagnosticBuilder, Handler};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use syntax_pos::{Span, DUMMY_SP, symbols};
|
||||
use log::debug;
|
||||
|
||||
use std::env;
|
||||
@ -1366,7 +1366,7 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
} else if n == "doc" {
|
||||
if let Some(content) = attr.meta_item_list() {
|
||||
if content.iter().any(|c| c.check_name("include")) {
|
||||
if content.iter().any(|c| c.check_name(symbols::include)) {
|
||||
gate_feature!(self, external_doc, attr.span,
|
||||
"#[doc(include = \"...\")] is experimental"
|
||||
);
|
||||
@ -1667,25 +1667,25 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
// check for gated attributes
|
||||
self.context.check_attribute(attr, false);
|
||||
|
||||
if attr.check_name("doc") {
|
||||
if attr.check_name(symbols::doc) {
|
||||
if let Some(content) = attr.meta_item_list() {
|
||||
if content.len() == 1 && content[0].check_name("cfg") {
|
||||
if content.len() == 1 && content[0].check_name(symbols::cfg) {
|
||||
gate_feature_post!(&self, doc_cfg, attr.span,
|
||||
"#[doc(cfg(...))] is experimental"
|
||||
);
|
||||
} else if content.iter().any(|c| c.check_name("masked")) {
|
||||
} else if content.iter().any(|c| c.check_name(symbols::masked)) {
|
||||
gate_feature_post!(&self, doc_masked, attr.span,
|
||||
"#[doc(masked)] is experimental"
|
||||
);
|
||||
} else if content.iter().any(|c| c.check_name("spotlight")) {
|
||||
} else if content.iter().any(|c| c.check_name(symbols::spotlight)) {
|
||||
gate_feature_post!(&self, doc_spotlight, attr.span,
|
||||
"#[doc(spotlight)] is experimental"
|
||||
);
|
||||
} else if content.iter().any(|c| c.check_name("alias")) {
|
||||
} else if content.iter().any(|c| c.check_name(symbols::alias)) {
|
||||
gate_feature_post!(&self, doc_alias, attr.span,
|
||||
"#[doc(alias = \"...\")] is experimental"
|
||||
);
|
||||
} else if content.iter().any(|c| c.check_name("keyword")) {
|
||||
} else if content.iter().any(|c| c.check_name(symbols::keyword)) {
|
||||
gate_feature_post!(&self, doc_keyword, attr.span,
|
||||
"#[doc(keyword = \"...\")] is experimental"
|
||||
);
|
||||
@ -1693,7 +1693,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
match BUILTIN_ATTRIBUTES.iter().find(|(name, ..)| attr.path == name) {
|
||||
match BUILTIN_ATTRIBUTES.iter().find(|(name, ..)| attr.path == *name) {
|
||||
Some(&(name, _, template, _)) => self.check_builtin_attribute(attr, name, template),
|
||||
None => if let Some(TokenTree::Token(_, token::Eq)) = attr.tokens.trees().next() {
|
||||
// All key-value attributes are restricted to meta-item syntax.
|
||||
@ -1748,7 +1748,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
ast::ItemKind::Struct(..) => {
|
||||
for attr in attr::filter_by_name(&i.attrs[..], "repr") {
|
||||
for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
|
||||
if item.check_name("simd") {
|
||||
if item.check_name(symbols::simd) {
|
||||
gate_feature_post!(&self, repr_simd, attr.span,
|
||||
"SIMD types are experimental and possibly buggy");
|
||||
}
|
||||
@ -1759,7 +1759,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
ast::ItemKind::Enum(..) => {
|
||||
for attr in attr::filter_by_name(&i.attrs[..], "repr") {
|
||||
for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
|
||||
if item.check_name("align") {
|
||||
if item.check_name(symbols::align) {
|
||||
gate_feature_post!(&self, repr_align_enum, attr.span,
|
||||
"`#[repr(align(x))]` on enums is experimental");
|
||||
}
|
||||
@ -2083,7 +2083,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
|
||||
// Process the edition umbrella feature-gates first, to ensure
|
||||
// `edition_enabled_features` is completed before it's queried.
|
||||
for attr in krate_attrs {
|
||||
if !attr.check_name("feature") {
|
||||
if !attr.check_name(symbols::feature) {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -2128,7 +2128,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
|
||||
}
|
||||
|
||||
for attr in krate_attrs {
|
||||
if !attr.check_name("feature") {
|
||||
if !attr.check_name(symbols::feature) {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -2258,7 +2258,7 @@ fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
|
||||
};
|
||||
if !allow_features {
|
||||
for attr in &krate.attrs {
|
||||
if attr.check_name("feature") {
|
||||
if attr.check_name(symbols::feature) {
|
||||
let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
|
||||
span_err!(span_handler, attr.span, E0554,
|
||||
"#![feature] may not be used on the {} release channel",
|
||||
|
@ -87,7 +87,7 @@ pub fn modify(sess: &ParseSess,
|
||||
}
|
||||
|
||||
pub fn is_proc_macro_attr(attr: &ast::Attribute) -> bool {
|
||||
PROC_MACRO_KINDS.iter().any(|kind| attr.check_name(kind))
|
||||
PROC_MACRO_KINDS.iter().any(|kind| attr.check_name(*kind))
|
||||
}
|
||||
|
||||
impl<'a> CollectProcMacros<'a> {
|
||||
|
@ -11,6 +11,7 @@ crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
serialize = { path = "../libserialize" }
|
||||
rustc_macros = { path = "../librustc_macros" }
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
arena = { path = "../libarena" }
|
||||
scoped-tls = "1.0"
|
||||
|
@ -16,6 +16,7 @@
|
||||
#![feature(non_exhaustive)]
|
||||
#![feature(optin_builtin_traits)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(proc_macro_hygiene)]
|
||||
#![feature(specialization)]
|
||||
#![feature(step_trait)]
|
||||
|
||||
@ -32,6 +33,7 @@ mod span_encoding;
|
||||
pub use span_encoding::{Span, DUMMY_SP};
|
||||
|
||||
pub mod symbol;
|
||||
pub use symbol::symbols;
|
||||
|
||||
mod analyze_source_file;
|
||||
|
||||
|
@ -6,6 +6,7 @@ use arena::DroplessArena;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc_data_structures::newtype_index;
|
||||
use rustc_macros::symbols;
|
||||
use serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||
|
||||
use std::fmt;
|
||||
@ -16,6 +17,94 @@ use std::hash::{Hash, Hasher};
|
||||
use crate::hygiene::SyntaxContext;
|
||||
use crate::{Span, DUMMY_SP, GLOBALS};
|
||||
|
||||
symbols! {
|
||||
// After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`,
|
||||
// this should be rarely necessary though if the keywords are kept in alphabetic order.
|
||||
Keywords {
|
||||
// Special reserved identifiers used internally for elided lifetimes,
|
||||
// unnamed method parameters, crate root module, error recovery etc.
|
||||
Invalid: "",
|
||||
PathRoot: "{{root}}",
|
||||
DollarCrate: "$crate",
|
||||
Underscore: "_",
|
||||
|
||||
// Keywords that are used in stable Rust.
|
||||
As: "as",
|
||||
Box: "box",
|
||||
Break: "break",
|
||||
Const: "const",
|
||||
Continue: "continue",
|
||||
Crate: "crate",
|
||||
Else: "else",
|
||||
Enum: "enum",
|
||||
Extern: "extern",
|
||||
False: "false",
|
||||
Fn: "fn",
|
||||
For: "for",
|
||||
If: "if",
|
||||
Impl: "impl",
|
||||
In: "in",
|
||||
Let: "let",
|
||||
Loop: "loop",
|
||||
Match: "match",
|
||||
Mod: "mod",
|
||||
Move: "move",
|
||||
Mut: "mut",
|
||||
Pub: "pub",
|
||||
Ref: "ref",
|
||||
Return: "return",
|
||||
SelfLower: "self",
|
||||
SelfUpper: "Self",
|
||||
Static: "static",
|
||||
Struct: "struct",
|
||||
Super: "super",
|
||||
Trait: "trait",
|
||||
True: "true",
|
||||
Type: "type",
|
||||
Unsafe: "unsafe",
|
||||
Use: "use",
|
||||
Where: "where",
|
||||
While: "while",
|
||||
|
||||
// Keywords that are used in unstable Rust or reserved for future use.
|
||||
Abstract: "abstract",
|
||||
Become: "become",
|
||||
Do: "do",
|
||||
Final: "final",
|
||||
Macro: "macro",
|
||||
Override: "override",
|
||||
Priv: "priv",
|
||||
Typeof: "typeof",
|
||||
Unsized: "unsized",
|
||||
Virtual: "virtual",
|
||||
Yield: "yield",
|
||||
|
||||
// Edition-specific keywords that are used in stable Rust.
|
||||
Dyn: "dyn", // >= 2018 Edition only
|
||||
|
||||
// Edition-specific keywords that are used in unstable Rust or reserved for future use.
|
||||
Async: "async", // >= 2018 Edition only
|
||||
Try: "try", // >= 2018 Edition only
|
||||
|
||||
// Special lifetime names
|
||||
UnderscoreLifetime: "'_",
|
||||
StaticLifetime: "'static",
|
||||
|
||||
// Weak keywords, have special meaning only in specific contexts.
|
||||
Auto: "auto",
|
||||
Catch: "catch",
|
||||
Default: "default",
|
||||
Existential: "existential",
|
||||
Union: "union",
|
||||
}
|
||||
|
||||
// Other symbols that can be referred to with syntax_pos::symbols::*
|
||||
Other {
|
||||
doc, cfg, masked, spotlight, alias, keyword, feature, include, simd, align, stable,
|
||||
unstable, rustc_const_unstable,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq)]
|
||||
pub struct Ident {
|
||||
pub name: Symbol,
|
||||
@ -317,129 +406,32 @@ impl Interner {
|
||||
}
|
||||
}
|
||||
|
||||
// In this macro, there is the requirement that the name (the number) must be monotonically
|
||||
// increasing by one in the special identifiers, starting at 0; the same holds for the keywords,
|
||||
// except starting from the next number instead of zero.
|
||||
macro_rules! declare_keywords {(
|
||||
$( ($index: expr, $konst: ident, $string: expr) )*
|
||||
) => {
|
||||
pub mod keywords {
|
||||
use super::{Symbol, Ident};
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Keyword {
|
||||
ident: Ident,
|
||||
}
|
||||
impl Keyword {
|
||||
#[inline] pub fn ident(self) -> Ident { self.ident }
|
||||
#[inline] pub fn name(self) -> Symbol { self.ident.name }
|
||||
}
|
||||
$(
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const $konst: Keyword = Keyword {
|
||||
ident: Ident::with_empty_ctxt(super::Symbol::new($index))
|
||||
};
|
||||
)*
|
||||
pub mod keywords {
|
||||
use super::{Symbol, Ident};
|
||||
|
||||
impl std::str::FromStr for Keyword {
|
||||
type Err = ();
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Keyword {
|
||||
ident: Ident,
|
||||
}
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, ()> {
|
||||
match s {
|
||||
$($string => Ok($konst),)*
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
impl Keyword {
|
||||
#[inline]
|
||||
pub fn ident(self) -> Ident {
|
||||
self.ident
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn name(self) -> Symbol {
|
||||
self.ident.name
|
||||
}
|
||||
}
|
||||
|
||||
impl Interner {
|
||||
pub fn fresh() -> Self {
|
||||
Interner::prefill(&[$($string,)*])
|
||||
}
|
||||
}
|
||||
}}
|
||||
keywords!();
|
||||
}
|
||||
|
||||
// N.B., 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
|
||||
// of the reserved words, and thus tagged as "reserved".
|
||||
// After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`,
|
||||
// this should be rarely necessary though if the keywords are kept in alphabetic order.
|
||||
declare_keywords! {
|
||||
// Special reserved identifiers used internally for elided lifetimes,
|
||||
// unnamed method parameters, crate root module, error recovery etc.
|
||||
(0, Invalid, "")
|
||||
(1, PathRoot, "{{root}}")
|
||||
(2, DollarCrate, "$crate")
|
||||
(3, Underscore, "_")
|
||||
|
||||
// Keywords that are used in stable Rust.
|
||||
(4, As, "as")
|
||||
(5, Box, "box")
|
||||
(6, Break, "break")
|
||||
(7, Const, "const")
|
||||
(8, Continue, "continue")
|
||||
(9, Crate, "crate")
|
||||
(10, Else, "else")
|
||||
(11, Enum, "enum")
|
||||
(12, Extern, "extern")
|
||||
(13, False, "false")
|
||||
(14, Fn, "fn")
|
||||
(15, For, "for")
|
||||
(16, If, "if")
|
||||
(17, Impl, "impl")
|
||||
(18, In, "in")
|
||||
(19, Let, "let")
|
||||
(20, Loop, "loop")
|
||||
(21, Match, "match")
|
||||
(22, Mod, "mod")
|
||||
(23, Move, "move")
|
||||
(24, Mut, "mut")
|
||||
(25, Pub, "pub")
|
||||
(26, Ref, "ref")
|
||||
(27, Return, "return")
|
||||
(28, SelfLower, "self")
|
||||
(29, SelfUpper, "Self")
|
||||
(30, Static, "static")
|
||||
(31, Struct, "struct")
|
||||
(32, Super, "super")
|
||||
(33, Trait, "trait")
|
||||
(34, True, "true")
|
||||
(35, Type, "type")
|
||||
(36, Unsafe, "unsafe")
|
||||
(37, Use, "use")
|
||||
(38, Where, "where")
|
||||
(39, While, "while")
|
||||
|
||||
// Keywords that are used in unstable Rust or reserved for future use.
|
||||
(40, Abstract, "abstract")
|
||||
(41, Become, "become")
|
||||
(42, Do, "do")
|
||||
(43, Final, "final")
|
||||
(44, Macro, "macro")
|
||||
(45, Override, "override")
|
||||
(46, Priv, "priv")
|
||||
(47, Typeof, "typeof")
|
||||
(48, Unsized, "unsized")
|
||||
(49, Virtual, "virtual")
|
||||
(50, Yield, "yield")
|
||||
|
||||
// Edition-specific keywords that are used in stable Rust.
|
||||
(51, Dyn, "dyn") // >= 2018 Edition only
|
||||
|
||||
// Edition-specific keywords that are used in unstable Rust or reserved for future use.
|
||||
(52, Async, "async") // >= 2018 Edition only
|
||||
(53, Try, "try") // >= 2018 Edition only
|
||||
|
||||
// Special lifetime names
|
||||
(54, UnderscoreLifetime, "'_")
|
||||
(55, StaticLifetime, "'static")
|
||||
|
||||
// Weak keywords, have special meaning only in specific contexts.
|
||||
(56, Auto, "auto")
|
||||
(57, Catch, "catch")
|
||||
(58, Default, "default")
|
||||
(59, Existential, "existential")
|
||||
(60, Union, "union")
|
||||
pub mod symbols {
|
||||
use super::Symbol;
|
||||
symbols!();
|
||||
}
|
||||
|
||||
impl Symbol {
|
||||
|
Loading…
x
Reference in New Issue
Block a user