Merge pull request #19474 from Veykril/push-nokkzzvwynnt

fix: Fix, clarify and require a value for `proc_macro_cwd` of `CrateData`
This commit is contained in:
Lukas Wirth 2025-03-29 07:24:39 +00:00 committed by GitHub
commit a73a37a757
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 143 additions and 74 deletions

View File

@ -24,7 +24,6 @@ jobs:
pull-requests: read
outputs:
typescript: ${{ steps.filter.outputs.typescript }}
proc_macros: ${{ steps.filter.outputs.proc_macros }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@1441771bbfdd59dcd748680ee64ebd8faab1a242
@ -33,15 +32,10 @@ jobs:
filters: |
typescript:
- 'editors/code/**'
proc_macros:
- 'crates/tt/**'
- 'crates/proc-macro-api/**'
- 'crates/proc-macro-srv/**'
- 'crates/proc-macro-srv-cli/**'
proc-macro-srv:
needs: changes
if: github.repository == 'rust-lang/rust-analyzer' && needs.changes.outputs.proc_macros == 'true'
if: github.repository == 'rust-lang/rust-analyzer'
name: proc-macro-srv
runs-on: ubuntu-latest
env:

1
Cargo.lock generated
View File

@ -2305,6 +2305,7 @@ dependencies = [
"cfg",
"hir-expand",
"intern",
"paths",
"rustc-hash 2.1.1",
"span",
"stdx",

View File

@ -303,9 +303,11 @@ pub struct CrateData<Id> {
pub dependencies: Vec<Dependency<Id>>,
pub origin: CrateOrigin,
pub is_proc_macro: bool,
/// The working directory to run proc-macros in. This is the workspace root of the cargo workspace
/// for workspace members, the crate manifest dir otherwise.
pub proc_macro_cwd: Option<AbsPathBuf>,
/// The working directory to run proc-macros in invoked in the context of this crate.
/// This is the workspace root of the cargo workspace for workspace members, the crate manifest
/// dir otherwise.
// FIXME: This ought to be a `VfsPath` or something opaque.
pub proc_macro_cwd: Arc<AbsPathBuf>,
}
pub type CrateDataBuilder = CrateData<CrateBuilderId>;
@ -425,7 +427,7 @@ impl CrateGraphBuilder {
mut env: Env,
origin: CrateOrigin,
is_proc_macro: bool,
proc_macro_cwd: Option<AbsPathBuf>,
proc_macro_cwd: Arc<AbsPathBuf>,
ws_data: Arc<CrateWorkspaceData>,
) -> CrateBuilderId {
env.entries.shrink_to_fit();
@ -861,6 +863,7 @@ impl fmt::Display for CyclicDependenciesError {
#[cfg(test)]
mod tests {
use triomphe::Arc;
use vfs::AbsPathBuf;
use crate::{CrateWorkspaceData, DependencyBuilder};
@ -883,7 +886,7 @@ mod tests {
Env::default(),
CrateOrigin::Local { repo: None, name: None },
false,
None,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
);
let crate2 = graph.add_crate_root(
@ -896,7 +899,7 @@ mod tests {
Env::default(),
CrateOrigin::Local { repo: None, name: None },
false,
None,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
);
let crate3 = graph.add_crate_root(
@ -909,7 +912,7 @@ mod tests {
Env::default(),
CrateOrigin::Local { repo: None, name: None },
false,
None,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
);
assert!(
@ -942,7 +945,7 @@ mod tests {
Env::default(),
CrateOrigin::Local { repo: None, name: None },
false,
None,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
);
let crate2 = graph.add_crate_root(
@ -955,7 +958,7 @@ mod tests {
Env::default(),
CrateOrigin::Local { repo: None, name: None },
false,
None,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
);
assert!(
@ -983,7 +986,7 @@ mod tests {
Env::default(),
CrateOrigin::Local { repo: None, name: None },
false,
None,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
);
let crate2 = graph.add_crate_root(
@ -996,7 +999,7 @@ mod tests {
Env::default(),
CrateOrigin::Local { repo: None, name: None },
false,
None,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
);
let crate3 = graph.add_crate_root(
@ -1009,7 +1012,7 @@ mod tests {
Env::default(),
CrateOrigin::Local { repo: None, name: None },
false,
None,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
);
assert!(
@ -1037,7 +1040,7 @@ mod tests {
Env::default(),
CrateOrigin::Local { repo: None, name: None },
false,
None,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
);
let crate2 = graph.add_crate_root(
@ -1050,7 +1053,7 @@ mod tests {
Env::default(),
CrateOrigin::Local { repo: None, name: None },
false,
None,
Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap())),
empty_ws_data(),
);
assert!(

View File

@ -362,7 +362,7 @@ impl ProcMacroExpander for IdentityWhenValidProcMacroExpander {
_: Span,
_: Span,
_: Span,
_: Option<String>,
_: String,
) -> Result<TopSubtree, ProcMacroExpansionError> {
let (parse, _) = syntax_bridge::token_tree_to_syntax_node(
subtree,

View File

@ -52,6 +52,7 @@ pub const BAZ: u32 = 0;
{
// Add a dependency a -> b.
let mut new_crate_graph = CrateGraphBuilder::default();
let mut add_crate = |crate_name, root_file_idx: usize| {
new_crate_graph.add_crate_root(
files[root_file_idx].file_id(),
@ -63,7 +64,13 @@ pub const BAZ: u32 = 0;
Env::default(),
CrateOrigin::Local { repo: None, name: Some(Symbol::intern(crate_name)) },
false,
None,
Arc::new(
// FIXME: This is less than ideal
TryFrom::try_from(
&*std::env::current_dir().unwrap().as_path().to_string_lossy(),
)
.unwrap(),
),
Arc::new(CrateWorkspaceData { data_layout: Err("".into()), toolchain: None }),
)
};

View File

@ -41,7 +41,7 @@ pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe + AsAny {
def_site: Span,
call_site: Span,
mixed_site: Span,
current_dir: Option<String>,
current_dir: String,
) -> Result<tt::TopSubtree, ProcMacroExpansionError>;
fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool;
@ -318,8 +318,8 @@ impl CustomProcMacroExpander {
// Proc macros have access to the environment variables of the invoking crate.
let env = calling_crate.env(db);
let current_dir =
calling_crate.data(db).proc_macro_cwd.as_deref().map(ToString::to_string);
// FIXME: Can we avoid the string allocation here?
let current_dir = calling_crate.data(db).proc_macro_cwd.to_string();
match proc_macro.expander.expand(
tt,

View File

@ -244,6 +244,12 @@ impl Analysis {
// FIXME: cfg options
// Default to enable test for single file.
let mut cfg_options = CfgOptions::default();
// FIXME: This is less than ideal
let proc_macro_cwd = Arc::new(
TryFrom::try_from(&*std::env::current_dir().unwrap().as_path().to_string_lossy())
.unwrap(),
);
cfg_options.insert_atom(sym::test.clone());
crate_graph.add_crate_root(
file_id,
@ -255,7 +261,7 @@ impl Analysis {
Env::default(),
CrateOrigin::Local { repo: None, name: None },
false,
None,
proc_macro_cwd,
Arc::new(CrateWorkspaceData {
data_layout: Err("fixture has no layout".into()),
toolchain: None,

View File

@ -496,7 +496,7 @@ impl ProcMacroExpander for Expander {
def_site: Span,
call_site: Span,
mixed_site: Span,
current_dir: Option<String>,
current_dir: String,
) -> Result<tt::TopSubtree<Span>, ProcMacroExpansionError> {
match self.0.expand(
subtree.view(),

View File

@ -170,7 +170,7 @@ impl ProcMacro {
def_site: Span,
call_site: Span,
mixed_site: Span,
current_dir: Option<String>,
current_dir: String,
) -> Result<Result<tt::TopSubtree<Span>, PanicMessage>, ServerError> {
let version = self.process.version();
@ -198,7 +198,7 @@ impl ProcMacro {
},
lib: self.dylib_path.to_path_buf().into(),
env,
current_dir,
current_dir: Some(current_dir),
};
let response = self.process.send_task(Request::ExpandMacro(Box::new(task)))?;

View File

@ -988,6 +988,7 @@ fn project_json_to_crate_graph(
);
let mut cfg_cache: FxHashMap<&str, Vec<CfgAtom>> = FxHashMap::default();
let project_root = Arc::new(project.project_root().to_path_buf());
let idx_to_crate_id: FxHashMap<CrateArrayIdx, _> = project
.crates()
@ -1067,7 +1068,10 @@ fn project_json_to_crate_graph(
CrateOrigin::Local { repo: None, name: None }
},
*is_proc_macro,
proc_macro_cwd.clone(),
match proc_macro_cwd {
Some(path) => Arc::new(path.clone()),
None => project_root.clone(),
},
crate_ws_data.clone(),
);
debug!(
@ -1139,6 +1143,7 @@ fn cargo_to_crate_graph(
let mut pkg_crates = FxHashMap::default();
// Does any crate signal to rust-analyzer that they need the rustc_private crates?
let mut has_private = false;
let workspace_proc_macro_cwd = Arc::new(cargo.workspace_root().to_path_buf());
// Next, create crates for each package, target pair
for pkg in cargo.packages() {
@ -1161,8 +1166,9 @@ fn cargo_to_crate_graph(
let mut lib_tgt = None;
for &tgt in cargo[pkg].targets.iter() {
let pkg_data = &cargo[pkg];
if !matches!(cargo[tgt].kind, TargetKind::Lib { .. })
&& (!cargo[pkg].is_member || cargo.is_sysroot())
&& (!pkg_data.is_member || cargo.is_sysroot())
{
// For non-workspace-members, Cargo does not resolve dev-dependencies, so we don't
// add any targets except the library target, since those will not work correctly if
@ -1176,7 +1182,6 @@ fn cargo_to_crate_graph(
let Some(file_id) = load(root) else { continue };
let build_data = build_scripts.get_output(pkg);
let pkg_data = &cargo[pkg];
let crate_id = add_target_crate_root(
crate_graph,
proc_macros,
@ -1203,6 +1208,11 @@ fn cargo_to_crate_graph(
}
},
crate_ws_data.clone(),
if pkg_data.is_member {
workspace_proc_macro_cwd.clone()
} else {
Arc::new(pkg_data.manifest.parent().to_path_buf())
},
);
if let TargetKind::Lib { .. } = kind {
lib_tgt = Some((crate_id, name.clone()));
@ -1364,7 +1374,7 @@ fn detached_file_to_crate_graph(
name: display_name.map(|n| n.canonical_name().to_owned()),
},
false,
None,
Arc::new(detached_file.parent().to_path_buf()),
crate_ws_data,
);
@ -1372,6 +1382,7 @@ fn detached_file_to_crate_graph(
(crate_graph, FxHashMap::default())
}
// FIXME: There shouldn't really be a need for duplicating all of this?
fn handle_rustc_crates(
crate_graph: &mut CrateGraphBuilder,
proc_macros: &mut ProcMacroPaths,
@ -1391,6 +1402,7 @@ fn handle_rustc_crates(
// The root package of the rustc-dev component is rustc_driver, so we match that
let root_pkg =
rustc_workspace.packages().find(|&package| rustc_workspace[package].name == "rustc_driver");
let workspace_proc_macro_cwd = Arc::new(cargo.workspace_root().to_path_buf());
// The rustc workspace might be incomplete (such as if rustc-dev is not
// installed for the current toolchain) and `rustc_source` is set to discover.
if let Some(root_pkg) = root_pkg {
@ -1404,14 +1416,15 @@ fn handle_rustc_crates(
if rustc_pkg_crates.contains_key(&pkg) {
continue;
}
for dep in &rustc_workspace[pkg].dependencies {
let pkg_data = &rustc_workspace[pkg];
for dep in &pkg_data.dependencies {
queue.push_back(dep.pkg);
}
let mut cfg_options = cfg_options.clone();
override_cfg.apply(&mut cfg_options, &rustc_workspace[pkg].name);
override_cfg.apply(&mut cfg_options, &pkg_data.name);
for &tgt in rustc_workspace[pkg].targets.iter() {
for &tgt in pkg_data.targets.iter() {
let kind @ TargetKind::Lib { is_proc_macro } = rustc_workspace[tgt].kind else {
continue;
};
@ -1421,14 +1434,19 @@ fn handle_rustc_crates(
crate_graph,
proc_macros,
rustc_workspace,
&rustc_workspace[pkg],
pkg_data,
build_scripts.get_output(pkg).zip(Some(build_scripts.error().is_some())),
cfg_options.clone(),
file_id,
&rustc_workspace[tgt].name,
kind,
CrateOrigin::Rustc { name: Symbol::intern(&rustc_workspace[pkg].name) },
CrateOrigin::Rustc { name: Symbol::intern(&pkg_data.name) },
crate_ws_data.clone(),
if pkg_data.is_member {
workspace_proc_macro_cwd.clone()
} else {
Arc::new(pkg_data.manifest.parent().to_path_buf())
},
);
pkg_to_lib_crate.insert(pkg, crate_id);
// Add dependencies on core / std / alloc for this crate
@ -1490,6 +1508,7 @@ fn add_target_crate_root(
kind: TargetKind,
origin: CrateOrigin,
crate_ws_data: Arc<CrateWorkspaceData>,
proc_macro_cwd: Arc<AbsPathBuf>,
) -> CrateBuilderId {
let edition = pkg.edition;
let potential_cfg_options = if pkg.features.is_empty() {
@ -1531,9 +1550,7 @@ fn add_target_crate_root(
env,
origin,
matches!(kind, TargetKind::Lib { is_proc_macro: true }),
matches!(kind, TargetKind::Lib { is_proc_macro: true }).then(|| {
if pkg.is_member { cargo.workspace_root() } else { pkg.manifest.parent() }.to_path_buf()
}),
proc_macro_cwd,
crate_ws_data,
);
if let TargetKind::Lib { is_proc_macro: true } = kind {
@ -1706,7 +1723,7 @@ fn sysroot_to_crate_graph(
Env::default(),
CrateOrigin::Lang(LangCrateOrigin::from(&*stitched[krate].name)),
false,
None,
Arc::new(stitched[krate].root.parent().to_path_buf()),
crate_ws_data.clone(),
);
Some((krate, crate_id))

View File

@ -22,7 +22,9 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$hello-world",
),
},
extra: ExtraCrateData {
version: Some(
@ -104,7 +106,9 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$hello-world",
),
},
extra: ExtraCrateData {
version: Some(
@ -186,7 +190,9 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$hello-world",
),
},
extra: ExtraCrateData {
version: Some(
@ -268,7 +274,9 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$hello-world",
),
},
extra: ExtraCrateData {
version: Some(
@ -333,7 +341,9 @@
name: "libc",
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
),
},
extra: ExtraCrateData {
version: Some(

View File

@ -22,7 +22,9 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$hello-world",
),
},
extra: ExtraCrateData {
version: Some(
@ -104,7 +106,9 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$hello-world",
),
},
extra: ExtraCrateData {
version: Some(
@ -186,7 +190,9 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$hello-world",
),
},
extra: ExtraCrateData {
version: Some(
@ -268,7 +274,9 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$hello-world",
),
},
extra: ExtraCrateData {
version: Some(
@ -333,7 +341,9 @@
name: "libc",
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
),
},
extra: ExtraCrateData {
version: Some(

View File

@ -22,7 +22,9 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$hello-world",
),
},
extra: ExtraCrateData {
version: Some(
@ -103,7 +105,9 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$hello-world",
),
},
extra: ExtraCrateData {
version: Some(
@ -184,7 +188,9 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$hello-world",
),
},
extra: ExtraCrateData {
version: Some(
@ -265,7 +271,9 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$hello-world",
),
},
extra: ExtraCrateData {
version: Some(
@ -329,7 +337,9 @@
name: "libc",
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
),
},
extra: ExtraCrateData {
version: Some(

View File

@ -13,7 +13,9 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$",
),
},
extra: ExtraCrateData {
version: None,
@ -61,7 +63,9 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$",
),
},
extra: ExtraCrateData {
version: None,

View File

@ -13,7 +13,9 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
proc_macro_cwd: AbsPathBuf(
"$ROOT$",
),
},
extra: ExtraCrateData {
version: None,

View File

@ -19,6 +19,7 @@ span.workspace = true
stdx.workspace = true
intern.workspace = true
triomphe.workspace = true
paths.workspace = true
[lints]
workspace = true

View File

@ -19,6 +19,7 @@ use hir_expand::{
tt::{Leaf, TokenTree, TopSubtree, TopSubtreeBuilder, TtElement, TtIter},
};
use intern::{Symbol, sym};
use paths::AbsPathBuf;
use rustc_hash::FxHashMap;
use span::{Edition, EditionedFileId, FileId, Span};
use stdx::itertools::Itertools;
@ -162,6 +163,9 @@ impl ChangeFixture {
let crate_ws_data =
Arc::new(CrateWorkspaceData { data_layout: target_data_layout, toolchain });
// FIXME: This is less than ideal
let proc_macro_cwd = Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap()));
for entry in fixture {
let mut range_or_offset = None;
let text = if entry.text.contains(CURSOR_MARKER) {
@ -213,7 +217,7 @@ impl ChangeFixture {
meta.env,
origin,
false,
None,
proc_macro_cwd.clone(),
crate_ws_data.clone(),
);
let prev = crates.insert(crate_name.clone(), crate_id);
@ -254,7 +258,7 @@ impl ChangeFixture {
default_env,
CrateOrigin::Local { repo: None, name: None },
false,
None,
proc_macro_cwd.clone(),
crate_ws_data.clone(),
);
} else {
@ -296,7 +300,7 @@ impl ChangeFixture {
)]),
CrateOrigin::Lang(LangCrateOrigin::Core),
false,
None,
proc_macro_cwd.clone(),
crate_ws_data.clone(),
);
@ -345,7 +349,7 @@ impl ChangeFixture {
)]),
CrateOrigin::Local { repo: None, name: None },
true,
None,
proc_macro_cwd.clone(),
crate_ws_data,
);
proc_macros.insert(proc_macros_crate, Ok(proc_macro));
@ -650,7 +654,7 @@ impl ProcMacroExpander for IdentityProcMacroExpander {
_: Span,
_: Span,
_: Span,
_: Option<String>,
_: String,
) -> Result<TopSubtree, ProcMacroExpansionError> {
Ok(subtree.clone())
}
@ -672,7 +676,7 @@ impl ProcMacroExpander for Issue18089ProcMacroExpander {
_: Span,
call_site: Span,
_: Span,
_: Option<String>,
_: String,
) -> Result<TopSubtree, ProcMacroExpansionError> {
let tt::TokenTree::Leaf(macro_name) = &subtree.0[2] else {
return Err(ProcMacroExpansionError::Panic("incorrect input".to_owned()));
@ -707,7 +711,7 @@ impl ProcMacroExpander for AttributeInputReplaceProcMacroExpander {
_: Span,
_: Span,
_: Span,
_: Option<String>,
_: String,
) -> Result<TopSubtree, ProcMacroExpansionError> {
attrs
.cloned()
@ -730,7 +734,7 @@ impl ProcMacroExpander for Issue18840ProcMacroExpander {
def_site: Span,
_: Span,
_: Span,
_: Option<String>,
_: String,
) -> Result<TopSubtree, ProcMacroExpansionError> {
// Input:
// ```
@ -765,7 +769,7 @@ impl ProcMacroExpander for MirrorProcMacroExpander {
_: Span,
_: Span,
_: Span,
_: Option<String>,
_: String,
) -> Result<TopSubtree, ProcMacroExpansionError> {
fn traverse(builder: &mut TopSubtreeBuilder, iter: TtIter<'_>) {
for tt in iter.collect_vec().into_iter().rev() {
@ -803,7 +807,7 @@ impl ProcMacroExpander for ShortenProcMacroExpander {
_: Span,
_: Span,
_: Span,
_: Option<String>,
_: String,
) -> Result<TopSubtree, ProcMacroExpansionError> {
let mut result = input.0.clone();
for it in &mut result {
@ -845,7 +849,7 @@ impl ProcMacroExpander for Issue17479ProcMacroExpander {
_: Span,
_: Span,
_: Span,
_: Option<String>,
_: String,
) -> Result<TopSubtree, ProcMacroExpansionError> {
let TokenTree::Leaf(Leaf::Literal(lit)) = &subtree.0[1] else {
return Err(ProcMacroExpansionError::Panic("incorrect Input".into()));
@ -874,7 +878,7 @@ impl ProcMacroExpander for Issue18898ProcMacroExpander {
def_site: Span,
_: Span,
_: Span,
_: Option<String>,
_: String,
) -> Result<TopSubtree, ProcMacroExpansionError> {
let span = subtree
.token_trees()
@ -929,7 +933,7 @@ impl ProcMacroExpander for DisallowCfgProcMacroExpander {
_: Span,
_: Span,
_: Span,
_: Option<String>,
_: String,
) -> Result<TopSubtree, ProcMacroExpansionError> {
for tt in subtree.token_trees().flat_tokens() {
if let tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = tt {