Stop checking err_count
in macro_rules validity checking
All errors are local anyway, so we can track them directly
This commit is contained in:
parent
5bd5d214ef
commit
f68741b637
1 changed files with 24 additions and 15 deletions
|
@ -485,7 +485,9 @@ pub fn compile_declarative_macro(
|
||||||
)
|
)
|
||||||
.pop()
|
.pop()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
valid &= check_lhs_nt_follows(sess, def, &tt);
|
// We don't handle errors here, the driver will abort
|
||||||
|
// after parsing/expansion. we can report every error in every macro this way.
|
||||||
|
valid &= check_lhs_nt_follows(sess, def, &tt).is_ok();
|
||||||
return tt;
|
return tt;
|
||||||
}
|
}
|
||||||
sess.dcx().span_bug(def.span, "wrong-structured lhs")
|
sess.dcx().span_bug(def.span, "wrong-structured lhs")
|
||||||
|
@ -589,18 +591,19 @@ pub fn compile_declarative_macro(
|
||||||
(mk_syn_ext(expander), rule_spans)
|
(mk_syn_ext(expander), rule_spans)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_lhs_nt_follows(sess: &Session, def: &ast::Item, lhs: &mbe::TokenTree) -> bool {
|
fn check_lhs_nt_follows(
|
||||||
|
sess: &Session,
|
||||||
|
def: &ast::Item,
|
||||||
|
lhs: &mbe::TokenTree,
|
||||||
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
// lhs is going to be like TokenTree::Delimited(...), where the
|
// lhs is going to be like TokenTree::Delimited(...), where the
|
||||||
// entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
|
// entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
|
||||||
if let mbe::TokenTree::Delimited(.., delimited) = lhs {
|
if let mbe::TokenTree::Delimited(.., delimited) = lhs {
|
||||||
check_matcher(sess, def, &delimited.tts)
|
check_matcher(sess, def, &delimited.tts)
|
||||||
} else {
|
} else {
|
||||||
let msg = "invalid macro matcher; matchers must be contained in balanced delimiters";
|
let msg = "invalid macro matcher; matchers must be contained in balanced delimiters";
|
||||||
sess.dcx().span_err(lhs.span(), msg);
|
Err(sess.dcx().span_err(lhs.span(), msg))
|
||||||
false
|
|
||||||
}
|
}
|
||||||
// we don't abort on errors on rejection, the driver will do that for us
|
|
||||||
// after parsing/expansion. we can report every error in every macro this way.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_empty_token_tree(sess: &Session, seq: &mbe::SequenceRepetition) -> bool {
|
fn is_empty_token_tree(sess: &Session, seq: &mbe::SequenceRepetition) -> bool {
|
||||||
|
@ -675,12 +678,15 @@ fn check_rhs(sess: &Session, rhs: &mbe::TokenTree) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_matcher(sess: &Session, def: &ast::Item, matcher: &[mbe::TokenTree]) -> bool {
|
fn check_matcher(
|
||||||
|
sess: &Session,
|
||||||
|
def: &ast::Item,
|
||||||
|
matcher: &[mbe::TokenTree],
|
||||||
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let first_sets = FirstSets::new(matcher);
|
let first_sets = FirstSets::new(matcher);
|
||||||
let empty_suffix = TokenSet::empty();
|
let empty_suffix = TokenSet::empty();
|
||||||
let err = sess.dcx().err_count();
|
check_matcher_core(sess, def, &first_sets, matcher, &empty_suffix)?;
|
||||||
check_matcher_core(sess, def, &first_sets, matcher, &empty_suffix);
|
Ok(())
|
||||||
err == sess.dcx().err_count()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_compile_error_macro(rhs: &mbe::TokenTree) -> bool {
|
fn has_compile_error_macro(rhs: &mbe::TokenTree) -> bool {
|
||||||
|
@ -1020,11 +1026,13 @@ fn check_matcher_core<'tt>(
|
||||||
first_sets: &FirstSets<'tt>,
|
first_sets: &FirstSets<'tt>,
|
||||||
matcher: &'tt [mbe::TokenTree],
|
matcher: &'tt [mbe::TokenTree],
|
||||||
follow: &TokenSet<'tt>,
|
follow: &TokenSet<'tt>,
|
||||||
) -> TokenSet<'tt> {
|
) -> Result<TokenSet<'tt>, ErrorGuaranteed> {
|
||||||
use mbe::TokenTree;
|
use mbe::TokenTree;
|
||||||
|
|
||||||
let mut last = TokenSet::empty();
|
let mut last = TokenSet::empty();
|
||||||
|
|
||||||
|
let mut errored = Ok(());
|
||||||
|
|
||||||
// 2. For each token and suffix [T, SUFFIX] in M:
|
// 2. For each token and suffix [T, SUFFIX] in M:
|
||||||
// ensure that T can be followed by SUFFIX, and if SUFFIX may be empty,
|
// ensure that T can be followed by SUFFIX, and if SUFFIX may be empty,
|
||||||
// then ensure T can also be followed by any element of FOLLOW.
|
// then ensure T can also be followed by any element of FOLLOW.
|
||||||
|
@ -1068,7 +1076,7 @@ fn check_matcher_core<'tt>(
|
||||||
token::CloseDelim(d.delim),
|
token::CloseDelim(d.delim),
|
||||||
span.close,
|
span.close,
|
||||||
));
|
));
|
||||||
check_matcher_core(sess, def, first_sets, &d.tts, &my_suffix);
|
check_matcher_core(sess, def, first_sets, &d.tts, &my_suffix)?;
|
||||||
// don't track non NT tokens
|
// don't track non NT tokens
|
||||||
last.replace_with_irrelevant();
|
last.replace_with_irrelevant();
|
||||||
|
|
||||||
|
@ -1100,7 +1108,7 @@ fn check_matcher_core<'tt>(
|
||||||
// At this point, `suffix_first` is built, and
|
// At this point, `suffix_first` is built, and
|
||||||
// `my_suffix` is some TokenSet that we can use
|
// `my_suffix` is some TokenSet that we can use
|
||||||
// for checking the interior of `seq_rep`.
|
// for checking the interior of `seq_rep`.
|
||||||
let next = check_matcher_core(sess, def, first_sets, &seq_rep.tts, my_suffix);
|
let next = check_matcher_core(sess, def, first_sets, &seq_rep.tts, my_suffix)?;
|
||||||
if next.maybe_empty {
|
if next.maybe_empty {
|
||||||
last.add_all(&next);
|
last.add_all(&next);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1206,14 +1214,15 @@ fn check_matcher_core<'tt>(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err.emit();
|
errored = Err(err.emit());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last
|
errored?;
|
||||||
|
Ok(last)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn token_can_be_followed_by_any(tok: &mbe::TokenTree) -> bool {
|
fn token_can_be_followed_by_any(tok: &mbe::TokenTree) -> bool {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue