diff options
-rw-r--r-- | crates/ra_hir_expand/src/db.rs | 12 | ||||
-rw-r--r-- | crates/ra_mbe/src/lib.rs | 32 | ||||
-rw-r--r-- | crates/ra_mbe/src/mbe_expander.rs | 16 | ||||
-rw-r--r-- | crates/ra_mbe/src/mbe_expander/matcher.rs | 21 | ||||
-rw-r--r-- | crates/ra_mbe/src/mbe_expander/transcriber.rs | 22 | ||||
-rw-r--r-- | crates/ra_mbe/src/tests.rs | 3 |
6 files changed, 63 insertions, 43 deletions
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index f1918817e..d171d2dfd 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use mbe::MacroRules; | 5 | use mbe::{ExpandResult, MacroRules}; |
6 | use ra_db::{salsa, SourceDatabase}; | 6 | use ra_db::{salsa, SourceDatabase}; |
7 | use ra_parser::FragmentKind; | 7 | use ra_parser::FragmentKind; |
8 | use ra_prof::profile; | 8 | use ra_prof::profile; |
@@ -31,12 +31,8 @@ impl TokenExpander { | |||
31 | match self { | 31 | match self { |
32 | TokenExpander::MacroRules(it) => it.expand(tt), | 32 | TokenExpander::MacroRules(it) => it.expand(tt), |
33 | // FIXME switch these to ExpandResult as well | 33 | // FIXME switch these to ExpandResult as well |
34 | TokenExpander::Builtin(it) => it | 34 | TokenExpander::Builtin(it) => it.expand(db, id, tt).into(), |
35 | .expand(db, id, tt) | 35 | TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), |
36 | .map_or_else(|e| (tt::Subtree::default(), Some(e)), |r| (r, None)), | ||
37 | TokenExpander::BuiltinDerive(it) => it | ||
38 | .expand(db, id, tt) | ||
39 | .map_or_else(|e| (tt::Subtree::default(), Some(e)), |r| (r, None)), | ||
40 | } | 36 | } |
41 | } | 37 | } |
42 | 38 | ||
@@ -204,7 +200,7 @@ fn macro_expand_with_arg( | |||
204 | Some(it) => it, | 200 | Some(it) => it, |
205 | None => return (None, Some("Fail to find macro definition".into())), | 201 | None => return (None, Some("Fail to find macro definition".into())), |
206 | }; | 202 | }; |
207 | let (tt, err) = macro_rules.0.expand(db, lazy_id, ¯o_arg.0); | 203 | let ExpandResult(tt, err) = macro_rules.0.expand(db, lazy_id, ¯o_arg.0); |
208 | // Set a hard limit for the expanded tt | 204 | // Set a hard limit for the expanded tt |
209 | let count = tt.count(); | 205 | let count = tt.count(); |
210 | if count > 65536 { | 206 | if count > 65536 { |
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index 3adec4978..6a9037bfc 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs | |||
@@ -30,8 +30,6 @@ pub enum ExpandError { | |||
30 | InvalidRepeat, | 30 | InvalidRepeat, |
31 | } | 31 | } |
32 | 32 | ||
33 | pub type ExpandResult<T> = (T, Option<ExpandError>); | ||
34 | |||
35 | pub use crate::syntax_bridge::{ | 33 | pub use crate::syntax_bridge::{ |
36 | ast_to_token_tree, parse_to_token_tree, syntax_node_to_token_tree, token_tree_to_syntax_node, | 34 | ast_to_token_tree, parse_to_token_tree, syntax_node_to_token_tree, token_tree_to_syntax_node, |
37 | TokenMap, | 35 | TokenMap, |
@@ -211,5 +209,35 @@ fn validate(pattern: &tt::Subtree) -> Result<(), ParseError> { | |||
211 | Ok(()) | 209 | Ok(()) |
212 | } | 210 | } |
213 | 211 | ||
212 | pub struct ExpandResult<T>(pub T, pub Option<ExpandError>); | ||
213 | |||
214 | impl<T> ExpandResult<T> { | ||
215 | pub fn ok(t: T) -> ExpandResult<T> { | ||
216 | ExpandResult(t, None) | ||
217 | } | ||
218 | |||
219 | pub fn only_err(err: ExpandError) -> ExpandResult<T> | ||
220 | where | ||
221 | T: Default, | ||
222 | { | ||
223 | ExpandResult(Default::default(), Some(err)) | ||
224 | } | ||
225 | |||
226 | pub fn map<U>(self, f: impl FnOnce(T) -> U) -> ExpandResult<U> { | ||
227 | ExpandResult(f(self.0), self.1) | ||
228 | } | ||
229 | |||
230 | pub fn result(self) -> Result<T, ExpandError> { | ||
231 | self.1.map(Err).unwrap_or(Ok(self.0)) | ||
232 | } | ||
233 | } | ||
234 | |||
235 | impl<T: Default> From<Result<T, ExpandError>> for ExpandResult<T> { | ||
236 | fn from(result: Result<T, ExpandError>) -> ExpandResult<T> { | ||
237 | result | ||
238 | .map_or_else(|e| ExpandResult(Default::default(), Some(e)), |it| ExpandResult(it, None)) | ||
239 | } | ||
240 | } | ||
241 | |||
214 | #[cfg(test)] | 242 | #[cfg(test)] |
215 | mod tests; | 243 | mod tests; |
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs index 204c30e3d..0a4d73dda 100644 --- a/crates/ra_mbe/src/mbe_expander.rs +++ b/crates/ra_mbe/src/mbe_expander.rs | |||
@@ -18,12 +18,13 @@ fn expand_rules(rules: &[crate::Rule], input: &tt::Subtree) -> ExpandResult<tt:: | |||
18 | let mut match_: Option<(matcher::Match, &crate::Rule)> = None; | 18 | let mut match_: Option<(matcher::Match, &crate::Rule)> = None; |
19 | let mut err = Some(ExpandError::NoMatchingRule); | 19 | let mut err = Some(ExpandError::NoMatchingRule); |
20 | for rule in rules { | 20 | for rule in rules { |
21 | let (new_match, bindings_err) = matcher::match_(&rule.lhs, input); | 21 | let ExpandResult(new_match, bindings_err) = matcher::match_(&rule.lhs, input); |
22 | if bindings_err.is_none() { | 22 | if bindings_err.is_none() { |
23 | // if we find a rule that applies without errors, we're done | 23 | // if we find a rule that applies without errors, we're done |
24 | let (res, transcribe_err) = transcriber::transcribe(&rule.rhs, &new_match.bindings); | 24 | let ExpandResult(res, transcribe_err) = |
25 | transcriber::transcribe(&rule.rhs, &new_match.bindings); | ||
25 | if transcribe_err.is_none() { | 26 | if transcribe_err.is_none() { |
26 | return (res, None); | 27 | return ExpandResult::ok(res); |
27 | } | 28 | } |
28 | } | 29 | } |
29 | // use the rule if we matched more tokens, or had fewer patterns left | 30 | // use the rule if we matched more tokens, or had fewer patterns left |
@@ -43,10 +44,11 @@ fn expand_rules(rules: &[crate::Rule], input: &tt::Subtree) -> ExpandResult<tt:: | |||
43 | } | 44 | } |
44 | if let Some((match_, rule)) = match_ { | 45 | if let Some((match_, rule)) = match_ { |
45 | // if we got here, there was no match without errors | 46 | // if we got here, there was no match without errors |
46 | let (result, transcribe_err) = transcriber::transcribe(&rule.rhs, &match_.bindings); | 47 | let ExpandResult(result, transcribe_err) = |
47 | (result, err.or(transcribe_err)) | 48 | transcriber::transcribe(&rule.rhs, &match_.bindings); |
49 | ExpandResult(result, err.or(transcribe_err)) | ||
48 | } else { | 50 | } else { |
49 | (tt::Subtree::default(), err) | 51 | ExpandResult(tt::Subtree::default(), err) |
50 | } | 52 | } |
51 | } | 53 | } |
52 | 54 | ||
@@ -171,6 +173,6 @@ mod tests { | |||
171 | ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); | 173 | ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); |
172 | 174 | ||
173 | let expanded = expand_rules(&rules.rules, &invocation_tt); | 175 | let expanded = expand_rules(&rules.rules, &invocation_tt); |
174 | (expanded.0, expanded.1) | 176 | expanded |
175 | } | 177 | } |
176 | } | 178 | } |
diff --git a/crates/ra_mbe/src/mbe_expander/matcher.rs b/crates/ra_mbe/src/mbe_expander/matcher.rs index f40d55d4e..22fb5d74c 100644 --- a/crates/ra_mbe/src/mbe_expander/matcher.rs +++ b/crates/ra_mbe/src/mbe_expander/matcher.rs | |||
@@ -79,7 +79,7 @@ pub(super) fn match_(pattern: &tt::Subtree, src: &tt::Subtree) -> ExpandResult<M | |||
79 | err = Some(err!("leftover tokens")); | 79 | err = Some(err!("leftover tokens")); |
80 | } | 80 | } |
81 | 81 | ||
82 | (res, err) | 82 | ExpandResult(res, err) |
83 | } | 83 | } |
84 | 84 | ||
85 | fn match_subtree( | 85 | fn match_subtree( |
@@ -148,7 +148,7 @@ fn match_subtree( | |||
148 | continue; | 148 | continue; |
149 | } | 149 | } |
150 | }; | 150 | }; |
151 | let (matched, match_err) = match_meta_var(kind.as_str(), src); | 151 | let ExpandResult(matched, match_err) = match_meta_var(kind.as_str(), src); |
152 | match matched { | 152 | match matched { |
153 | Some(fragment) => { | 153 | Some(fragment) => { |
154 | res.bindings.inner.insert(name.clone(), Binding::Fragment(fragment)); | 154 | res.bindings.inner.insert(name.clone(), Binding::Fragment(fragment)); |
@@ -308,17 +308,17 @@ impl<'a> TtIter<'a> { | |||
308 | token_trees: res.into_iter().cloned().collect(), | 308 | token_trees: res.into_iter().cloned().collect(), |
309 | })), | 309 | })), |
310 | }; | 310 | }; |
311 | (res, err) | 311 | ExpandResult(res, err) |
312 | } | 312 | } |
313 | 313 | ||
314 | pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> { | 314 | pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> { |
315 | let mut fork = self.clone(); | 315 | let mut fork = self.clone(); |
316 | match fork.expect_fragment(Visibility) { | 316 | match fork.expect_fragment(Visibility) { |
317 | (tt, None) => { | 317 | ExpandResult(tt, None) => { |
318 | *self = fork; | 318 | *self = fork; |
319 | tt | 319 | tt |
320 | } | 320 | } |
321 | (_, Some(_)) => None, | 321 | ExpandResult(_, Some(_)) => None, |
322 | } | 322 | } |
323 | } | 323 | } |
324 | } | 324 | } |
@@ -419,12 +419,11 @@ fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult<Option<Fragmen | |||
419 | }, | 419 | }, |
420 | _ => Err(ExpandError::UnexpectedToken), | 420 | _ => Err(ExpandError::UnexpectedToken), |
421 | }; | 421 | }; |
422 | return to_expand_result(tt_result.map(|it| it.map(Fragment::Tokens))); | 422 | return tt_result.map(|it| it.map(Fragment::Tokens)).into(); |
423 | } | 423 | } |
424 | }; | 424 | }; |
425 | let (tt, err) = input.expect_fragment(fragment); | 425 | let result = input.expect_fragment(fragment); |
426 | let fragment = if kind == "expr" { tt.map(Fragment::Ast) } else { tt.map(Fragment::Tokens) }; | 426 | result.map(|tt| if kind == "expr" { tt.map(Fragment::Ast) } else { tt.map(Fragment::Tokens) }) |
427 | (fragment, err) | ||
428 | } | 427 | } |
429 | 428 | ||
430 | fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &tt::Subtree) -> Result<(), ExpandError> { | 429 | fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &tt::Subtree) -> Result<(), ExpandError> { |
@@ -438,7 +437,3 @@ fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &tt::Subtree) -> Result<(), Exp | |||
438 | } | 437 | } |
439 | Ok(()) | 438 | Ok(()) |
440 | } | 439 | } |
441 | |||
442 | fn to_expand_result<T: Default>(result: Result<T, ExpandError>) -> ExpandResult<T> { | ||
443 | result.map_or_else(|e| (Default::default(), Some(e)), |it| (it, None)) | ||
444 | } | ||
diff --git a/crates/ra_mbe/src/mbe_expander/transcriber.rs b/crates/ra_mbe/src/mbe_expander/transcriber.rs index c53c2d35e..4b173edd3 100644 --- a/crates/ra_mbe/src/mbe_expander/transcriber.rs +++ b/crates/ra_mbe/src/mbe_expander/transcriber.rs | |||
@@ -87,23 +87,23 @@ fn expand_subtree(ctx: &mut ExpandCtx, template: &tt::Subtree) -> ExpandResult<t | |||
87 | match op { | 87 | match op { |
88 | Op::TokenTree(tt @ tt::TokenTree::Leaf(..)) => buf.push(tt.clone()), | 88 | Op::TokenTree(tt @ tt::TokenTree::Leaf(..)) => buf.push(tt.clone()), |
89 | Op::TokenTree(tt::TokenTree::Subtree(tt)) => { | 89 | Op::TokenTree(tt::TokenTree::Subtree(tt)) => { |
90 | let (tt, e) = expand_subtree(ctx, tt); | 90 | let ExpandResult(tt, e) = expand_subtree(ctx, tt); |
91 | err = err.or(e); | 91 | err = err.or(e); |
92 | buf.push(tt.into()); | 92 | buf.push(tt.into()); |
93 | } | 93 | } |
94 | Op::Var { name, kind: _ } => { | 94 | Op::Var { name, kind: _ } => { |
95 | let (fragment, e) = expand_var(ctx, name); | 95 | let ExpandResult(fragment, e) = expand_var(ctx, name); |
96 | err = err.or(e); | 96 | err = err.or(e); |
97 | push_fragment(&mut buf, fragment); | 97 | push_fragment(&mut buf, fragment); |
98 | } | 98 | } |
99 | Op::Repeat { subtree, kind, separator } => { | 99 | Op::Repeat { subtree, kind, separator } => { |
100 | let (fragment, e) = expand_repeat(ctx, subtree, kind, separator); | 100 | let ExpandResult(fragment, e) = expand_repeat(ctx, subtree, kind, separator); |
101 | err = err.or(e); | 101 | err = err.or(e); |
102 | push_fragment(&mut buf, fragment) | 102 | push_fragment(&mut buf, fragment) |
103 | } | 103 | } |
104 | } | 104 | } |
105 | } | 105 | } |
106 | (tt::Subtree { delimiter: template.delimiter, token_trees: buf }, err) | 106 | ExpandResult(tt::Subtree { delimiter: template.delimiter, token_trees: buf }, err) |
107 | } | 107 | } |
108 | 108 | ||
109 | fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> { | 109 | fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> { |
@@ -112,7 +112,7 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> { | |||
112 | let tt = | 112 | let tt = |
113 | tt::Leaf::from(tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() }) | 113 | tt::Leaf::from(tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() }) |
114 | .into(); | 114 | .into(); |
115 | (Fragment::Tokens(tt), None) | 115 | ExpandResult::ok(Fragment::Tokens(tt)) |
116 | } else if !ctx.bindings.contains(v) { | 116 | } else if !ctx.bindings.contains(v) { |
117 | // Note that it is possible to have a `$var` inside a macro which is not bound. | 117 | // Note that it is possible to have a `$var` inside a macro which is not bound. |
118 | // For example: | 118 | // For example: |
@@ -141,11 +141,11 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> { | |||
141 | ], | 141 | ], |
142 | } | 142 | } |
143 | .into(); | 143 | .into(); |
144 | (Fragment::Tokens(tt), None) | 144 | ExpandResult::ok(Fragment::Tokens(tt)) |
145 | } else { | 145 | } else { |
146 | ctx.bindings.get(&v, &mut ctx.nesting).map_or_else( | 146 | ctx.bindings.get(&v, &mut ctx.nesting).map_or_else( |
147 | |e| (Fragment::Tokens(tt::TokenTree::empty()), Some(e)), | 147 | |e| ExpandResult(Fragment::Tokens(tt::TokenTree::empty()), Some(e)), |
148 | |b| (b.clone(), None), | 148 | |b| ExpandResult::ok(b.clone()), |
149 | ) | 149 | ) |
150 | } | 150 | } |
151 | } | 151 | } |
@@ -165,7 +165,7 @@ fn expand_repeat( | |||
165 | let mut counter = 0; | 165 | let mut counter = 0; |
166 | 166 | ||
167 | loop { | 167 | loop { |
168 | let (mut t, e) = expand_subtree(ctx, template); | 168 | let ExpandResult(mut t, e) = expand_subtree(ctx, template); |
169 | let nesting_state = ctx.nesting.last_mut().unwrap(); | 169 | let nesting_state = ctx.nesting.last_mut().unwrap(); |
170 | if nesting_state.at_end || !nesting_state.hit { | 170 | if nesting_state.at_end || !nesting_state.hit { |
171 | break; | 171 | break; |
@@ -225,9 +225,9 @@ fn expand_repeat( | |||
225 | let tt = tt::Subtree { delimiter: None, token_trees: buf }.into(); | 225 | let tt = tt::Subtree { delimiter: None, token_trees: buf }.into(); |
226 | 226 | ||
227 | if RepeatKind::OneOrMore == kind && counter == 0 { | 227 | if RepeatKind::OneOrMore == kind && counter == 0 { |
228 | return (Fragment::Tokens(tt), Some(ExpandError::UnexpectedToken)); | 228 | return ExpandResult(Fragment::Tokens(tt), Some(ExpandError::UnexpectedToken)); |
229 | } | 229 | } |
230 | (Fragment::Tokens(tt), None) | 230 | ExpandResult::ok(Fragment::Tokens(tt)) |
231 | } | 231 | } |
232 | 232 | ||
233 | fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) { | 233 | fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) { |
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs index faf88c1b1..44f381938 100644 --- a/crates/ra_mbe/src/tests.rs +++ b/crates/ra_mbe/src/tests.rs | |||
@@ -1430,8 +1430,7 @@ impl MacroFixture { | |||
1430 | let (invocation_tt, _) = | 1430 | let (invocation_tt, _) = |
1431 | ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); | 1431 | ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); |
1432 | 1432 | ||
1433 | let (tt, err) = self.rules.expand(&invocation_tt); | 1433 | self.rules.expand(&invocation_tt).result() |
1434 | err.map(Err).unwrap_or(Ok(tt)) | ||
1435 | } | 1434 | } |
1436 | 1435 | ||
1437 | fn assert_expand_err(&self, invocation: &str, err: &ExpandError) { | 1436 | fn assert_expand_err(&self, invocation: &str, err: &ExpandError) { |