Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #20164 from ChayimFriedman2/fix-edition
fix: Pass the correct per-token (not global) edition when expanding macro_rules
Chayim Refael Friedman 5 months ago
parent 2d2ca30 · parent 97f0401 · commit 8cec5e5
-rw-r--r--Cargo.lock1
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mbe.rs52
-rw-r--r--crates/hir-expand/src/builtin/fn_macro.rs4
-rw-r--r--crates/hir-expand/src/db.rs2
-rw-r--r--crates/hir-expand/src/declarative.rs6
-rw-r--r--crates/mbe/Cargo.toml1
-rw-r--r--crates/mbe/src/benchmark.rs14
-rw-r--r--crates/mbe/src/expander.rs6
-rw-r--r--crates/mbe/src/expander/matcher.rs22
-rw-r--r--crates/mbe/src/lib.rs9
-rw-r--r--crates/mbe/src/tests.rs3
11 files changed, 64 insertions, 56 deletions
diff --git a/Cargo.lock b/Cargo.lock
index fe839f2a70..e21776cdab 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1475,6 +1475,7 @@ dependencies = [
"parser",
"ra-ap-rustc_lexer",
"rustc-hash 2.1.1",
+ "salsa",
"smallvec",
"span",
"stdx",
diff --git a/crates/hir-def/src/macro_expansion_tests/mbe.rs b/crates/hir-def/src/macro_expansion_tests/mbe.rs
index c489c1f7c1..445caef85f 100644
--- a/crates/hir-def/src/macro_expansion_tests/mbe.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mbe.rs
@@ -1959,28 +1959,6 @@ fn f() {
}
#[test]
-fn test_edition_handling_in() {
- check(
- r#"
-//- /main.rs crate:main deps:old edition:2021
-fn f() {
- old::parse_try_old!(try!{});
-}
-//- /old.rs crate:old edition:2015
-#[macro_export]
-macro_rules! parse_try_old {
- ($it:expr) => {};
-}
- "#,
- expect![[r#"
-fn f() {
- ;
-}
-"#]],
- );
-}
-
-#[test]
fn semicolon_does_not_glue() {
check(
r#"
@@ -2051,3 +2029,33 @@ fn f() {
"#]],
);
}
+
+#[test]
+fn per_token_edition() {
+ check(
+ r#"
+//- /foo.rs crate:foo edition:2024
+#[macro_export]
+macro_rules! m {
+ ($e:expr) => {};
+}
+//- /bar.rs crate:bar deps:foo edition:2021
+fn gen() -> usize {
+ 0
+}
+
+fn foo() {
+ foo::m!(gen());
+}
+ "#,
+ expect![[r#"
+fn gen() -> usize {
+ 0
+}
+
+fn foo() {
+ ;
+}
+ "#]],
+ );
+}
diff --git a/crates/hir-expand/src/builtin/fn_macro.rs b/crates/hir-expand/src/builtin/fn_macro.rs
index 6fe63f249c..56f68d8277 100644
--- a/crates/hir-expand/src/builtin/fn_macro.rs
+++ b/crates/hir-expand/src/builtin/fn_macro.rs
@@ -18,7 +18,7 @@ use syntax::{
use syntax_bridge::syntax_node_to_token_tree;
use crate::{
- EditionedFileId, ExpandError, ExpandResult, Lookup as _, MacroCallId,
+ EditionedFileId, ExpandError, ExpandResult, MacroCallId,
builtin::quote::{WithDelimiter, dollar_crate},
db::ExpandDatabase,
hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt},
@@ -230,9 +230,9 @@ fn assert_expand(
let mut iter = tt.iter();
let cond = expect_fragment(
+ db,
&mut iter,
parser::PrefixEntryPoint::Expr,
- id.lookup(db).krate.data(db).edition,
tt.top_subtree().delimiter.delim_span(),
);
_ = iter.expect_char(',');
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index d1e681a1c7..944161ff00 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -299,7 +299,7 @@ pub fn expand_speculative(
}
MacroDefKind::Declarative(it, _) => db
.decl_macro_expander(loc.krate, it)
- .expand_unhygienic(tt, loc.kind.call_style(), span, loc.def.edition),
+ .expand_unhygienic(db, tt, loc.kind.call_style(), span),
MacroDefKind::BuiltIn(_, it) => {
it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
}
diff --git a/crates/hir-expand/src/declarative.rs b/crates/hir-expand/src/declarative.rs
index e4375e05d2..d36d85a141 100644
--- a/crates/hir-expand/src/declarative.rs
+++ b/crates/hir-expand/src/declarative.rs
@@ -42,6 +42,7 @@ impl DeclarativeMacroExpander {
None => self
.mac
.expand(
+ db,
&tt,
|s| {
s.ctx =
@@ -49,7 +50,6 @@ impl DeclarativeMacroExpander {
},
loc.kind.call_style(),
span,
- loc.def.edition,
)
.map_err(Into::into),
}
@@ -57,10 +57,10 @@ impl DeclarativeMacroExpander {
pub fn expand_unhygienic(
&self,
+ db: &dyn ExpandDatabase,
tt: tt::TopSubtree,
call_style: MacroCallStyle,
call_site: Span,
- def_site_edition: Edition,
) -> ExpandResult<tt::TopSubtree> {
match self.mac.err() {
Some(_) => ExpandResult::new(
@@ -69,7 +69,7 @@ impl DeclarativeMacroExpander {
),
None => self
.mac
- .expand(&tt, |_| (), call_style, call_site, def_site_edition)
+ .expand(db, &tt, |_| (), call_style, call_site)
.map(TupleExt::head)
.map_err(Into::into),
}
diff --git a/crates/mbe/Cargo.toml b/crates/mbe/Cargo.toml
index 9e262c3539..b6e55b9360 100644
--- a/crates/mbe/Cargo.toml
+++ b/crates/mbe/Cargo.toml
@@ -18,6 +18,7 @@ rustc-hash.workspace = true
smallvec.workspace = true
arrayvec.workspace = true
ra-ap-rustc_lexer.workspace = true
+salsa.workspace = true
bitflags.workspace = true
# local deps
diff --git a/crates/mbe/src/benchmark.rs b/crates/mbe/src/benchmark.rs
index 9e4b78c2d8..ffe3bdd06c 100644
--- a/crates/mbe/src/benchmark.rs
+++ b/crates/mbe/src/benchmark.rs
@@ -2,7 +2,7 @@
use intern::Symbol;
use rustc_hash::FxHashMap;
-use span::{Edition, Span};
+use span::Span;
use stdx::itertools::Itertools;
use syntax::{
AstNode,
@@ -44,16 +44,16 @@ fn benchmark_expand_macro_rules() {
if skip_slow_tests() {
return;
}
+ let db = salsa::DatabaseImpl::default();
let rules = macro_rules_fixtures();
- let invocations = invocation_fixtures(&rules);
+ let invocations = invocation_fixtures(&db, &rules);
let hash: usize = {
let _pt = bench("mbe expand macro rules");
invocations
.into_iter()
.map(|(id, tt)| {
- let res =
- rules[&id].expand(&tt, |_| (), MacroCallStyle::FnLike, DUMMY, Edition::CURRENT);
+ let res = rules[&id].expand(&db, &tt, |_| (), MacroCallStyle::FnLike, DUMMY);
assert!(res.err.is_none());
res.value.0.0.len()
})
@@ -93,6 +93,7 @@ fn macro_rules_fixtures_tt() -> FxHashMap<String, tt::TopSubtree<Span>> {
/// Generate random invocation fixtures from rules
fn invocation_fixtures(
+ db: &dyn salsa::Database,
rules: &FxHashMap<String, DeclarativeMacro>,
) -> Vec<(String, tt::TopSubtree<Span>)> {
let mut seed = 123456789;
@@ -124,10 +125,7 @@ fn invocation_fixtures(
}
let subtree = builder.build();
- if it
- .expand(&subtree, |_| (), MacroCallStyle::FnLike, DUMMY, Edition::CURRENT)
- .err
- .is_none()
+ if it.expand(db, &subtree, |_| (), MacroCallStyle::FnLike, DUMMY).err.is_none()
{
res.push((name.clone(), subtree));
break;
diff --git a/crates/mbe/src/expander.rs b/crates/mbe/src/expander.rs
index 507402197e..6510fefcb6 100644
--- a/crates/mbe/src/expander.rs
+++ b/crates/mbe/src/expander.rs
@@ -7,7 +7,7 @@ mod transcriber;
use intern::Symbol;
use rustc_hash::FxHashMap;
-use span::{Edition, Span};
+use span::Span;
use crate::{
ExpandError, ExpandErrorKind, ExpandResult, MacroCallStyle, MatchedArmIndex,
@@ -15,12 +15,12 @@ use crate::{
};
pub(crate) fn expand_rules(
+ db: &dyn salsa::Database,
rules: &[crate::Rule],
input: &tt::TopSubtree<Span>,
marker: impl Fn(&mut Span) + Copy,
call_style: MacroCallStyle,
call_site: Span,
- def_site_edition: Edition,
) -> ExpandResult<(tt::TopSubtree<Span>, MatchedArmIndex)> {
let mut match_: Option<(matcher::Match<'_>, &crate::Rule, usize)> = None;
for (idx, rule) in rules.iter().enumerate() {
@@ -29,7 +29,7 @@ pub(crate) fn expand_rules(
continue;
}
- let new_match = matcher::match_(&rule.lhs, input, def_site_edition);
+ let new_match = matcher::match_(db, &rule.lhs, input);
if new_match.err.is_none() {
// If we find a rule that applies without errors, we're done.
diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs
index 189efcd15c..4da8b309f0 100644
--- a/crates/mbe/src/expander/matcher.rs
+++ b/crates/mbe/src/expander/matcher.rs
@@ -63,7 +63,7 @@ use std::{rc::Rc, sync::Arc};
use intern::{Symbol, sym};
use smallvec::{SmallVec, smallvec};
-use span::{Edition, Span};
+use span::Span;
use tt::{
DelimSpan,
iter::{TtElement, TtIter},
@@ -112,11 +112,11 @@ impl Match<'_> {
/// Matching errors are added to the `Match`.
pub(super) fn match_<'t>(
+ db: &dyn salsa::Database,
pattern: &'t MetaTemplate,
input: &'t tt::TopSubtree<Span>,
- edition: Edition,
) -> Match<'t> {
- let mut res = match_loop(pattern, input, edition);
+ let mut res = match_loop(db, pattern, input);
res.bound_count = count(res.bindings.bindings());
return res;
@@ -365,6 +365,7 @@ struct MatchState<'t> {
/// - `error_items`: the set of items in errors, used for error-resilient parsing
#[inline]
fn match_loop_inner<'t>(
+ db: &dyn salsa::Database,
src: TtIter<'t, Span>,
stack: &[TtIter<'t, Span>],
res: &mut Match<'t>,
@@ -375,7 +376,6 @@ fn match_loop_inner<'t>(
eof_items: &mut SmallVec<[MatchState<'t>; 1]>,
error_items: &mut SmallVec<[MatchState<'t>; 1]>,
delim_span: tt::DelimSpan<Span>,
- edition: Edition,
) {
macro_rules! try_push {
($items: expr, $it:expr) => {
@@ -486,7 +486,7 @@ fn match_loop_inner<'t>(
OpDelimited::Op(Op::Var { kind, name, .. }) => {
if let &Some(kind) = kind {
let mut fork = src.clone();
- let match_res = match_meta_var(kind, &mut fork, delim_span, edition);
+ let match_res = match_meta_var(db, kind, &mut fork, delim_span);
match match_res.err {
None => {
// Some meta variables are optional (e.g. vis)
@@ -621,9 +621,9 @@ fn match_loop_inner<'t>(
}
fn match_loop<'t>(
+ db: &dyn salsa::Database,
pattern: &'t MetaTemplate,
src: &'t tt::TopSubtree<Span>,
- edition: Edition,
) -> Match<'t> {
let span = src.top_subtree().delimiter.delim_span();
let mut src = src.iter();
@@ -655,6 +655,7 @@ fn match_loop<'t>(
stdx::always!(next_items.is_empty());
match_loop_inner(
+ db,
src.clone(),
&stack,
&mut res,
@@ -665,7 +666,6 @@ fn match_loop<'t>(
&mut eof_items,
&mut error_items,
span,
- edition,
);
stdx::always!(cur_items.is_empty());
@@ -772,14 +772,14 @@ fn match_loop<'t>(
}
fn match_meta_var<'t>(
+ db: &dyn salsa::Database,
kind: MetaVarKind,
input: &mut TtIter<'t, Span>,
delim_span: DelimSpan<Span>,
- edition: Edition,
) -> ExpandResult<Fragment<'t>> {
let fragment = match kind {
MetaVarKind::Path => {
- return expect_fragment(input, parser::PrefixEntryPoint::Path, edition, delim_span)
+ return expect_fragment(db, input, parser::PrefixEntryPoint::Path, delim_span)
.map(Fragment::Path);
}
MetaVarKind::Expr(expr) => {
@@ -807,7 +807,7 @@ fn match_meta_var<'t>(
}
_ => {}
};
- return expect_fragment(input, parser::PrefixEntryPoint::Expr, edition, delim_span)
+ return expect_fragment(db, input, parser::PrefixEntryPoint::Expr, delim_span)
.map(Fragment::Expr);
}
MetaVarKind::Ident | MetaVarKind::Tt | MetaVarKind::Lifetime | MetaVarKind::Literal => {
@@ -853,7 +853,7 @@ fn match_meta_var<'t>(
MetaVarKind::Item => parser::PrefixEntryPoint::Item,
MetaVarKind::Vis => parser::PrefixEntryPoint::Vis,
};
- expect_fragment(input, fragment, edition, delim_span).map(Fragment::Tokens)
+ expect_fragment(db, input, fragment, delim_span).map(Fragment::Tokens)
}
fn collect_vars(collector_fun: &mut impl FnMut(Symbol), pattern: &MetaTemplate) {
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs
index f301d256f5..1193c4290c 100644
--- a/crates/mbe/src/lib.rs
+++ b/crates/mbe/src/lib.rs
@@ -275,13 +275,13 @@ impl DeclarativeMacro {
pub fn expand(
&self,
+ db: &dyn salsa::Database,
tt: &tt::TopSubtree<Span>,
marker: impl Fn(&mut Span) + Copy,
call_style: MacroCallStyle,
call_site: Span,
- def_site_edition: Edition,
) -> ExpandResult<(tt::TopSubtree<Span>, MatchedArmIndex)> {
- expander::expand_rules(&self.rules, tt, marker, call_style, call_site, def_site_edition)
+ expander::expand_rules(db, &self.rules, tt, marker, call_style, call_site)
}
}
@@ -390,15 +390,14 @@ impl<T: Default, E> From<Result<T, E>> for ValueResult<T, E> {
}
pub fn expect_fragment<'t>(
+ db: &dyn salsa::Database,
tt_iter: &mut TtIter<'t, Span>,
entry_point: ::parser::PrefixEntryPoint,
- edition: ::parser::Edition,
delim_span: DelimSpan<Span>,
) -> ExpandResult<tt::TokenTreesView<'t, Span>> {
use ::parser;
let buffer = tt_iter.remaining();
- // FIXME: Pass the correct edition per token. Due to the split between mbe and hir-expand it's complicated.
- let parser_input = to_parser_input(buffer, &mut |_ctx| edition);
+ let parser_input = to_parser_input(buffer, &mut |ctx| ctx.edition(db));
let tree_traversal = entry_point.parse(&parser_input);
let mut cursor = buffer.cursor();
let mut error = false;
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs
index 98ed0a3222..4a1af31656 100644
--- a/crates/mbe/src/tests.rs
+++ b/crates/mbe/src/tests.rs
@@ -22,6 +22,7 @@ fn check_(
expect: expect_test::Expect,
parse: parser::TopEntryPoint,
) {
+ let db = salsa::DatabaseImpl::default();
let decl_tt = &syntax_bridge::parse_to_token_tree(
def_edition,
SpanAnchor {
@@ -49,6 +50,7 @@ fn check_(
)
.unwrap();
let res = mac.expand(
+ &db,
&arg_tt,
|_| (),
crate::MacroCallStyle::FnLike,
@@ -57,7 +59,6 @@ fn check_(
anchor: call_anchor,
ctx: SyntaxContext::root(Edition::CURRENT),
},
- def_edition,
);
let mut expect_res = String::new();
if let Some(err) = res.err {