Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir_def/src/macro_expansion_tests/builtin_fn_macro.rs34
-rw-r--r--crates/hir_expand/src/builtin_fn_macro.rs13
2 files changed, 46 insertions, 1 deletions
diff --git a/crates/hir_def/src/macro_expansion_tests/builtin_fn_macro.rs b/crates/hir_def/src/macro_expansion_tests/builtin_fn_macro.rs
index 06039e95c5..6e91301ecd 100644
--- a/crates/hir_def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/crates/hir_def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -314,6 +314,40 @@ fn main() { "foor0bar\nfalse"; }
}
#[test]
+fn test_concat_with_captured_expr() {
+ check(
+ r##"
+#[rustc_builtin_macro]
+macro_rules! concat {}
+
+macro_rules! surprise {
+ () => { "s" };
+}
+
+macro_rules! stuff {
+ ($string:expr) => { concat!($string) };
+}
+
+fn main() { concat!(surprise!()); }
+"##,
+ expect![[r##"
+#[rustc_builtin_macro]
+macro_rules! concat {}
+
+macro_rules! surprise {
+ () => { "s" };
+}
+
+macro_rules! stuff {
+ ($string:expr) => { concat!($string) };
+}
+
+fn main() { "s"; }
+"##]],
+ );
+}
+
+#[test]
fn test_concat_idents_expand() {
check(
r##"
diff --git a/crates/hir_expand/src/builtin_fn_macro.rs b/crates/hir_expand/src/builtin_fn_macro.rs
index 3add4c1103..57e66e5cc4 100644
--- a/crates/hir_expand/src/builtin_fn_macro.rs
+++ b/crates/hir_expand/src/builtin_fn_macro.rs
@@ -386,7 +386,18 @@ fn concat_expand(
) -> ExpandResult<Option<ExpandedEager>> {
let mut err = None;
let mut text = String::new();
- for (i, t) in tt.token_trees.iter().enumerate() {
+ for (i, mut t) in tt.token_trees.iter().enumerate() {
+ // FIXME: hack on top of a hack: `$e:expr` captures get surrounded in parentheses
+ // to ensure the right parsing order, so skip the parentheses here. Ideally we'd
+ // implement rustc's model. cc https://github.com/rust-analyzer/rust-analyzer/pull/10623
+ if let tt::TokenTree::Subtree(tt::Subtree { delimiter: Some(delim), token_trees }) = t {
+ if let [tt] = &**token_trees {
+ if delim.kind == tt::DelimiterKind::Parenthesis {
+ t = tt;
+ }
+ }
+ }
+
match t {
tt::TokenTree::Leaf(tt::Leaf::Literal(it)) if i % 2 == 0 => {
// concat works with string and char literals, so remove any quotes.