Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
//! Proc macro which builds the Symbol table
|
|
|
|
//!
|
|
|
|
//! # Debugging
|
|
|
|
//!
|
|
|
|
//! Since this proc-macro does some non-trivial work, debugging it is important.
|
|
|
|
//! This proc-macro can be invoked as an ordinary unit test, like so:
|
|
|
|
//!
|
|
|
|
//! ```bash
|
|
|
|
//! cd compiler/rustc_macros
|
|
|
|
//! cargo test symbols::test_symbols -- --nocapture
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! This unit test finds the `symbols!` invocation in `compiler/rustc_span/src/symbol.rs`
|
|
|
|
//! and runs it. It verifies that the output token stream can be parsed as valid module
|
|
|
|
//! items and that no errors were produced.
|
|
|
|
//!
|
|
|
|
//! You can also view the generated code by using `cargo expand`:
|
|
|
|
//!
|
|
|
|
//! ```bash
|
|
|
|
//! cargo install cargo-expand # this is necessary only once
|
|
|
|
//! cd compiler/rustc_span
|
2023-11-08 22:30:22 +00:00
|
|
|
//! # The specific version number in CFG_RELEASE doesn't matter.
|
|
|
|
//! # The output is large.
|
|
|
|
//! CFG_RELEASE="0.0.0" cargo +nightly expand > /tmp/rustc_span.rs
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
//! ```
|
|
|
|
|
|
|
|
use proc_macro2::{Span, TokenStream};
|
2019-04-03 00:43:49 +00:00
|
|
|
use quote::quote;
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
use std::collections::HashMap;
|
2019-04-03 00:43:49 +00:00
|
|
|
use syn::parse::{Parse, ParseStream, Result};
|
2023-10-25 20:52:38 +00:00
|
|
|
use syn::{braced, punctuated::Punctuated, Expr, Ident, Lit, LitStr, Macro, Token};
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests;
|
2019-04-03 00:43:49 +00:00
|
|
|
|
|
|
|
mod kw {
|
|
|
|
syn::custom_keyword!(Keywords);
|
2019-05-06 23:55:12 +00:00
|
|
|
syn::custom_keyword!(Symbols);
|
2019-04-03 00:43:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct Keyword {
|
|
|
|
name: Ident,
|
|
|
|
value: LitStr,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Parse for Keyword {
|
|
|
|
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
|
|
|
let name = input.parse()?;
|
2019-04-09 07:39:48 +00:00
|
|
|
input.parse::<Token![:]>()?;
|
2019-04-03 00:43:49 +00:00
|
|
|
let value = input.parse()?;
|
|
|
|
|
|
|
|
Ok(Keyword { name, value })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-06 23:55:12 +00:00
|
|
|
struct Symbol {
|
|
|
|
name: Ident,
|
2023-10-25 18:12:32 +00:00
|
|
|
value: Value,
|
|
|
|
}
|
|
|
|
|
|
|
|
enum Value {
|
|
|
|
SameAsName,
|
|
|
|
String(LitStr),
|
2023-10-25 20:52:38 +00:00
|
|
|
Env(LitStr, Macro),
|
2023-10-25 20:46:59 +00:00
|
|
|
Unsupported(Expr),
|
2019-05-06 23:55:12 +00:00
|
|
|
}
|
2019-04-03 00:43:49 +00:00
|
|
|
|
|
|
|
impl Parse for Symbol {
|
|
|
|
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
2019-05-06 23:55:12 +00:00
|
|
|
let name = input.parse()?;
|
2023-10-25 18:10:21 +00:00
|
|
|
let colon_token: Option<Token![:]> = input.parse()?;
|
2023-10-25 18:15:18 +00:00
|
|
|
let value = if colon_token.is_some() { input.parse()? } else { Value::SameAsName };
|
2019-04-03 00:43:49 +00:00
|
|
|
|
2019-05-06 23:55:12 +00:00
|
|
|
Ok(Symbol { name, value })
|
2019-04-03 00:43:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-25 18:15:18 +00:00
|
|
|
impl Parse for Value {
|
|
|
|
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
2023-10-25 18:20:07 +00:00
|
|
|
let expr: Expr = input.parse()?;
|
|
|
|
match &expr {
|
|
|
|
Expr::Lit(expr) => {
|
|
|
|
if let Lit::Str(lit) = &expr.lit {
|
|
|
|
return Ok(Value::String(lit.clone()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Expr::Macro(expr) => {
|
2023-11-13 13:24:55 +00:00
|
|
|
if expr.mac.path.is_ident("env")
|
|
|
|
&& let Ok(lit) = expr.mac.parse_body()
|
|
|
|
{
|
2023-10-25 20:52:38 +00:00
|
|
|
return Ok(Value::Env(lit, expr.mac.clone()));
|
2023-10-25 18:20:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2023-10-25 20:46:59 +00:00
|
|
|
Ok(Value::Unsupported(expr))
|
2023-10-25 18:15:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-03 00:43:49 +00:00
|
|
|
struct Input {
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
keywords: Punctuated<Keyword, Token![,]>,
|
|
|
|
symbols: Punctuated<Symbol, Token![,]>,
|
2019-04-03 00:43:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Parse for Input {
|
|
|
|
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
|
|
|
input.parse::<kw::Keywords>()?;
|
|
|
|
let content;
|
|
|
|
braced!(content in input);
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
let keywords = Punctuated::parse_terminated(&content)?;
|
2019-04-03 00:43:49 +00:00
|
|
|
|
2019-05-06 23:55:12 +00:00
|
|
|
input.parse::<kw::Symbols>()?;
|
2019-04-03 00:43:49 +00:00
|
|
|
let content;
|
|
|
|
braced!(content in input);
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
let symbols = Punctuated::parse_terminated(&content)?;
|
2019-04-03 00:43:49 +00:00
|
|
|
|
|
|
|
Ok(Input { keywords, symbols })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
#[derive(Default)]
|
|
|
|
struct Errors {
|
|
|
|
list: Vec<syn::Error>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Errors {
|
|
|
|
fn error(&mut self, span: Span, message: String) {
|
|
|
|
self.list.push(syn::Error::new(span, message));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-03 00:43:49 +00:00
|
|
|
pub fn symbols(input: TokenStream) -> TokenStream {
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
let (mut output, errors) = symbols_with_errors(input);
|
|
|
|
|
|
|
|
// If we generated any errors, then report them as compiler_error!() macro calls.
|
|
|
|
// This lets the errors point back to the most relevant span. It also allows us
|
|
|
|
// to report as many errors as we can during a single run.
|
|
|
|
output.extend(errors.into_iter().map(|e| e.to_compile_error()));
|
|
|
|
|
|
|
|
output
|
|
|
|
}
|
|
|
|
|
2023-10-25 20:20:47 +00:00
|
|
|
struct Preinterned {
|
|
|
|
idx: u32,
|
|
|
|
span_of_name: Span,
|
|
|
|
}
|
|
|
|
|
2023-10-25 20:42:58 +00:00
|
|
|
struct Entries {
|
|
|
|
map: HashMap<String, Preinterned>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Entries {
|
|
|
|
fn with_capacity(capacity: usize) -> Self {
|
|
|
|
Entries { map: HashMap::with_capacity(capacity) }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn insert(&mut self, span: Span, str: &str, errors: &mut Errors) -> u32 {
|
|
|
|
if let Some(prev) = self.map.get(str) {
|
|
|
|
errors.error(span, format!("Symbol `{str}` is duplicated"));
|
|
|
|
errors.error(prev.span_of_name, "location of previous definition".to_string());
|
|
|
|
prev.idx
|
|
|
|
} else {
|
|
|
|
let idx = self.len();
|
|
|
|
self.map.insert(str.to_string(), Preinterned { idx, span_of_name: span });
|
|
|
|
idx
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn len(&self) -> u32 {
|
|
|
|
u32::try_from(self.map.len()).expect("way too many symbols")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) {
|
|
|
|
let mut errors = Errors::default();
|
|
|
|
|
|
|
|
let input: Input = match syn::parse2(input) {
|
|
|
|
Ok(input) => input,
|
|
|
|
Err(e) => {
|
|
|
|
// This allows us to display errors at the proper span, while minimizing
|
|
|
|
// unrelated errors caused by bailing out (and not generating code).
|
|
|
|
errors.list.push(e);
|
|
|
|
Input { keywords: Default::default(), symbols: Default::default() }
|
|
|
|
}
|
|
|
|
};
|
2019-04-03 00:43:49 +00:00
|
|
|
|
|
|
|
let mut keyword_stream = quote! {};
|
|
|
|
let mut symbols_stream = quote! {};
|
|
|
|
let mut prefill_stream = quote! {};
|
2023-10-25 20:42:58 +00:00
|
|
|
let mut entries = Entries::with_capacity(input.keywords.len() + input.symbols.len() + 10);
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
let mut prev_key: Option<(Span, String)> = None;
|
|
|
|
|
|
|
|
let mut check_order = |span: Span, str: &str, errors: &mut Errors| {
|
|
|
|
if let Some((prev_span, ref prev_str)) = prev_key {
|
2020-07-09 23:46:38 +00:00
|
|
|
if str < prev_str {
|
2022-12-19 09:31:55 +00:00
|
|
|
errors.error(span, format!("Symbol `{str}` must precede `{prev_str}`"));
|
|
|
|
errors.error(prev_span, format!("location of previous symbol `{prev_str}`"));
|
2020-07-09 23:46:38 +00:00
|
|
|
}
|
|
|
|
}
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
prev_key = Some((span, str.to_string()));
|
2020-07-09 23:46:38 +00:00
|
|
|
};
|
|
|
|
|
2019-05-22 09:25:39 +00:00
|
|
|
// Generate the listed keywords.
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
for keyword in input.keywords.iter() {
|
2019-04-03 00:43:49 +00:00
|
|
|
let name = &keyword.name;
|
|
|
|
let value = &keyword.value;
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
let value_string = value.value();
|
2023-10-25 20:42:58 +00:00
|
|
|
let idx = entries.insert(keyword.name.span(), &value_string, &mut errors);
|
2019-04-03 00:43:49 +00:00
|
|
|
prefill_stream.extend(quote! {
|
|
|
|
#value,
|
|
|
|
});
|
|
|
|
keyword_stream.extend(quote! {
|
2023-10-25 20:20:47 +00:00
|
|
|
pub const #name: Symbol = Symbol::new(#idx);
|
2019-04-03 00:43:49 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-05-22 09:25:39 +00:00
|
|
|
// Generate the listed symbols.
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
for symbol in input.symbols.iter() {
|
2019-05-06 23:55:12 +00:00
|
|
|
let name = &symbol.name;
|
2023-10-25 18:20:07 +00:00
|
|
|
check_order(symbol.name.span(), &name.to_string(), &mut errors);
|
|
|
|
|
2019-05-06 23:55:12 +00:00
|
|
|
let value = match &symbol.value {
|
2023-10-25 18:12:32 +00:00
|
|
|
Value::SameAsName => name.to_string(),
|
|
|
|
Value::String(lit) => lit.value(),
|
2023-10-25 20:52:38 +00:00
|
|
|
Value::Env(..) => continue, // in another loop below
|
2023-10-25 20:46:59 +00:00
|
|
|
Value::Unsupported(expr) => {
|
|
|
|
errors.list.push(syn::Error::new_spanned(
|
|
|
|
expr,
|
|
|
|
concat!(
|
|
|
|
"unsupported expression for symbol value; implement support for this in ",
|
|
|
|
file!(),
|
|
|
|
),
|
|
|
|
));
|
|
|
|
continue;
|
|
|
|
}
|
2019-05-06 23:55:12 +00:00
|
|
|
};
|
2023-10-25 20:42:58 +00:00
|
|
|
let idx = entries.insert(symbol.name.span(), &value, &mut errors);
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
|
2019-04-03 00:43:49 +00:00
|
|
|
prefill_stream.extend(quote! {
|
2019-05-06 23:55:12 +00:00
|
|
|
#value,
|
2019-04-03 00:43:49 +00:00
|
|
|
});
|
|
|
|
symbols_stream.extend(quote! {
|
2023-10-25 20:20:47 +00:00
|
|
|
pub const #name: Symbol = Symbol::new(#idx);
|
2019-04-03 00:43:49 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-05-22 09:25:39 +00:00
|
|
|
// Generate symbols for the strings "0", "1", ..., "9".
|
|
|
|
for n in 0..10 {
|
|
|
|
let n = n.to_string();
|
2023-10-25 20:42:58 +00:00
|
|
|
entries.insert(Span::call_site(), &n, &mut errors);
|
2019-05-22 09:25:39 +00:00
|
|
|
prefill_stream.extend(quote! {
|
|
|
|
#n,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-10-25 18:20:07 +00:00
|
|
|
// Symbols whose value comes from an environment variable. It's allowed for
|
|
|
|
// these to have the same value as another symbol.
|
|
|
|
for symbol in &input.symbols {
|
2023-10-25 20:52:38 +00:00
|
|
|
let (env_var, expr) = match &symbol.value {
|
|
|
|
Value::Env(lit, expr) => (lit, expr),
|
2023-10-25 20:46:59 +00:00
|
|
|
Value::SameAsName | Value::String(_) | Value::Unsupported(_) => continue,
|
2023-10-25 18:20:07 +00:00
|
|
|
};
|
|
|
|
|
2023-10-25 21:45:31 +00:00
|
|
|
if !proc_macro::is_available() {
|
|
|
|
errors.error(
|
|
|
|
Span::call_site(),
|
|
|
|
"proc_macro::tracked_env is not available in unit test".to_owned(),
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-10-25 18:20:07 +00:00
|
|
|
let value = match proc_macro::tracked_env::var(env_var.value()) {
|
|
|
|
Ok(value) => value,
|
|
|
|
Err(err) => {
|
2023-10-25 20:52:38 +00:00
|
|
|
errors.list.push(syn::Error::new_spanned(expr, err));
|
2023-10-25 18:20:07 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let idx = if let Some(prev) = entries.map.get(&value) {
|
|
|
|
prev.idx
|
|
|
|
} else {
|
|
|
|
prefill_stream.extend(quote! {
|
|
|
|
#value,
|
|
|
|
});
|
|
|
|
entries.insert(symbol.name.span(), &value, &mut errors)
|
|
|
|
};
|
|
|
|
|
|
|
|
let name = &symbol.name;
|
|
|
|
symbols_stream.extend(quote! {
|
|
|
|
pub const #name: Symbol = Symbol::new(#idx);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-10-25 20:42:58 +00:00
|
|
|
let symbol_digits_base = entries.map["0"].idx;
|
|
|
|
let preinterned_symbols_count = entries.len();
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
let output = quote! {
|
2023-10-25 20:20:47 +00:00
|
|
|
const SYMBOL_DIGITS_BASE: u32 = #symbol_digits_base;
|
|
|
|
const PREINTERNED_SYMBOLS_COUNT: u32 = #preinterned_symbols_count;
|
2019-04-03 00:43:49 +00:00
|
|
|
|
2020-12-14 19:34:55 +00:00
|
|
|
#[doc(hidden)]
|
|
|
|
#[allow(non_upper_case_globals)]
|
|
|
|
mod kw_generated {
|
|
|
|
use super::Symbol;
|
|
|
|
#keyword_stream
|
|
|
|
}
|
2019-05-22 09:25:39 +00:00
|
|
|
|
2020-12-14 19:34:55 +00:00
|
|
|
#[allow(non_upper_case_globals)]
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub mod sym_generated {
|
|
|
|
use super::Symbol;
|
|
|
|
#symbols_stream
|
2019-04-03 00:43:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Interner {
|
2021-08-08 15:24:30 +00:00
|
|
|
pub(crate) fn fresh() -> Self {
|
2019-04-03 00:43:49 +00:00
|
|
|
Interner::prefill(&[
|
|
|
|
#prefill_stream
|
|
|
|
])
|
|
|
|
}
|
|
|
|
}
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
};
|
2019-05-06 23:55:12 +00:00
|
|
|
|
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
2020-12-11 19:32:48 +00:00
|
|
|
(output, errors.list)
|
2019-04-03 00:43:49 +00:00
|
|
|
}
|