parser/derive: use only one hasher throughout the proc_macro

This commit is contained in:
René Kijewski 2025-08-03 05:53:00 +02:00
parent 3a677870d9
commit 267a115672
11 changed files with 41 additions and 44 deletions

View File

@ -1,5 +1,5 @@
use std::borrow::{Borrow, Cow};
use std::collections::btree_map::{BTreeMap, Entry};
use std::collections::hash_map::Entry;
use std::mem::ManuallyDrop;
use std::ops::Deref;
use std::path::{Path, PathBuf};
@ -12,12 +12,12 @@ use proc_macro2::Span;
#[cfg(feature = "config")]
use serde_derive::Deserialize;
use crate::{CompileError, FileInfo, OnceMap};
use crate::{CompileError, FileInfo, HashMap, OnceMap};
#[derive(Debug)]
pub(crate) struct Config {
pub(crate) dirs: Vec<PathBuf>,
pub(crate) syntaxes: BTreeMap<String, SyntaxAndCache<'static>>,
pub(crate) syntaxes: HashMap<String, SyntaxAndCache<'static>>,
pub(crate) default_syntax: &'static str,
pub(crate) escapers: Vec<(Vec<Cow<'static, str>>, Cow<'static, str>)>,
pub(crate) whitespace: Whitespace,
@ -107,7 +107,7 @@ impl Config {
let default_dirs = vec![root.join("templates")];
let mut syntaxes = BTreeMap::new();
let mut syntaxes = HashMap::default();
syntaxes.insert(DEFAULT_SYNTAX_NAME.to_string(), SyntaxAndCache::default());
let raw = if s.is_empty() {

View File

@ -4,7 +4,6 @@ mod helpers;
mod node;
use std::borrow::Cow;
use std::collections::hash_map::HashMap;
use std::env::current_dir;
use std::ops::Deref;
use std::path::{Path, PathBuf};
@ -15,7 +14,6 @@ use parser::node::{Call, Macro, Whitespace};
use parser::{CharLit, Expr, FloatKind, IntKind, Num, StrLit, WithSpan};
use proc_macro2::TokenStream;
use quote::{ToTokens, quote_spanned};
use rustc_hash::FxBuildHasher;
use syn::Token;
use crate::generator::helpers::{clean_path, diff_paths};
@ -23,12 +21,12 @@ use crate::heritage::{Context, Heritage};
use crate::html::write_escaped_str;
use crate::input::{Source, TemplateInput};
use crate::integration::{Buffer, impl_everything, write_header};
use crate::{CompileError, FileInfo, field_new, quote_into};
use crate::{CompileError, FileInfo, HashMap, field_new, quote_into};
pub(crate) fn template_to_string(
buf: &mut Buffer,
input: &TemplateInput<'_>,
contexts: &HashMap<&Arc<Path>, Context<'_>, FxBuildHasher>,
contexts: &HashMap<&Arc<Path>, Context<'_>>,
heritage: Option<&Heritage<'_, '_>>,
tmpl_kind: TmplKind<'_>,
) -> Result<usize, CompileError> {
@ -69,7 +67,7 @@ struct Generator<'a, 'h> {
/// The template input state: original struct AST and attributes
input: &'a TemplateInput<'a>,
/// All contexts, keyed by the package-relative template path
contexts: &'a HashMap<&'a Arc<Path>, Context<'a>, FxBuildHasher>,
contexts: &'a HashMap<&'a Arc<Path>, Context<'a>>,
/// The heritage contains references to blocks and their ancestry
heritage: Option<&'h Heritage<'a, 'h>>,
/// Variables accessible directly from the current scope (not redirected to context)
@ -102,7 +100,7 @@ enum CallerDir {
impl<'a, 'h> Generator<'a, 'h> {
fn new(
input: &'a TemplateInput<'a>,
contexts: &'a HashMap<&'a Arc<Path>, Context<'a>, FxBuildHasher>,
contexts: &'a HashMap<&'a Arc<Path>, Context<'a>>,
heritage: Option<&'h Heritage<'a, 'h>>,
locals: MapChain<'a>,
buf_writable_discard: bool,
@ -619,7 +617,7 @@ impl<'a> LocalMeta<'a> {
}
struct MapChain<'a> {
scopes: Vec<HashMap<Cow<'a, str>, LocalMeta<'a>, FxBuildHasher>>,
scopes: Vec<HashMap<Cow<'a, str>, LocalMeta<'a>>>,
}
impl<'a> MapChain<'a> {

View File

@ -1,19 +1,17 @@
use core::fmt;
use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt::Write;
use std::mem;
use parser::node::{Call, Macro, Ws};
use parser::{Expr, Span, WithSpan};
use quote::quote_spanned;
use rustc_hash::FxBuildHasher;
use crate::generator::node::AstLevel;
use crate::generator::{Generator, LocalMeta, is_copyable};
use crate::heritage::Context;
use crate::integration::Buffer;
use crate::{CompileError, field_new, quote_into};
use crate::{CompileError, HashMap, field_new, quote_into};
/// Helper to generate the code for macro invocations
pub(crate) struct MacroInvocation<'a, 'b> {
@ -97,14 +95,14 @@ impl<'a, 'b> MacroInvocation<'a, 'b> {
buf: &'b mut Buffer,
generator: &mut Generator<'a, 'h>,
) -> Result<(), CompileError> {
let mut named_arguments: HashMap<&str, _, FxBuildHasher> = HashMap::default();
let mut named_arguments = HashMap::default();
if let Some(Expr::NamedArgument(_, _)) = self.call_args.last().map(|expr| &***expr) {
// First we check that all named arguments actually exist in the called item.
for (index, arg) in self.call_args.iter().enumerate().rev() {
let Expr::NamedArgument(arg_name, _) = &***arg else {
let &Expr::NamedArgument(arg_name, _) = &***arg else {
break;
};
if !self.macro_def.args.iter().any(|(arg, _)| arg == arg_name) {
if !self.macro_def.args.iter().any(|&(arg, _)| arg == arg_name) {
return Err(self.callsite_ctx.generate_error(
format_args!(
"no argument named `{arg_name}` in macro {}",

View File

@ -1,5 +1,5 @@
use std::borrow::Cow;
use std::collections::hash_map::{Entry, HashMap};
use std::collections::hash_map::Entry;
use std::fmt::Debug;
use std::mem;
use std::ops::ControlFlow;
@ -12,13 +12,14 @@ use parser::node::{
use parser::{Expr, Node, Span, Target, WithSpan};
use proc_macro2::TokenStream;
use quote::quote_spanned;
use rustc_hash::FxBuildHasher;
use syn::Token;
use super::{DisplayWrap, Generator, LocalMeta, MapChain, compile_time_escape, is_copyable};
use crate::generator::{LocalCallerMeta, Writable, helpers, logic_op};
use crate::heritage::{Context, Heritage};
use crate::integration::{Buffer, string_escape};
use crate::{CompileError, FileInfo, field_new, fmt_left, fmt_right, quote_into};
use crate::{CompileError, FileInfo, HashMap, field_new, fmt_left, fmt_right, quote_into};
impl<'a> Generator<'a, '_> {
pub(super) fn impl_template_inner(
@ -1270,7 +1271,8 @@ impl<'a> Generator<'a, '_> {
let mut targets = Buffer::new();
let mut lines = Buffer::new();
let mut expr_cache = HashMap::with_capacity(self.buf_writable.len());
let mut expr_cache =
HashMap::with_capacity_and_hasher(self.buf_writable.len(), FxBuildHasher);
// the `last_line` contains any sequence of trailing simple `writer.write_str()` calls
let mut trailing_simple_lines = Vec::new();

View File

@ -1,15 +1,13 @@
use core::fmt;
use std::collections::HashMap;
use std::path::Path;
use std::sync::Arc;
use parser::node::{BlockDef, Macro};
use parser::{Node, Parsed, Span};
use rustc_hash::FxBuildHasher;
use crate::config::Config;
use crate::input::LiteralOrSpan;
use crate::{CompileError, FileInfo};
use crate::{CompileError, FileInfo, HashMap};
pub(crate) struct Heritage<'a, 'h> {
pub(crate) root: &'h Context<'a>,
@ -19,7 +17,7 @@ pub(crate) struct Heritage<'a, 'h> {
impl<'a, 'h> Heritage<'a, 'h> {
pub(crate) fn new(
mut root: &'h Context<'a>,
contexts: &'a HashMap<&'a Arc<Path>, Context<'a>, FxBuildHasher>,
contexts: &'a HashMap<&'a Arc<Path>, Context<'a>>,
) -> Self {
let mut blocks: BlockAncestry<'a, 'h> = root
.blocks
@ -38,16 +36,15 @@ impl<'a, 'h> Heritage<'a, 'h> {
}
}
type BlockAncestry<'a, 'h> =
HashMap<&'a str, Vec<(&'h Context<'a>, &'a BlockDef<'a>)>, FxBuildHasher>;
type BlockAncestry<'a, 'h> = HashMap<&'a str, Vec<(&'h Context<'a>, &'a BlockDef<'a>)>>;
#[derive(Clone)]
pub(crate) struct Context<'a> {
pub(crate) nodes: &'a [Box<Node<'a>>],
pub(crate) extends: Option<Arc<Path>>,
pub(crate) blocks: HashMap<&'a str, &'a BlockDef<'a>, FxBuildHasher>,
pub(crate) macros: HashMap<&'a str, &'a Macro<'a>, FxBuildHasher>,
pub(crate) imports: HashMap<&'a str, Arc<Path>, FxBuildHasher>,
pub(crate) blocks: HashMap<&'a str, &'a BlockDef<'a>>,
pub(crate) macros: HashMap<&'a str, &'a Macro<'a>>,
pub(crate) imports: HashMap<&'a str, Arc<Path>>,
pub(crate) path: Option<&'a Path>,
pub(crate) parsed: &'a Parsed,
pub(crate) literal: Option<LiteralOrSpan>,

View File

@ -1,5 +1,4 @@
use std::borrow::Cow;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::sync::Arc;
@ -7,13 +6,12 @@ use std::sync::Arc;
use parser::node::Whitespace;
use parser::{Node, Parsed};
use proc_macro2::Span;
use rustc_hash::FxBuildHasher;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::{Attribute, Expr, ExprLit, ExprPath, Ident, Lit, LitBool, LitStr, Meta, Token};
use crate::config::{Config, SyntaxAndCache};
use crate::{CompileError, FileInfo, MsgValidEscapers};
use crate::{CompileError, FileInfo, HashMap, MsgValidEscapers};
#[derive(Clone, Debug)]
pub(crate) enum LiteralOrSpan {
@ -178,7 +176,7 @@ impl TemplateInput<'_> {
pub(crate) fn find_used_templates(
&self,
map: &mut HashMap<Arc<Path>, Arc<Parsed>, FxBuildHasher>,
map: &mut HashMap<Arc<Path>, Arc<Parsed>>,
) -> Result<(), CompileError> {
let (source, source_path) = match &self.source {
Source::Source(s) => (s.clone(), None),

View File

@ -23,7 +23,7 @@ pub mod __macro_support {
}
use std::borrow::{Borrow, Cow};
use std::collections::hash_map::{Entry, HashMap};
use std::collections::hash_map::Entry;
use std::fmt;
use std::hash::{BuildHasher, Hash};
use std::path::Path;
@ -623,7 +623,7 @@ fn var_expr_n(n: usize, span: proc_macro2::Span) -> Ident {
}
#[derive(Debug)]
struct OnceMap<K, V>([Mutex<HashMap<K, V, FxBuildHasher>>; 8]);
struct OnceMap<K, V>([Mutex<HashMap<K, V>>; 8]);
impl<K, V> Default for OnceMap<K, V> {
fn default() -> Self {
@ -718,3 +718,5 @@ macro_rules! quote_into {
}
pub(crate) use {fmt_left, fmt_right, quote_into};
type HashMap<K, V> = std::collections::hash_map::HashMap<K, V, FxBuildHasher>;

View File

@ -21,6 +21,7 @@ name = "from_str"
harness = false
[dependencies]
rustc-hash = "2.0.0"
serde = { version = "1.0", optional = true }
serde_derive = { version = "1.0", optional = true }
unicode-ident = "1.0.12"

View File

@ -1,4 +1,3 @@
use std::collections::HashSet;
use std::str;
use winnow::Parser;
@ -11,9 +10,9 @@ use winnow::token::{one_of, take_until};
use crate::node::CondTest;
use crate::{
CharLit, ErrorContext, Level, Num, ParseResult, PathOrIdentifier, StrLit, StrPrefix, WithSpan,
can_be_variable_name, char_lit, cut_error, filter, identifier, keyword, not_suffix_with_hash,
num_lit, path_or_identifier, skip_ws0, skip_ws1, str_lit, ws,
CharLit, ErrorContext, HashSet, Level, Num, ParseResult, PathOrIdentifier, StrLit, StrPrefix,
WithSpan, can_be_variable_name, char_lit, cut_error, filter, identifier, keyword,
not_suffix_with_hash, num_lit, path_or_identifier, skip_ws0, skip_ws1, str_lit, ws,
};
macro_rules! expr_prec_layer {
@ -253,7 +252,7 @@ impl<'a> Expr<'a> {
level: Level<'_>,
) -> ParseResult<'a, Vec<WithSpan<'a, Box<Self>>>> {
let _level_guard = level.nest(i)?;
let mut named_arguments = HashSet::new();
let mut named_arguments = HashSet::default();
let start = *i;
preceded(

View File

@ -18,6 +18,7 @@ use std::path::Path;
use std::sync::Arc;
use std::{fmt, str};
use rustc_hash::FxBuildHasher;
use winnow::ascii::take_escaped;
use winnow::combinator::{
alt, cut_err, delimited, empty, fail, not, opt, peek, preceded, repeat, terminated,
@ -1463,6 +1464,8 @@ fn cut_context_err<'a, T>(gen_err: impl FnOnce() -> ErrorContext<'a>) -> ParseRe
Err(ErrMode::Cut(gen_err()))
}
type HashSet<T> = std::collections::hash_set::HashSet<T, FxBuildHasher>;
#[cfg(not(windows))]
#[cfg(test)]
mod test {

View File

@ -1,4 +1,3 @@
use std::collections::HashSet;
use std::str::{self, FromStr};
use winnow::combinator::{
@ -11,8 +10,8 @@ use winnow::token::{any, rest, take_until};
use winnow::{ModalParser, Parser};
use crate::{
ErrorContext, Expr, Filter, ParseResult, Span, State, Target, WithSpan, cut_error, filter,
identifier, is_rust_keyword, keyword, skip_ws0, str_lit_without_prefix, ws,
ErrorContext, Expr, Filter, HashSet, ParseResult, Span, State, Target, WithSpan, cut_error,
filter, identifier, is_rust_keyword, keyword, skip_ws0, str_lit_without_prefix, ws,
};
#[derive(Debug, PartialEq)]
@ -685,7 +684,7 @@ impl<'a> Macro<'a> {
}
if let Some(ref params) = params {
let mut names = HashSet::new();
let mut names = HashSet::default();
let mut iter = params.iter();
while let Some((arg_name, default_value)) = iter.next() {