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
| -rw-r--r-- | Cargo.lock | 1 | ||||
| -rw-r--r-- | crates/hir-def/src/macro_expansion_tests/mbe.rs | 52 | ||||
| -rw-r--r-- | crates/hir-expand/src/builtin/fn_macro.rs | 4 | ||||
| -rw-r--r-- | crates/hir-expand/src/db.rs | 2 | ||||
| -rw-r--r-- | crates/hir-expand/src/declarative.rs | 6 | ||||
| -rw-r--r-- | crates/mbe/Cargo.toml | 1 | ||||
| -rw-r--r-- | crates/mbe/src/benchmark.rs | 14 | ||||
| -rw-r--r-- | crates/mbe/src/expander.rs | 6 | ||||
| -rw-r--r-- | crates/mbe/src/expander/matcher.rs | 22 | ||||
| -rw-r--r-- | crates/mbe/src/lib.rs | 9 | ||||
| -rw-r--r-- | crates/mbe/src/tests.rs | 3 |
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 { |