Skip to content

Commit 6ecd43c

Browse files
Merge #1040
1040: Do not propagate parse errors in match repetitions r=CohenArthur a=CohenArthur Since parsing repetitions is very eager, the parser might accumulate bogus errors by trying to match more repetitions than there are. We can avoid this by clearing the parsing errors if parsing repetitions returned a valid result. This should not be an issue for previous matchers erroring out, as they would immediately return upon failure and not reach inside other match functions. We need to figure out the best way to emit parser errors, as we do not always want to emit them in `match_fragment`. I think for now the easiest is to just *not* emit parse errors and simply error out with "failed to match macro rule". We will need to think about adding a bunch of hints too in order to make using macros easier. Fixes #958 Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
2 parents 32894e6 + a64a5cf commit 6ecd43c

File tree

4 files changed

+18
-6
lines changed

4 files changed

+18
-6
lines changed

gcc/rust/expand/rust-macro-expand.cc

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -505,9 +505,6 @@ MacroExpander::match_fragment (Parser<MacroInvocLexer> &parser,
505505
return false;
506506
}
507507

508-
for (const auto &error : parser.get_errors ())
509-
error.emit_error ();
510-
511508
// it matches if the parser did not produce errors trying to parse that type
512509
// of item
513510
return !parser.has_errors ();
@@ -714,7 +711,13 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser,
714711
bool did_meet_lo_bound = match_amount >= lo_bound;
715712
bool did_meet_hi_bound = hi_bound ? match_amount <= hi_bound : true;
716713

717-
return did_meet_lo_bound && did_meet_hi_bound;
714+
// If the end-result is valid, then we can clear the parse errors: Since
715+
// repetitions are parsed eagerly, it is okay to fail in some cases
716+
auto res = did_meet_lo_bound && did_meet_hi_bound;
717+
if (res)
718+
parser.clear_errors ();
719+
720+
return res;
718721
}
719722

720723
bool

gcc/rust/parse/rust-parse.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,6 @@ template <typename ManagedTokenSource> class Parser
649649
bool done_end_of_file ();
650650

651651
void add_error (Error error) { error_table.push_back (std::move (error)); }
652-
void clear_errors () { error_table.clear (); }
653652

654653
public:
655654
// Construct parser with specified "managed" token source.
@@ -668,6 +667,8 @@ template <typename ManagedTokenSource> class Parser
668667

669668
// Returns whether any parsing errors have occurred.
670669
bool has_errors () const { return !error_table.empty (); }
670+
// Remove all parsing errors from the table
671+
void clear_errors () { error_table.clear (); }
671672

672673
// Get a reference to the list of errors encountered
673674
std::vector<Error> &get_errors () { return error_table; }

gcc/testsuite/rust/compile/macro25.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
macro_rules! valid {
2+
($($a:literal)* $i:ident) => {{}};
3+
}
4+
5+
fn main() {
6+
valid!(1 one_lit);
7+
valid!(identifier_only);
8+
valid!(1 2 two_lits);
9+
}

gcc/testsuite/rust/compile/macro9.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ fn main() -> i32 {
1212
let b = add!(15);
1313
let b = add!(15 14); // { dg-error "Failed to match any rule within macro" }
1414
let b = add!(15, 14,); // { dg-error "Failed to match any rule within macro" }
15-
// { dg-error "found unexpected token" "" { target *-*-* } .-1 }
1615

1716
0
1817
}

0 commit comments

Comments
 (0)