1
Fork 0

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:
Oli Scherer 2024-01-25 11:57:01 +00:00
parent 5bd5d214ef
commit f68741b637

View file

@ -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 {