diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 1849038545556..fcb7af64f5c0d 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -264,7 +264,7 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) hash_untracked_state: None, register_lints: None, override_queries: None, - extra_symbols: Vec::new(), + preinterned_symbols: None, make_codegen_backend: None, registry: diagnostics_registry(), using_internal_features: &USING_INTERNAL_FEATURES, diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs index 18c2bfdac8ce1..c9ac5fe1370fd 100644 --- a/compiler/rustc_hir/src/tests.rs +++ b/compiler/rustc_hir/src/tests.rs @@ -17,7 +17,7 @@ fn def_path_hash_depends_on_crate_id() { // the crate by changing the crate disambiguator (e.g. via bumping the // crate's version number). - create_session_globals_then(Edition::Edition2024, &[], None, || { + create_session_globals_then(Edition::Edition2024, None, None, || { let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()], ""); let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()], ""); diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index c46e879b976ac..52292ca071984 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -350,9 +350,9 @@ pub struct Config { /// the list of queries. pub override_queries: Option, - /// An extra set of symbols to add to the symbol interner, the symbol indices - /// will start at [`PREDEFINED_SYMBOLS_COUNT`](rustc_span::symbol::PREDEFINED_SYMBOLS_COUNT) - pub extra_symbols: Vec<&'static str>, + /// Replaces the default list of preinterned symbols, should be set to the `PREINTERNED_SYMBOLS` + /// expanded from [`rustc_span::extra_symbols`] + pub preinterned_symbols: Option<&'static [&'static str]>, /// This is a callback from the driver that is called to create a codegen backend. /// @@ -418,7 +418,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se &early_dcx, config.opts.edition, config.opts.unstable_opts.threads, - &config.extra_symbols, + config.preinterned_symbols, SourceMapInputs { file_loader, path_mapping, hash_kind, checksum_hash_kind }, |current_gcx, jobserver_proxy| { // The previous `early_dcx` can't be reused here because it doesn't diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 360b5629e9d6e..bbc0318e8aaaa 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -55,7 +55,7 @@ where checksum_hash_kind, }); - rustc_span::create_session_globals_then(DEFAULT_EDITION, &[], sm_inputs, || { + rustc_span::create_session_globals_then(DEFAULT_EDITION, None, sm_inputs, || { let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); let io = CompilerIO { input: Input::Str { name: FileName::Custom(String::new()), input: String::new() }, diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 0ca4fcc66ca55..54c58605d7f99 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -128,7 +128,7 @@ fn run_in_thread_with_globals) -> R + Send, R: thread_stack_size: usize, edition: Edition, sm_inputs: SourceMapInputs, - extra_symbols: &[&'static str], + driver_symbols: Option<&[&'static str]>, f: F, ) -> R { // The "thread pool" is a single spawned thread in the non-parallel @@ -148,7 +148,7 @@ fn run_in_thread_with_globals) -> R + Send, R: .spawn_scoped(s, move || { rustc_span::create_session_globals_then( edition, - extra_symbols, + driver_symbols, Some(sm_inputs), || f(CurrentGcx::new(), Proxy::new()), ) @@ -170,7 +170,7 @@ pub(crate) fn run_in_thread_pool_with_globals< thread_builder_diag: &EarlyDiagCtxt, edition: Edition, threads: usize, - extra_symbols: &[&'static str], + driver_symbols: Option<&[&'static str]>, sm_inputs: SourceMapInputs, f: F, ) -> R { @@ -191,7 +191,7 @@ pub(crate) fn run_in_thread_pool_with_globals< thread_stack_size, edition, sm_inputs, - extra_symbols, + driver_symbols, |current_gcx, jobserver_proxy| { // Register the thread for use with the `WorkerLocal` type. registry.register(); @@ -259,7 +259,7 @@ pub(crate) fn run_in_thread_pool_with_globals< // pool. Upon creation, each worker thread created gets a copy of the // session globals in TLS. This is possible because `SessionGlobals` impls // `Send` in the parallel compiler. - rustc_span::create_session_globals_then(edition, extra_symbols, Some(sm_inputs), || { + rustc_span::create_session_globals_then(edition, driver_symbols, Some(sm_inputs), || { rustc_span::with_session_globals(|session_globals| { let session_globals = FromDyn::from(session_globals); builder diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 1006ea3ba10a0..6ccc6733e7ace 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -40,6 +40,11 @@ pub fn symbols(input: TokenStream) -> TokenStream { symbols::symbols(input.into()).into() } +#[proc_macro] +pub fn extra_symbols_impl(input: TokenStream) -> TokenStream { + symbols::extra_symbols(input.into()).into() +} + /// Derive an extension trait for a given impl block. The trait name /// goes into the parenthesized args of the macro, for greppability. /// For example: diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs index 78a4d47ca3346..1e7b20f8562a4 100644 --- a/compiler/rustc_macros/src/symbols.rs +++ b/compiler/rustc_macros/src/symbols.rs @@ -25,12 +25,13 @@ //! ``` use std::collections::HashMap; +use std::collections::hash_map::Entry; use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::parse::{Parse, ParseStream, Result}; use syn::punctuated::Punctuated; -use syn::{Expr, Ident, Lit, LitStr, Macro, Token, braced}; +use syn::{Expr, Ident, Lit, LitStr, Macro, Token, braced, bracketed}; #[cfg(test)] mod tests; @@ -147,25 +148,44 @@ struct Predefined { span_of_name: Span, } +struct Duplicate { + name: String, + span_of_name: Span, +} + struct Entries { map: HashMap, + prefill_stream: TokenStream, } impl Entries { fn with_capacity(capacity: usize) -> Self { - Entries { map: HashMap::with_capacity(capacity) } + Entries { map: HashMap::with_capacity(capacity), prefill_stream: TokenStream::new() } + } + + fn try_insert(&mut self, span: Span, s: String) -> (u32, Option) { + let len = self.len(); + match self.map.entry(s) { + Entry::Occupied(entry) => { + let Predefined { idx, span_of_name } = *entry.get(); + (idx, Some(Duplicate { name: entry.key().clone(), span_of_name })) + } + Entry::Vacant(entry) => { + let s = entry.key().as_str(); + self.prefill_stream.extend(quote! { #s, }); + entry.insert(Predefined { idx: len, span_of_name: span }); + (len, None) + } + } } - fn insert(&mut self, span: Span, s: &str, errors: &mut Errors) -> u32 { - if let Some(prev) = self.map.get(s) { - errors.error(span, format!("Symbol `{s}` is duplicated")); - errors.error(prev.span_of_name, "location of previous definition".to_string()); - prev.idx - } else { - let idx = self.len(); - self.map.insert(s.to_string(), Predefined { idx, span_of_name: span }); - idx + fn insert(&mut self, span: Span, s: String, errors: &mut Errors) -> u32 { + let (idx, duplicate) = self.try_insert(span, s); + if let Some(Duplicate { name, span_of_name }) = duplicate { + errors.error(span, format!("Symbol `{name}` is duplicated")); + errors.error(span_of_name, "location of previous definition".to_string()); } + idx } fn len(&self) -> u32 { @@ -188,18 +208,13 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { let mut keyword_stream = quote! {}; let mut symbols_stream = quote! {}; - let mut prefill_stream = quote! {}; let mut entries = Entries::with_capacity(input.keywords.len() + input.symbols.len() + 10); // Generate the listed keywords. for keyword in input.keywords.iter() { let name = &keyword.name; - let value = &keyword.value; - let value_string = value.value(); - let idx = entries.insert(keyword.name.span(), &value_string, &mut errors); - prefill_stream.extend(quote! { - #value, - }); + let value_string = keyword.value.value(); + let idx = entries.insert(keyword.name.span(), value_string, &mut errors); keyword_stream.extend(quote! { pub const #name: Symbol = Symbol::new(#idx); }); @@ -224,11 +239,7 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { continue; } }; - let idx = entries.insert(symbol.name.span(), &value, &mut errors); - - prefill_stream.extend(quote! { - #value, - }); + let idx = entries.insert(symbol.name.span(), value, &mut errors); symbols_stream.extend(quote! { pub const #name: Symbol = Symbol::new(#idx); }); @@ -236,11 +247,7 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { // Generate symbols for the strings "0", "1", ..., "9". for n in 0..10 { - let n = n.to_string(); - entries.insert(Span::call_site(), &n, &mut errors); - prefill_stream.extend(quote! { - #n, - }); + entries.insert(Span::call_site(), n.to_string(), &mut errors); } // Symbols whose value comes from an environment variable. It's allowed for @@ -267,16 +274,8 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { } }; - 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; + let (idx, _) = entries.try_insert(name.span(), value); symbols_stream.extend(quote! { pub const #name: Symbol = Symbol::new(#idx); }); @@ -284,6 +283,7 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { let symbol_digits_base = entries.map["0"].idx; let predefined_symbols_count = entries.len(); + let prefill_stream = entries.prefill_stream; let output = quote! { const SYMBOL_DIGITS_BASE: u32 = #symbol_digits_base; @@ -309,14 +309,124 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { impl Interner { /// Creates an `Interner` with the predefined symbols from the `symbols!` macro and /// any extra symbols provided by external drivers such as Clippy - pub(crate) fn with_extra_symbols(extra_symbols: &[&'static str]) -> Self { + pub(crate) fn new(driver_symbols: Option<&[&'static str]>) -> Self { Interner::prefill( - &[#prefill_stream], - extra_symbols, + driver_symbols.unwrap_or(&[#prefill_stream]) ) } } + + /// Allows drivers to define extra preinterned symbols, the expanded `PREINTERNED_SYMBOLS` + /// is to be provided to `rustc_interface::Config` + #[macro_export] + macro_rules! extra_symbols { + ($(#[macro_export] $further_symbols:ident;)? Symbols { $($tt:tt)* }) => { + rustc_macros::extra_symbols_impl! { + $($further_symbols)? [#prefill_stream] $($tt)* + } + }; + } }; (output, errors.list) } + +#[derive(Default)] +struct ExtraSymbols { + macro_ident: Option, + predefined: Punctuated, + extra_symbols: Punctuated, +} + +impl Parse for ExtraSymbols { + fn parse(input: ParseStream<'_>) -> Result { + let macro_ident: Option = input.parse()?; + + let content; + bracketed!(content in input); + let predefined = Punctuated::parse_terminated(&content)?; + + let extra_symbols = Punctuated::parse_terminated(&input)?; + + Ok(ExtraSymbols { macro_ident, predefined, extra_symbols }) + } +} + +pub(super) fn extra_symbols(input: TokenStream) -> TokenStream { + let mut errors = Errors::default(); + + let input: ExtraSymbols = match syn::parse2(input) { + Ok(input) => input, + Err(e) => { + errors.list.push(e); + Default::default() + } + }; + + let mut symbol_stream = TokenStream::new(); + let mut duplicate_symbols = TokenStream::new(); + + let mut entries = Entries::with_capacity(input.predefined.len() + input.extra_symbols.len()); + for lit in &input.predefined { + entries.insert(lit.span(), lit.value(), &mut errors); + } + + for symbol in input.extra_symbols { + let value = match symbol.value { + Value::SameAsName => symbol.name.to_string(), + Value::String(lit) => lit.value(), + _ => { + errors.error( + symbol.name.span(), + "unsupported expression for extra symbol value".to_string(), + ); + continue; + } + }; + + let name = &symbol.name; + let (idx, duplicate) = entries.try_insert(name.span(), value); + if duplicate.is_some() { + duplicate_symbols.extend(quote! { #name, }); + } + symbol_stream.extend(quote! { + pub const #name: Symbol = Symbol::new(#idx); + }); + } + + let prefill_stream = entries.prefill_stream; + + let further_symbols = if let Some(macro_ident) = input.macro_ident { + quote! { + #[macro_export] + macro_rules! #macro_ident { + ($(#[macro_export] $further_symbols:ident;)? Symbols { $($tt:tt)* }) => { + rustc_macros::extra_symbols_impl! { + $($further_symbols)? [#prefill_stream] $($tt)* + } + }; + } + } + } else { + TokenStream::new() + }; + + let mut output = quote! { + /// To be supplied to `rustc_interface::Config` + pub const PREINTERNED_SYMBOLS: &[&str] = &[ + #prefill_stream + ]; + + pub const DUPLICATE_SYMBOLS: &[Symbol] = &[ + #duplicate_symbols + ]; + + #symbol_stream + + #further_symbols + }; + + output.extend(errors.list.into_iter().map(|e| e.into_compile_error())); + + output +} diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 9b0e009b2cd37..33480c119cf0d 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -117,11 +117,11 @@ pub struct SessionGlobals { impl SessionGlobals { pub fn new( edition: Edition, - extra_symbols: &[&'static str], + driver_symbols: Option<&[&'static str]>, sm_inputs: Option, ) -> SessionGlobals { SessionGlobals { - symbol_interner: symbol::Interner::with_extra_symbols(extra_symbols), + symbol_interner: symbol::Interner::new(driver_symbols), span_interner: Lock::new(span_encoding::SpanInterner::default()), metavar_spans: Default::default(), hygiene_data: Lock::new(hygiene::HygieneData::new(edition)), @@ -132,7 +132,7 @@ impl SessionGlobals { pub fn create_session_globals_then( edition: Edition, - extra_symbols: &[&'static str], + driver_symbols: Option<&[&'static str]>, sm_inputs: Option, f: impl FnOnce() -> R, ) -> R { @@ -141,7 +141,7 @@ pub fn create_session_globals_then( "SESSION_GLOBALS should never be overwritten! \ Use another thread if you need another SessionGlobals" ); - let session_globals = SessionGlobals::new(edition, extra_symbols, sm_inputs); + let session_globals = SessionGlobals::new(edition, driver_symbols, sm_inputs); SESSION_GLOBALS.set(&session_globals, f) } @@ -160,7 +160,7 @@ where F: FnOnce(&SessionGlobals) -> R, { if !SESSION_GLOBALS.is_set() { - let session_globals = SessionGlobals::new(edition, &[], None); + let session_globals = SessionGlobals::new(edition, None, None); SESSION_GLOBALS.set(&session_globals, || SESSION_GLOBALS.with(f)) } else { SESSION_GLOBALS.with(f) @@ -176,7 +176,7 @@ where /// Default edition, no source map. pub fn create_default_session_globals_then(f: impl FnOnce() -> R) -> R { - create_session_globals_then(edition::DEFAULT_EDITION, &[], None, f) + create_session_globals_then(edition::DEFAULT_EDITION, None, None, f) } // If this ever becomes non thread-local, `decode_syntax_context` diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 09f01d8704e2a..c5616a14ae86d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2740,18 +2740,11 @@ struct InternerInner { } impl Interner { - // These arguments are `&str`, but because of the sharing, we are + // These initial symbols are `&str`, but because of the sharing, we are // effectively pre-interning all these strings for both `Symbol` and // `ByteSymbol`. - fn prefill(init: &[&'static str], extra: &[&'static str]) -> Self { - let byte_strs = FxIndexSet::from_iter( - init.iter().copied().chain(extra.iter().copied()).map(|str| str.as_bytes()), - ); - assert_eq!( - byte_strs.len(), - init.len() + extra.len(), - "duplicate symbols in the rustc symbol list and the extra symbols added by the driver", - ); + fn prefill(init: &[&'static str]) -> Self { + let byte_strs = FxIndexSet::from_iter(init.iter().map(|str| str.as_bytes())); Interner(Lock::new(InternerInner { arena: Default::default(), byte_strs })) } diff --git a/compiler/rustc_span/src/symbol/tests.rs b/compiler/rustc_span/src/symbol/tests.rs index bf0660aa51085..4dfb80836ab66 100644 --- a/compiler/rustc_span/src/symbol/tests.rs +++ b/compiler/rustc_span/src/symbol/tests.rs @@ -3,7 +3,7 @@ use crate::create_default_session_globals_then; #[test] fn interner_tests() { - let i = Interner::prefill(&[], &[]); + let i = Interner::prefill(&[]); // first one is zero: assert_eq!(i.intern_str("dog"), Symbol::new(0)); // re-use gets the same entry, even with a `ByteSymbol` @@ -22,3 +22,49 @@ fn without_first_quote_test() { assert_eq!(i.without_first_quote().name, kw::Break); }); } + +#[allow(non_upper_case_globals)] +mod extra_symbols_macro { + use crate::{Symbol, sym}; + + mod a { + use crate::*; + + extra_symbols! { + #[macro_export] extra_symbols_plus_a; + + Symbols { + DEFINED_IN_A, + std, + } + } + } + + mod b { + use crate::*; + + extra_symbols_plus_a! { + Symbols { + DEFINED_IN_A, + DEFINED_IN_B, + core, + std, + } + } + } + + #[test] + fn extra_symbols() { + // Extra symbols are preinterned but not considered predefined + assert!(!Symbol::is_predefined(a::DEFINED_IN_A.as_u32())); + assert!(!Symbol::is_predefined(b::DEFINED_IN_B.as_u32())); + + assert_eq!(sym::std, a::std); + assert_eq!(sym::std, b::std); + + assert_eq!(a::DEFINED_IN_A, b::DEFINED_IN_A); + + assert_eq!(a::DUPLICATE_SYMBOLS, [sym::std]); + assert_eq!(b::DUPLICATE_SYMBOLS, [a::DEFINED_IN_A, sym::core, sym::std]); + } +} diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index bd57bb21e639b..d32257a933f69 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -318,7 +318,7 @@ pub(crate) fn create_config( (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id) }; }), - extra_symbols: Vec::new(), + preinterned_symbols: None, make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), ice_file: None, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 9b4d25339541d..05bb5bfcbfb2f 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -148,7 +148,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions hash_untracked_state: None, register_lints: Some(Box::new(crate::lint::register_lints)), override_queries: None, - extra_symbols: Vec::new(), + preinterned_symbols: None, make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), ice_file: None, diff --git a/src/tools/clippy/clippy_dev/src/fmt.rs b/src/tools/clippy/clippy_dev/src/fmt.rs index c1b6b37070696..08e7e51e1335b 100644 --- a/src/tools/clippy/clippy_dev/src/fmt.rs +++ b/src/tools/clippy/clippy_dev/src/fmt.rs @@ -235,8 +235,8 @@ fn fmt_syms(update_mode: UpdateMode) { update_mode, "clippy_utils/src/sym.rs", &mut |_, text: &str, new_text: &mut String| { - let (pre, conf) = text.split_once("generate! {\n").expect("can't find generate! call"); - let (conf, post) = conf.split_once("\n}\n").expect("can't find end of generate! call"); + let (pre, conf) = text.split_once("Symbols {\n").expect("can't find Symbols { .. }"); + let (conf, post) = conf.split_once("\n }\n").expect("can't find end of Symbols { .. }"); let mut lines = conf .lines() .map(|line| { diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs index 74283d7ba863b..ccb08dc94bce8 100644 --- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs +++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs @@ -38,7 +38,7 @@ pub fn check( // of all `#[test]` attributes in not ignored code examples fn check_code_sample(code: String, edition: Edition, ignore: bool) -> (bool, Vec>) { rustc_driver::catch_fatal_errors(|| { - rustc_span::create_session_globals_then(edition, &[], None, || { + rustc_span::create_session_globals_then(edition, None, None, || { let mut test_attr_spans = vec![]; let filename = FileName::anon_source_code(&code); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index c01f0ffaac9a0..0458aad4d591f 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -43,6 +43,7 @@ extern crate rustc_index; extern crate rustc_infer; extern crate rustc_lexer; extern crate rustc_lint; +extern crate rustc_macros; extern crate rustc_middle; extern crate rustc_mir_dataflow; extern crate rustc_session; diff --git a/src/tools/clippy/clippy_utils/src/sym.rs b/src/tools/clippy/clippy_utils/src/sym.rs index 8a8218c6976f3..35a9f1e7b7a47 100644 --- a/src/tools/clippy/clippy_utils/src/sym.rs +++ b/src/tools/clippy/clippy_utils/src/sym.rs @@ -1,373 +1,353 @@ #![allow(non_upper_case_globals)] -use rustc_span::symbol::PREDEFINED_SYMBOLS_COUNT; +use rustc_span::{extra_symbols, Symbol}; #[doc(no_inline)] pub use rustc_span::sym::*; -macro_rules! val { - ($name:ident) => { - stringify!($name) - }; - ($name:ident $value:literal) => { - $value - }; -} - -macro_rules! generate { - ($($name:ident $(: $value:literal)? ,)*) => { - /// To be supplied to `rustc_interface::Config` - pub const EXTRA_SYMBOLS: &[&str] = &[ - $( - val!($name $($value)?), - )* - ]; - - $( - pub const $name: rustc_span::Symbol = rustc_span::Symbol::new(PREDEFINED_SYMBOLS_COUNT + ${index()}); - )* - }; -} - // List of extra symbols to be included in Clippy (for example, as `sym::ambiguous_glob_reexports`). // An alternative content can be specified using a colon after the symbol name. // -// `cargo dev fmt` ensures that the content of the `generate!()` macro call stays sorted. -generate! { - AsyncReadExt, - AsyncWriteExt, - BACKSLASH_SINGLE_QUOTE: r"\'", - Binary, - CLIPPY_ARGS, - CLIPPY_CONF_DIR, - CRLF: "\r\n", - Cargo_toml: "Cargo.toml", - Current, - DOUBLE_QUOTE: "\"", - Deserialize, - EarlyLintPass, - IntoIter, - Itertools, - LF: "\n", - Lazy, - Lint, - LowerExp, - LowerHex, - MAX, - MIN, - MsrvStack, - Octal, - OpenOptions, - Other, - PathLookup, - Regex, - RegexBuilder, - RegexSet, - Start, - Symbol, - SyntaxContext, - TBD, - UpperExp, - UpperHex, - V4, - V6, - Visitor, - Weak, - abs, - ambiguous_glob_reexports, - append, - arg, - as_bytes, - as_deref, - as_deref_mut, - as_mut, - as_path, - assert_failed, - author, - borrow, - borrow_mut, - build_hasher, - by_ref, - bytes, - capacity, - cargo_clippy: "cargo-clippy", - cast, - cast_const, - cast_mut, - ceil, - ceil_char_boundary, - chain, - chars, - checked_abs, - checked_add, - checked_isqrt, - checked_mul, - checked_pow, - checked_rem_euclid, - checked_sub, - clamp, - clippy_utils, - clone_into, - cloned, - cognitive_complexity, - collect, - const_ptr, - contains, - copied, - copy_from, - copy_from_nonoverlapping, - copy_to, - copy_to_nonoverlapping, - count_ones, - create, - create_new, - cycle, - cyclomatic_complexity, - de, - diagnostics, - disallowed_types, - drain, - dump, - ends_with, - enum_glob_use, - enumerate, - err, - exp, - expect_err, - expn_data, - extend, - filter, - filter_map, - find, - find_map, - finish, - finish_non_exhaustive, - first, - flat_map, - flatten, - floor, - floor_char_boundary, - fold, - for_each, - from_be_bytes, - from_bytes_with_nul, - from_bytes_with_nul_unchecked, - from_le_bytes, - from_ne_bytes, - from_ptr, - from_raw, - from_str, - from_str_radix, - fs, - fuse, - futures_util, - get, - get_mut, - get_or_insert, - get_or_insert_with, - get_unchecked, - get_unchecked_mut, - has_significant_drop, - hidden_glob_reexports, - hygiene, - if_chain, - insert, - inspect, - int_roundings, - into, - into_bytes, - into_ok, - into_owned, - io, - is_ascii, - is_char_boundary, - is_digit, - is_empty, - is_err, - is_file, - is_none, - is_none_or, - is_ok, - is_some, - is_some_and, - isqrt, - itertools, - join, - kw, - last, - lazy_static, - ln, - lock, - lock_api, - log, - log10, - log2, - macro_use_imports, - map_break, - map_continue, - map_or, - map_or_else, - match_indices, - matches, - max, - max_by, - max_by_key, - max_value, - maximum, - min, - min_by, - min_by_key, - min_value, - minimum, - mode, - module_name_repetitions, - msrv, - msrvs, - mut_ptr, - mutex, - needless_return, - next_back, - next_if, - next_if_eq, - next_tuple, - nth, - ok, - ok_or, - once_cell, - open, - or_default, - or_else, - or_insert, - or_insert_with, - outer_expn, - panic_cold_display, - panic_cold_explicit, - panic_display, - panic_str, - parse, - partition, - paths, - peek, - peek_mut, - peekable, - pow, - powf, - powi, - product, - push, - read, - read_exact, - read_line, - read_to_end, - read_to_string, - read_unaligned, - redundant_pub_crate, - regex, - rem_euclid, - repeat, - replace, - replacen, - reserve, - resize, - restriction, - rev, - rfind, - rmatch_indices, - rmatches, - round, - rposition, - rsplit, - rsplit_once, - rsplit_terminator, - rsplitn, - rsplitn_mut, - rustc_lint, - rustc_lint_defs, - rustc_span, - rustfmt_skip, - rwlock, - saturating_abs, - saturating_pow, - scan, - seek, - serde, - set_len, - set_mode, - set_readonly, - signum, - single_component_path_imports, - skip_while, - slice_mut_unchecked, - slice_unchecked, - sort, - sort_by, - sort_unstable_by, - span_lint_and_then, - split, - split_at, - split_at_checked, - split_at_mut, - split_at_mut_checked, - split_inclusive, - split_once, - split_terminator, - split_whitespace, - splitn, - splitn_mut, - sqrt, - starts_with, - step_by, - strlen, - style, - subsec_micros, - subsec_nanos, - sum, - symbol, - take, - take_while, - then, - then_some, - to_ascii_lowercase, - to_ascii_uppercase, - to_be_bytes, - to_digit, - to_le_bytes, - to_lowercase, - to_ne_bytes, - to_os_string, - to_owned, - to_path_buf, - to_uppercase, - tokio, - trim, - trim_end, - trim_end_matches, - trim_start, - trim_start_matches, - truncate, - unreachable_pub, - unsafe_removed_from_name, - unused, - unused_braces, - unused_extern_crates, - unused_import_braces, - unused_trait_names, - unwrap_err, - unwrap_err_unchecked, - unwrap_or_default, - unwrap_or_else, - unwrap_unchecked, - unzip, - utils, - visit_str, - visit_string, - wake, - warnings, - wildcard_imports, - with_capacity, - wrapping_offset, - write, - write_unaligned, - writeln, - zip, +// `cargo dev fmt` ensures that the content of `Symbols { .. }` stays sorted. +extra_symbols! { + #[macro_export] extra_symbols_plus_clippy; + + Symbols { + AsyncReadExt, + AsyncWriteExt, + BACKSLASH_SINGLE_QUOTE: r"\'", + Binary, + CLIPPY_ARGS, + CLIPPY_CONF_DIR, + CRLF: "\r\n", + Cargo_toml: "Cargo.toml", + Current, + DOUBLE_QUOTE: "\"", + Deserialize, + EarlyLintPass, + IntoIter, + Itertools, + LF: "\n", + Lazy, + Lint, + LowerExp, + LowerHex, + MAX, + MIN, + MsrvStack, + Octal, + OpenOptions, + Other, + PathLookup, + Regex, + RegexBuilder, + RegexSet, + Start, + Symbol, + SyntaxContext, + TBD, + UpperExp, + UpperHex, + V4, + V6, + Visitor, + Weak, + abs, + ambiguous_glob_reexports, + append, + arg, + as_bytes, + as_deref, + as_deref_mut, + as_mut, + as_path, + assert_failed, + author, + borrow, + borrow_mut, + build_hasher, + by_ref, + bytes, + capacity, + cargo_clippy: "cargo-clippy", + cast, + cast_const, + cast_mut, + ceil, + ceil_char_boundary, + chain, + chars, + checked_abs, + checked_add, + checked_isqrt, + checked_mul, + checked_pow, + checked_rem_euclid, + checked_sub, + clamp, + clippy_utils, + clone_into, + cloned, + cognitive_complexity, + collect, + const_ptr, + contains, + copied, + copy_from, + copy_from_nonoverlapping, + copy_to, + copy_to_nonoverlapping, + count_ones, + create, + create_new, + cycle, + cyclomatic_complexity, + de, + diagnostics, + disallowed_types, + drain, + dump, + ends_with, + enum_glob_use, + enumerate, + err, + exp, + expect_err, + expn_data, + extend, + filter, + filter_map, + find, + find_map, + finish, + finish_non_exhaustive, + first, + flat_map, + flatten, + floor, + floor_char_boundary, + fold, + for_each, + from_be_bytes, + from_bytes_with_nul, + from_bytes_with_nul_unchecked, + from_le_bytes, + from_ne_bytes, + from_ptr, + from_raw, + from_str, + from_str_radix, + fs, + fuse, + futures_util, + get, + get_mut, + get_or_insert, + get_or_insert_with, + get_unchecked, + get_unchecked_mut, + has_significant_drop, + hidden_glob_reexports, + hygiene, + if_chain, + insert, + inspect, + int_roundings, + into, + into_bytes, + into_ok, + into_owned, + io, + is_ascii, + is_char_boundary, + is_digit, + is_empty, + is_err, + is_file, + is_none, + is_none_or, + is_ok, + is_some, + is_some_and, + isqrt, + itertools, + join, + kw, + last, + lazy_static, + ln, + lock, + lock_api, + log, + log10, + log2, + macro_use_imports, + map_break, + map_continue, + map_or, + map_or_else, + match_indices, + matches, + max, + max_by, + max_by_key, + max_value, + maximum, + min, + min_by, + min_by_key, + min_value, + minimum, + mode, + module_name_repetitions, + msrv, + msrvs, + mut_ptr, + mutex, + needless_return, + next_back, + next_if, + next_if_eq, + next_tuple, + nth, + ok, + ok_or, + once_cell, + open, + or_default, + or_else, + or_insert, + or_insert_with, + outer_expn, + panic_cold_display, + panic_cold_explicit, + panic_display, + panic_str, + parse, + partition, + paths, + peek, + peek_mut, + peekable, + pow, + powf, + powi, + product, + push, + read, + read_exact, + read_line, + read_to_end, + read_to_string, + read_unaligned, + redundant_pub_crate, + regex, + rem_euclid, + repeat, + replace, + replacen, + reserve, + resize, + restriction, + rev, + rfind, + rmatch_indices, + rmatches, + round, + rposition, + rsplit, + rsplit_once, + rsplit_terminator, + rsplitn, + rsplitn_mut, + rustc_lint, + rustc_lint_defs, + rustc_span, + rustfmt_skip, + rwlock, + saturating_abs, + saturating_pow, + scan, + seek, + serde, + set_len, + set_mode, + set_readonly, + signum, + single_component_path_imports, + skip_while, + slice_mut_unchecked, + slice_unchecked, + sort, + sort_by, + sort_unstable_by, + span_lint_and_then, + split, + split_at, + split_at_checked, + split_at_mut, + split_at_mut_checked, + split_inclusive, + split_once, + split_terminator, + split_whitespace, + splitn, + splitn_mut, + sqrt, + starts_with, + step_by, + strlen, + style, + subsec_micros, + subsec_nanos, + sum, + symbol, + take, + take_while, + then, + then_some, + to_ascii_lowercase, + to_ascii_uppercase, + to_be_bytes, + to_digit, + to_le_bytes, + to_lowercase, + to_ne_bytes, + to_os_string, + to_owned, + to_path_buf, + to_uppercase, + tokio, + trim, + trim_end, + trim_end_matches, + trim_start, + trim_start_matches, + truncate, + unreachable_pub, + unsafe_removed_from_name, + unused, + unused_braces, + unused_extern_crates, + unused_import_braces, + unused_trait_names, + unwrap_err, + unwrap_err_unchecked, + unwrap_or_default, + unwrap_or_else, + unwrap_unchecked, + unzip, + utils, + visit_str, + visit_string, + wake, + warnings, + wildcard_imports, + with_capacity, + wrapping_offset, + write, + write_unaligned, + writeln, + zip, + } } diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index c4076cbaa77b2..f77f76f8f3b71 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -167,7 +167,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks { #[cfg(feature = "internal")] clippy_lints_internal::register_lints(lint_store); })); - config.extra_symbols = sym::EXTRA_SYMBOLS.into(); + config.preinterned_symbols = Some(sym::PREINTERNED_SYMBOLS); // FIXME: #4825; This is required, because Clippy lints that are based on MIR have to be // run on the unoptimized MIR. On the other hand this results in some false negatives. If diff --git a/src/tools/clippy/tests/symbols-used.rs b/src/tools/clippy/tests/symbols-used.rs index bc0456711fb2b..998e73991dc1a 100644 --- a/src/tools/clippy/tests/symbols-used.rs +++ b/src/tools/clippy/tests/symbols-used.rs @@ -27,13 +27,13 @@ fn all_symbols_are_used() -> Result<()> { // Load all symbols defined in `SYM_FILE`. let content = fs::read_to_string(SYM_FILE)?; let content = content - .split_once("generate! {") + .split_once("extra_symbols! {") .ok_or("cannot find symbols start")? .1 .split_once("\n}\n") .ok_or("cannot find symbols end")? .0; - let mut interned: HashSet = Regex::new(r"(?m)^ (\w+)") + let mut interned: HashSet = Regex::new(r"(?m)^ {8}(\w+)") .unwrap() .captures_iter(content) .map(|m| m[1].to_owned()) diff --git a/tests/ui-fulldeps/run-compiler-twice.rs b/tests/ui-fulldeps/run-compiler-twice.rs index 87504b8301f03..ca37e08d6fd08 100644 --- a/tests/ui-fulldeps/run-compiler-twice.rs +++ b/tests/ui-fulldeps/run-compiler-twice.rs @@ -70,7 +70,7 @@ fn compile(code: String, output: PathBuf, sysroot: Sysroot, linker: Option<&Path hash_untracked_state: None, register_lints: None, override_queries: None, - extra_symbols: Vec::new(), + preinterned_symbols: None, make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), using_internal_features: &rustc_driver::USING_INTERNAL_FEATURES,