diff options
Diffstat (limited to 'crates/mbe/src')
-rw-r--r-- | crates/mbe/src/mbe_expander/matcher.rs | 2 | ||||
-rw-r--r-- | crates/mbe/src/mbe_expander/transcriber.rs | 27 | ||||
-rw-r--r-- | crates/mbe/src/parser.rs | 15 | ||||
-rw-r--r-- | crates/mbe/src/tests.rs | 13 |
4 files changed, 34 insertions, 23 deletions
diff --git a/crates/mbe/src/mbe_expander/matcher.rs b/crates/mbe/src/mbe_expander/matcher.rs index fdc8844ce..c6d615c81 100644 --- a/crates/mbe/src/mbe_expander/matcher.rs +++ b/crates/mbe/src/mbe_expander/matcher.rs | |||
@@ -150,7 +150,7 @@ fn match_subtree( | |||
150 | res.add_err(err!("leftover tokens")); | 150 | res.add_err(err!("leftover tokens")); |
151 | } | 151 | } |
152 | } | 152 | } |
153 | Op::Var { name, kind } => { | 153 | Op::Var { name, kind, .. } => { |
154 | let kind = match kind { | 154 | let kind = match kind { |
155 | Some(k) => k, | 155 | Some(k) => k, |
156 | None => { | 156 | None => { |
diff --git a/crates/mbe/src/mbe_expander/transcriber.rs b/crates/mbe/src/mbe_expander/transcriber.rs index 720531237..27b2ac777 100644 --- a/crates/mbe/src/mbe_expander/transcriber.rs +++ b/crates/mbe/src/mbe_expander/transcriber.rs | |||
@@ -100,8 +100,8 @@ fn expand_subtree( | |||
100 | err = err.or(e); | 100 | err = err.or(e); |
101 | arena.push(tt.into()); | 101 | arena.push(tt.into()); |
102 | } | 102 | } |
103 | Op::Var { name, .. } => { | 103 | Op::Var { name, id, .. } => { |
104 | let ExpandResult { value: fragment, err: e } = expand_var(ctx, &name); | 104 | let ExpandResult { value: fragment, err: e } = expand_var(ctx, &name, *id); |
105 | err = err.or(e); | 105 | err = err.or(e); |
106 | push_fragment(arena, fragment); | 106 | push_fragment(arena, fragment); |
107 | } | 107 | } |
@@ -118,14 +118,11 @@ fn expand_subtree( | |||
118 | ExpandResult { value: tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err } | 118 | ExpandResult { value: tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err } |
119 | } | 119 | } |
120 | 120 | ||
121 | fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> { | 121 | fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr, id: tt::TokenId) -> ExpandResult<Fragment> { |
122 | if v == "crate" { | 122 | // We already handle $crate case in mbe parser |
123 | // We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path. | 123 | debug_assert!(v != "crate"); |
124 | let tt = | 124 | |
125 | tt::Leaf::from(tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() }) | 125 | if !ctx.bindings.contains(v) { |
126 | .into(); | ||
127 | ExpandResult::ok(Fragment::Tokens(tt)) | ||
128 | } else if !ctx.bindings.contains(v) { | ||
129 | // Note that it is possible to have a `$var` inside a macro which is not bound. | 126 | // Note that it is possible to have a `$var` inside a macro which is not bound. |
130 | // For example: | 127 | // For example: |
131 | // ``` | 128 | // ``` |
@@ -142,14 +139,8 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> { | |||
142 | let tt = tt::Subtree { | 139 | let tt = tt::Subtree { |
143 | delimiter: None, | 140 | delimiter: None, |
144 | token_trees: vec![ | 141 | token_trees: vec![ |
145 | tt::Leaf::from(tt::Punct { | 142 | tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, id }).into(), |
146 | char: '$', | 143 | tt::Leaf::from(tt::Ident { text: v.clone(), id }).into(), |
147 | spacing: tt::Spacing::Alone, | ||
148 | id: tt::TokenId::unspecified(), | ||
149 | }) | ||
150 | .into(), | ||
151 | tt::Leaf::from(tt::Ident { text: v.clone(), id: tt::TokenId::unspecified() }) | ||
152 | .into(), | ||
153 | ], | 144 | ], |
154 | } | 145 | } |
155 | .into(); | 146 | .into(); |
diff --git a/crates/mbe/src/parser.rs b/crates/mbe/src/parser.rs index 2f3ebc831..f3047972d 100644 --- a/crates/mbe/src/parser.rs +++ b/crates/mbe/src/parser.rs | |||
@@ -8,7 +8,7 @@ use crate::{tt_iter::TtIter, ExpandError, MetaTemplate}; | |||
8 | 8 | ||
9 | #[derive(Clone, Debug, PartialEq, Eq)] | 9 | #[derive(Clone, Debug, PartialEq, Eq)] |
10 | pub(crate) enum Op { | 10 | pub(crate) enum Op { |
11 | Var { name: SmolStr, kind: Option<SmolStr> }, | 11 | Var { name: SmolStr, kind: Option<SmolStr>, id: tt::TokenId }, |
12 | Repeat { subtree: MetaTemplate, kind: RepeatKind, separator: Option<Separator> }, | 12 | Repeat { subtree: MetaTemplate, kind: RepeatKind, separator: Option<Separator> }, |
13 | Leaf(tt::Leaf), | 13 | Leaf(tt::Leaf), |
14 | Subtree(MetaTemplate), | 14 | Subtree(MetaTemplate), |
@@ -106,18 +106,25 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul | |||
106 | } | 106 | } |
107 | let name = UNDERSCORE.clone(); | 107 | let name = UNDERSCORE.clone(); |
108 | let kind = eat_fragment_kind(src, mode)?; | 108 | let kind = eat_fragment_kind(src, mode)?; |
109 | Op::Var { name, kind } | 109 | let id = punct.id; |
110 | Op::Var { name, kind, id } | ||
111 | } | ||
112 | tt::Leaf::Ident(ident) if ident.text == "crate" => { | ||
113 | // We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path. | ||
114 | Op::Leaf(tt::Leaf::from(tt::Ident { text: "$crate".into(), id: ident.id })) | ||
110 | } | 115 | } |
111 | tt::Leaf::Ident(ident) => { | 116 | tt::Leaf::Ident(ident) => { |
112 | let name = ident.text.clone(); | 117 | let name = ident.text.clone(); |
113 | let kind = eat_fragment_kind(src, mode)?; | 118 | let kind = eat_fragment_kind(src, mode)?; |
114 | Op::Var { name, kind } | 119 | let id = ident.id; |
120 | Op::Var { name, kind, id } | ||
115 | } | 121 | } |
116 | tt::Leaf::Literal(lit) => { | 122 | tt::Leaf::Literal(lit) => { |
117 | if is_boolean_literal(&lit) { | 123 | if is_boolean_literal(&lit) { |
118 | let name = lit.text.clone(); | 124 | let name = lit.text.clone(); |
119 | let kind = eat_fragment_kind(src, mode)?; | 125 | let kind = eat_fragment_kind(src, mode)?; |
120 | Op::Var { name, kind } | 126 | let id = lit.id; |
127 | Op::Var { name, kind, id } | ||
121 | } else { | 128 | } else { |
122 | bail!("bad var 2"); | 129 | bail!("bad var 2"); |
123 | } | 130 | } |
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs index 1d9afb4fb..d854985c5 100644 --- a/crates/mbe/src/tests.rs +++ b/crates/mbe/src/tests.rs | |||
@@ -1080,6 +1080,19 @@ fn test_vertical_bar_with_pat() { | |||
1080 | } | 1080 | } |
1081 | 1081 | ||
1082 | #[test] | 1082 | #[test] |
1083 | fn test_dollar_crate_lhs_is_not_meta() { | ||
1084 | parse_macro( | ||
1085 | r#" | ||
1086 | macro_rules! foo { | ||
1087 | ($crate) => {}; | ||
1088 | () => {0}; | ||
1089 | } | ||
1090 | "#, | ||
1091 | ) | ||
1092 | .assert_expand_items(r#"foo!{}"#, r#"0"#); | ||
1093 | } | ||
1094 | |||
1095 | #[test] | ||
1083 | fn test_lifetime() { | 1096 | fn test_lifetime() { |
1084 | parse_macro( | 1097 | parse_macro( |
1085 | r#" | 1098 | r#" |