@@ -29,7 +29,7 @@ use syntax_pos::Span;
29
29
use rustc_data_structures:: fx:: FxHashMap ;
30
30
use std:: borrow:: Cow ;
31
31
use std:: collections:: hash_map:: Entry ;
32
- use std:: slice;
32
+ use std:: { mem , slice} ;
33
33
34
34
use errors:: Applicability ;
35
35
use rustc_data_structures:: sync:: Lrc ;
@@ -182,16 +182,25 @@ fn generic_extension<'cx>(
182
182
183
183
// Which arm's failure should we report? (the one furthest along)
184
184
let mut best_failure: Option < ( Token , & str ) > = None ;
185
-
186
185
for ( i, lhs) in lhses. iter ( ) . enumerate ( ) {
187
186
// try each arm's matchers
188
187
let lhs_tt = match * lhs {
189
188
mbe:: TokenTree :: Delimited ( _, ref delim) => & delim. tts [ ..] ,
190
189
_ => cx. span_bug ( sp, "malformed macro lhs" ) ,
191
190
} ;
192
191
192
+ // Take a snapshot of the state of pre-expansion gating at this point.
193
+ // This is used so that if a matcher is not `Success(..)`ful,
194
+ // then the spans which became gated when parsing the unsucessful matcher
195
+ // are not recorded. On the first `Success(..)`ful matcher, the spans are merged.
196
+ let mut gated_spans_snaphot = mem:: take ( & mut * cx. parse_sess . gated_spans . spans . borrow_mut ( ) ) ;
197
+
193
198
match parse_tt ( cx, lhs_tt, arg. clone ( ) ) {
194
199
Success ( named_matches) => {
200
+ // The matcher was `Success(..)`ful.
201
+ // Merge the gated spans from parsing the matcher with the pre-existing ones.
202
+ cx. parse_sess . gated_spans . merge ( gated_spans_snaphot) ;
203
+
195
204
let rhs = match rhses[ i] {
196
205
// ignore delimiters
197
206
mbe:: TokenTree :: Delimited ( _, ref delimed) => delimed. tts . clone ( ) ,
@@ -248,6 +257,10 @@ fn generic_extension<'cx>(
248
257
} ,
249
258
Error ( err_sp, ref msg) => cx. span_fatal ( err_sp. substitute_dummy ( sp) , & msg[ ..] ) ,
250
259
}
260
+
261
+ // The matcher was not `Success(..)`ful.
262
+ // Restore to the state before snapshotting and maybe try again.
263
+ mem:: swap ( & mut gated_spans_snaphot, & mut cx. parse_sess . gated_spans . spans . borrow_mut ( ) ) ;
251
264
}
252
265
253
266
let ( token, label) = best_failure. expect ( "ran no matchers" ) ;
0 commit comments