mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-27 06:14:55 +00:00
Turn ExpandResult into struct
This commit is contained in:
parent
f3c6a2e3db
commit
d655749aae
@ -2,7 +2,7 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use mbe::MacroRules;
|
||||
use mbe::{ExpandResult, MacroRules};
|
||||
use ra_db::{salsa, SourceDatabase};
|
||||
use ra_parser::FragmentKind;
|
||||
use ra_prof::profile;
|
||||
@ -31,12 +31,8 @@ impl TokenExpander {
|
||||
match self {
|
||||
TokenExpander::MacroRules(it) => it.expand(tt),
|
||||
// FIXME switch these to ExpandResult as well
|
||||
TokenExpander::Builtin(it) => it
|
||||
.expand(db, id, tt)
|
||||
.map_or_else(|e| (tt::Subtree::default(), Some(e)), |r| (r, None)),
|
||||
TokenExpander::BuiltinDerive(it) => it
|
||||
.expand(db, id, tt)
|
||||
.map_or_else(|e| (tt::Subtree::default(), Some(e)), |r| (r, None)),
|
||||
TokenExpander::Builtin(it) => it.expand(db, id, tt).into(),
|
||||
TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,7 +200,7 @@ fn macro_expand_with_arg(
|
||||
Some(it) => it,
|
||||
None => return (None, Some("Fail to find macro definition".into())),
|
||||
};
|
||||
let (tt, err) = macro_rules.0.expand(db, lazy_id, ¯o_arg.0);
|
||||
let ExpandResult(tt, err) = macro_rules.0.expand(db, lazy_id, ¯o_arg.0);
|
||||
// Set a hard limit for the expanded tt
|
||||
let count = tt.count();
|
||||
if count > 65536 {
|
||||
|
@ -30,8 +30,6 @@ pub enum ExpandError {
|
||||
InvalidRepeat,
|
||||
}
|
||||
|
||||
pub type ExpandResult<T> = (T, Option<ExpandError>);
|
||||
|
||||
pub use crate::syntax_bridge::{
|
||||
ast_to_token_tree, parse_to_token_tree, syntax_node_to_token_tree, token_tree_to_syntax_node,
|
||||
TokenMap,
|
||||
@ -211,5 +209,35 @@ fn validate(pattern: &tt::Subtree) -> Result<(), ParseError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub struct ExpandResult<T>(pub T, pub Option<ExpandError>);
|
||||
|
||||
impl<T> ExpandResult<T> {
|
||||
pub fn ok(t: T) -> ExpandResult<T> {
|
||||
ExpandResult(t, None)
|
||||
}
|
||||
|
||||
pub fn only_err(err: ExpandError) -> ExpandResult<T>
|
||||
where
|
||||
T: Default,
|
||||
{
|
||||
ExpandResult(Default::default(), Some(err))
|
||||
}
|
||||
|
||||
pub fn map<U>(self, f: impl FnOnce(T) -> U) -> ExpandResult<U> {
|
||||
ExpandResult(f(self.0), self.1)
|
||||
}
|
||||
|
||||
pub fn result(self) -> Result<T, ExpandError> {
|
||||
self.1.map(Err).unwrap_or(Ok(self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> From<Result<T, ExpandError>> for ExpandResult<T> {
|
||||
fn from(result: Result<T, ExpandError>) -> ExpandResult<T> {
|
||||
result
|
||||
.map_or_else(|e| ExpandResult(Default::default(), Some(e)), |it| ExpandResult(it, None))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -18,12 +18,13 @@ fn expand_rules(rules: &[crate::Rule], input: &tt::Subtree) -> ExpandResult<tt::
|
||||
let mut match_: Option<(matcher::Match, &crate::Rule)> = None;
|
||||
let mut err = Some(ExpandError::NoMatchingRule);
|
||||
for rule in rules {
|
||||
let (new_match, bindings_err) = matcher::match_(&rule.lhs, input);
|
||||
let ExpandResult(new_match, bindings_err) = matcher::match_(&rule.lhs, input);
|
||||
if bindings_err.is_none() {
|
||||
// if we find a rule that applies without errors, we're done
|
||||
let (res, transcribe_err) = transcriber::transcribe(&rule.rhs, &new_match.bindings);
|
||||
let ExpandResult(res, transcribe_err) =
|
||||
transcriber::transcribe(&rule.rhs, &new_match.bindings);
|
||||
if transcribe_err.is_none() {
|
||||
return (res, None);
|
||||
return ExpandResult::ok(res);
|
||||
}
|
||||
}
|
||||
// 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::
|
||||
}
|
||||
if let Some((match_, rule)) = match_ {
|
||||
// if we got here, there was no match without errors
|
||||
let (result, transcribe_err) = transcriber::transcribe(&rule.rhs, &match_.bindings);
|
||||
(result, err.or(transcribe_err))
|
||||
let ExpandResult(result, transcribe_err) =
|
||||
transcriber::transcribe(&rule.rhs, &match_.bindings);
|
||||
ExpandResult(result, err.or(transcribe_err))
|
||||
} else {
|
||||
(tt::Subtree::default(), err)
|
||||
ExpandResult(tt::Subtree::default(), err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,6 +173,6 @@ mod tests {
|
||||
ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap();
|
||||
|
||||
let expanded = expand_rules(&rules.rules, &invocation_tt);
|
||||
(expanded.0, expanded.1)
|
||||
expanded
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ pub(super) fn match_(pattern: &tt::Subtree, src: &tt::Subtree) -> ExpandResult<M
|
||||
err = Some(err!("leftover tokens"));
|
||||
}
|
||||
|
||||
(res, err)
|
||||
ExpandResult(res, err)
|
||||
}
|
||||
|
||||
fn match_subtree(
|
||||
@ -148,7 +148,7 @@ fn match_subtree(
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let (matched, match_err) = match_meta_var(kind.as_str(), src);
|
||||
let ExpandResult(matched, match_err) = match_meta_var(kind.as_str(), src);
|
||||
match matched {
|
||||
Some(fragment) => {
|
||||
res.bindings.inner.insert(name.clone(), Binding::Fragment(fragment));
|
||||
@ -308,17 +308,17 @@ impl<'a> TtIter<'a> {
|
||||
token_trees: res.into_iter().cloned().collect(),
|
||||
})),
|
||||
};
|
||||
(res, err)
|
||||
ExpandResult(res, err)
|
||||
}
|
||||
|
||||
pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> {
|
||||
let mut fork = self.clone();
|
||||
match fork.expect_fragment(Visibility) {
|
||||
(tt, None) => {
|
||||
ExpandResult(tt, None) => {
|
||||
*self = fork;
|
||||
tt
|
||||
}
|
||||
(_, Some(_)) => None,
|
||||
ExpandResult(_, Some(_)) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -419,12 +419,11 @@ fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult<Option<Fragmen
|
||||
},
|
||||
_ => Err(ExpandError::UnexpectedToken),
|
||||
};
|
||||
return to_expand_result(tt_result.map(|it| it.map(Fragment::Tokens)));
|
||||
return tt_result.map(|it| it.map(Fragment::Tokens)).into();
|
||||
}
|
||||
};
|
||||
let (tt, err) = input.expect_fragment(fragment);
|
||||
let fragment = if kind == "expr" { tt.map(Fragment::Ast) } else { tt.map(Fragment::Tokens) };
|
||||
(fragment, err)
|
||||
let result = input.expect_fragment(fragment);
|
||||
result.map(|tt| if kind == "expr" { tt.map(Fragment::Ast) } else { tt.map(Fragment::Tokens) })
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn to_expand_result<T: Default>(result: Result<T, ExpandError>) -> ExpandResult<T> {
|
||||
result.map_or_else(|e| (Default::default(), Some(e)), |it| (it, None))
|
||||
}
|
||||
|
@ -87,23 +87,23 @@ fn expand_subtree(ctx: &mut ExpandCtx, template: &tt::Subtree) -> ExpandResult<t
|
||||
match op {
|
||||
Op::TokenTree(tt @ tt::TokenTree::Leaf(..)) => buf.push(tt.clone()),
|
||||
Op::TokenTree(tt::TokenTree::Subtree(tt)) => {
|
||||
let (tt, e) = expand_subtree(ctx, tt);
|
||||
let ExpandResult(tt, e) = expand_subtree(ctx, tt);
|
||||
err = err.or(e);
|
||||
buf.push(tt.into());
|
||||
}
|
||||
Op::Var { name, kind: _ } => {
|
||||
let (fragment, e) = expand_var(ctx, name);
|
||||
let ExpandResult(fragment, e) = expand_var(ctx, name);
|
||||
err = err.or(e);
|
||||
push_fragment(&mut buf, fragment);
|
||||
}
|
||||
Op::Repeat { subtree, kind, separator } => {
|
||||
let (fragment, e) = expand_repeat(ctx, subtree, kind, separator);
|
||||
let ExpandResult(fragment, e) = expand_repeat(ctx, subtree, kind, separator);
|
||||
err = err.or(e);
|
||||
push_fragment(&mut buf, fragment)
|
||||
}
|
||||
}
|
||||
}
|
||||
(tt::Subtree { delimiter: template.delimiter, token_trees: buf }, err)
|
||||
ExpandResult(tt::Subtree { delimiter: template.delimiter, token_trees: buf }, err)
|
||||
}
|
||||
|
||||
fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> {
|
||||
@ -112,7 +112,7 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> {
|
||||
let tt =
|
||||
tt::Leaf::from(tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() })
|
||||
.into();
|
||||
(Fragment::Tokens(tt), None)
|
||||
ExpandResult::ok(Fragment::Tokens(tt))
|
||||
} else if !ctx.bindings.contains(v) {
|
||||
// Note that it is possible to have a `$var` inside a macro which is not bound.
|
||||
// For example:
|
||||
@ -141,11 +141,11 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> {
|
||||
],
|
||||
}
|
||||
.into();
|
||||
(Fragment::Tokens(tt), None)
|
||||
ExpandResult::ok(Fragment::Tokens(tt))
|
||||
} else {
|
||||
ctx.bindings.get(&v, &mut ctx.nesting).map_or_else(
|
||||
|e| (Fragment::Tokens(tt::TokenTree::empty()), Some(e)),
|
||||
|b| (b.clone(), None),
|
||||
|e| ExpandResult(Fragment::Tokens(tt::TokenTree::empty()), Some(e)),
|
||||
|b| ExpandResult::ok(b.clone()),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -165,7 +165,7 @@ fn expand_repeat(
|
||||
let mut counter = 0;
|
||||
|
||||
loop {
|
||||
let (mut t, e) = expand_subtree(ctx, template);
|
||||
let ExpandResult(mut t, e) = expand_subtree(ctx, template);
|
||||
let nesting_state = ctx.nesting.last_mut().unwrap();
|
||||
if nesting_state.at_end || !nesting_state.hit {
|
||||
break;
|
||||
@ -225,9 +225,9 @@ fn expand_repeat(
|
||||
let tt = tt::Subtree { delimiter: None, token_trees: buf }.into();
|
||||
|
||||
if RepeatKind::OneOrMore == kind && counter == 0 {
|
||||
return (Fragment::Tokens(tt), Some(ExpandError::UnexpectedToken));
|
||||
return ExpandResult(Fragment::Tokens(tt), Some(ExpandError::UnexpectedToken));
|
||||
}
|
||||
(Fragment::Tokens(tt), None)
|
||||
ExpandResult::ok(Fragment::Tokens(tt))
|
||||
}
|
||||
|
||||
fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) {
|
||||
|
@ -1430,8 +1430,7 @@ impl MacroFixture {
|
||||
let (invocation_tt, _) =
|
||||
ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap();
|
||||
|
||||
let (tt, err) = self.rules.expand(&invocation_tt);
|
||||
err.map(Err).unwrap_or(Ok(tt))
|
||||
self.rules.expand(&invocation_tt).result()
|
||||
}
|
||||
|
||||
fn assert_expand_err(&self, invocation: &str, err: &ExpandError) {
|
||||
|
Loading…
Reference in New Issue
Block a user