@@ -349,203 +349,12 @@ fn check_rhs(cx: &mut ExtCtxt, rhs: &TokenTree) -> bool {
349
349
false
350
350
}
351
351
352
- // Issue 30450: when we are through a warning cycle, we can just error
353
- // on all failure conditions and remove this struct and enum.
354
-
355
- #[ derive( Debug ) ]
356
- struct OnFail {
357
- saw_failure : bool ,
358
- action : OnFailAction ,
359
- }
360
-
361
- #[ derive( Copy , Clone , Debug , PartialEq ) ]
362
- enum OnFailAction { Warn , Error , DoNothing }
363
-
364
- impl OnFail {
365
- fn warn ( ) -> OnFail { OnFail { saw_failure : false , action : OnFailAction :: Warn } }
366
- fn error ( ) -> OnFail { OnFail { saw_failure : false , action : OnFailAction :: Error } }
367
- fn do_nothing ( ) -> OnFail { OnFail { saw_failure : false , action : OnFailAction :: DoNothing } }
368
- fn react ( & mut self , cx : & mut ExtCtxt , sp : Span , msg : & str , help : Option < & str > ) {
369
- match self . action {
370
- OnFailAction :: DoNothing => { }
371
- OnFailAction :: Error => {
372
- let mut err = cx. struct_span_err ( sp, msg) ;
373
- if let Some ( msg) = help { err. span_help ( sp, msg) ; }
374
- err. emit ( ) ;
375
- }
376
- OnFailAction :: Warn => {
377
- let mut warn = cx. struct_span_warn ( sp, msg) ;
378
- if let Some ( msg) = help { warn. span_help ( sp, msg) ; }
379
- warn. span_note ( sp, "The above warning will be a hard error in the next release." )
380
- . emit ( ) ;
381
- }
382
- } ;
383
- self . saw_failure = true ;
384
- }
385
- }
386
-
387
352
fn check_matcher ( cx : & mut ExtCtxt , matcher : & [ TokenTree ] ) -> bool {
388
- // Issue 30450: when we are through a warning cycle, we can just
389
- // error on all failure conditions (and remove check_matcher_old).
390
-
391
- // First run the old-pass, but *only* to find out if it would have failed.
392
- let mut on_fail = OnFail :: do_nothing ( ) ;
393
- check_matcher_old ( cx, matcher. iter ( ) , & Eof , & mut on_fail) ;
394
- // Then run the new pass, but merely warn if the old pass accepts and new pass rejects.
395
- // (Note this silently accepts code if new pass accepts.)
396
- let mut on_fail = if on_fail. saw_failure {
397
- OnFail :: error ( )
398
- } else {
399
- OnFail :: warn ( )
400
- } ;
401
- check_matcher_new ( cx, matcher, & mut on_fail) ;
402
- // matcher is valid if the new pass didn't see any error,
403
- // or if errors were considered warnings
404
- on_fail. action != OnFailAction :: Error || !on_fail. saw_failure
405
- }
406
-
407
- // returns the last token that was checked, for TokenTree::Sequence.
408
- // return value is used by recursive calls.
409
- fn check_matcher_old < ' a , I > ( cx : & mut ExtCtxt , matcher : I , follow : & Token , on_fail : & mut OnFail )
410
- -> Option < ( Span , Token ) > where I : Iterator < Item =& ' a TokenTree > {
411
- use print:: pprust:: token_to_string;
412
- use std:: iter:: once;
413
-
414
- let mut last = None ;
415
-
416
- // 2. For each token T in M:
417
- let mut tokens = matcher. peekable ( ) ;
418
- while let Some ( token) = tokens. next ( ) {
419
- last = match * token {
420
- TokenTree :: Token ( sp, MatchNt ( ref name, ref frag_spec) ) => {
421
- // ii. If T is a simple NT, look ahead to the next token T' in
422
- // M. If T' is in the set FOLLOW(NT), continue. Else; reject.
423
- if can_be_followed_by_any ( & frag_spec. name . as_str ( ) ) {
424
- continue
425
- } else {
426
- let next_token = match tokens. peek ( ) {
427
- // If T' closes a complex NT, replace T' with F
428
- Some ( & & TokenTree :: Token ( _, CloseDelim ( _) ) ) => follow. clone ( ) ,
429
- Some ( & & TokenTree :: Token ( _, ref tok) ) => tok. clone ( ) ,
430
- Some ( & & TokenTree :: Sequence ( sp, _) ) => {
431
- // Be conservative around sequences: to be
432
- // more specific, we would need to
433
- // consider FIRST sets, but also the
434
- // possibility that the sequence occurred
435
- // zero times (in which case we need to
436
- // look at the token that follows the
437
- // sequence, which may itself be a sequence,
438
- // and so on).
439
- on_fail. react ( cx, sp,
440
- & format ! ( "`${0}:{1}` is followed by a \
441
- sequence repetition, which is not \
442
- allowed for `{1}` fragments",
443
- name, frag_spec) ,
444
- None ) ;
445
- Eof
446
- } ,
447
- // die next iteration
448
- Some ( & & TokenTree :: Delimited ( _, ref delim) ) => delim. close_token ( ) ,
449
- // else, we're at the end of the macro or sequence
450
- None => follow. clone ( )
451
- } ;
452
-
453
- let tok = if let TokenTree :: Token ( _, ref tok) = * token {
454
- tok
455
- } else {
456
- unreachable ! ( )
457
- } ;
458
-
459
- // If T' is in the set FOLLOW(NT), continue. Else, reject.
460
- match ( & next_token, is_in_follow ( cx, & next_token, & frag_spec. name . as_str ( ) ) ) {
461
- ( _, Err ( ( msg, _) ) ) => {
462
- // no need for help message, those messages
463
- // are never emitted anyway...
464
- on_fail. react ( cx, sp, & msg, None ) ;
465
- continue
466
- }
467
- ( & Eof , _) => return Some ( ( sp, tok. clone ( ) ) ) ,
468
- ( _, Ok ( true ) ) => continue ,
469
- ( next, Ok ( false ) ) => {
470
- on_fail. react ( cx, sp, & format ! ( "`${0}:{1}` is followed by `{2}`, which \
471
- is not allowed for `{1}` fragments",
472
- name, frag_spec,
473
- token_to_string( next) ) , None ) ;
474
- continue
475
- } ,
476
- }
477
- }
478
- } ,
479
- TokenTree :: Sequence ( sp, ref seq) => {
480
- // iii. Else, T is a complex NT.
481
- match seq. separator {
482
- // If T has the form $(...)U+ or $(...)U* for some token U,
483
- // run the algorithm on the contents with F set to U. If it
484
- // accepts, continue, else, reject.
485
- Some ( ref u) => {
486
- let last = check_matcher_old ( cx, seq. tts . iter ( ) , u, on_fail) ;
487
- match last {
488
- // Since the delimiter isn't required after the last
489
- // repetition, make sure that the *next* token is
490
- // sane. This doesn't actually compute the FIRST of
491
- // the rest of the matcher yet, it only considers
492
- // single tokens and simple NTs. This is imprecise,
493
- // but conservatively correct.
494
- Some ( ( span, tok) ) => {
495
- let fol = match tokens. peek ( ) {
496
- Some ( & & TokenTree :: Token ( _, ref tok) ) => tok. clone ( ) ,
497
- Some ( & & TokenTree :: Delimited ( _, ref delim) ) =>
498
- delim. close_token ( ) ,
499
- Some ( _) => {
500
- on_fail. react ( cx, sp, "sequence repetition followed by \
501
- another sequence repetition, which is not allowed",
502
- None ) ;
503
- Eof
504
- } ,
505
- None => Eof
506
- } ;
507
- check_matcher_old ( cx, once ( & TokenTree :: Token ( span, tok. clone ( ) ) ) ,
508
- & fol, on_fail)
509
- } ,
510
- None => last,
511
- }
512
- } ,
513
- // If T has the form $(...)+ or $(...)*, run the algorithm
514
- // on the contents with F set to the token following the
515
- // sequence. If it accepts, continue, else, reject.
516
- None => {
517
- let fol = match tokens. peek ( ) {
518
- Some ( & & TokenTree :: Token ( _, ref tok) ) => tok. clone ( ) ,
519
- Some ( & & TokenTree :: Delimited ( _, ref delim) ) => delim. close_token ( ) ,
520
- Some ( _) => {
521
- on_fail. react ( cx, sp, "sequence repetition followed by another \
522
- sequence repetition, which is not allowed", None ) ;
523
- Eof
524
- } ,
525
- None => Eof
526
- } ;
527
- check_matcher_old ( cx, seq. tts . iter ( ) , & fol, on_fail)
528
- }
529
- }
530
- } ,
531
- TokenTree :: Token ( ..) => {
532
- // i. If T is not an NT, continue.
533
- continue
534
- } ,
535
- TokenTree :: Delimited ( _, ref tts) => {
536
- // if we don't pass in that close delimiter, we'll incorrectly consider the matcher
537
- // `{ $foo:ty }` as having a follow that isn't `RBrace`
538
- check_matcher_old ( cx, tts. tts . iter ( ) , & tts. close_token ( ) , on_fail)
539
- }
540
- }
541
- }
542
- last
543
- }
544
-
545
- fn check_matcher_new ( cx : & mut ExtCtxt , matcher : & [ TokenTree ] , on_fail : & mut OnFail ) {
546
353
let first_sets = FirstSets :: new ( matcher) ;
547
354
let empty_suffix = TokenSet :: empty ( ) ;
548
- check_matcher_core ( cx, & first_sets, matcher, & empty_suffix, on_fail) ;
355
+ let err = cx. parse_sess . span_diagnostic . err_count ( ) ;
356
+ check_matcher_core ( cx, & first_sets, matcher, & empty_suffix) ;
357
+ err == cx. parse_sess . span_diagnostic . err_count ( )
549
358
}
550
359
551
360
// The FirstSets for a matcher is a mapping from subsequences in the
@@ -785,8 +594,7 @@ impl TokenSet {
785
594
fn check_matcher_core ( cx : & mut ExtCtxt ,
786
595
first_sets : & FirstSets ,
787
596
matcher : & [ TokenTree ] ,
788
- follow : & TokenSet ,
789
- on_fail : & mut OnFail ) -> TokenSet {
597
+ follow : & TokenSet ) -> TokenSet {
790
598
use print:: pprust:: token_to_string;
791
599
792
600
let mut last = TokenSet :: empty ( ) ;
@@ -815,11 +623,11 @@ fn check_matcher_core(cx: &mut ExtCtxt,
815
623
TokenTree :: Token ( sp, ref tok) => {
816
624
let can_be_followed_by_any;
817
625
if let Err ( bad_frag) = has_legal_fragment_specifier ( tok) {
818
- on_fail . react ( cx , sp ,
819
- & format ! ( "invalid fragment specifier `{}`" , bad_frag ) ,
820
- Some ( "valid fragment specifiers are `ident `, `block`, \
821
- `stmt`, `expr`, `pat`, `ty`, `path`, `meta`, `tt` \
822
- and `item`" ) ) ;
626
+ cx . struct_span_err ( sp , & format ! ( "invalid fragment specifier `{}`" , bad_frag ) )
627
+ . help ( "valid fragment specifiers are `ident`, `block`, \
628
+ `stmt`, `expr`, `pat`, `ty`, `path `, `meta`, `tt` \
629
+ and `item`" )
630
+ . emit ( ) ;
823
631
// (This eliminates false positives and duplicates
824
632
// from error messages.)
825
633
can_be_followed_by_any = true ;
@@ -840,7 +648,7 @@ fn check_matcher_core(cx: &mut ExtCtxt,
840
648
}
841
649
TokenTree :: Delimited ( _, ref d) => {
842
650
let my_suffix = TokenSet :: singleton ( ( d. close_span , Token :: CloseDelim ( d. delim ) ) ) ;
843
- check_matcher_core ( cx, first_sets, & d. tts , & my_suffix, on_fail ) ;
651
+ check_matcher_core ( cx, first_sets, & d. tts , & my_suffix) ;
844
652
// don't track non NT tokens
845
653
last. replace_with_irrelevant ( ) ;
846
654
@@ -872,7 +680,7 @@ fn check_matcher_core(cx: &mut ExtCtxt,
872
680
// At this point, `suffix_first` is built, and
873
681
// `my_suffix` is some TokenSet that we can use
874
682
// for checking the interior of `seq_rep`.
875
- let next = check_matcher_core ( cx, first_sets, & seq_rep. tts , my_suffix, on_fail ) ;
683
+ let next = check_matcher_core ( cx, first_sets, & seq_rep. tts , my_suffix) ;
876
684
if next. maybe_empty {
877
685
last. add_all ( & next) ;
878
686
} else {
@@ -894,7 +702,7 @@ fn check_matcher_core(cx: &mut ExtCtxt,
894
702
for & ( sp, ref next_token) in & suffix_first. tokens {
895
703
match is_in_follow ( cx, next_token, & frag_spec. name . as_str ( ) ) {
896
704
Err ( ( msg, help) ) => {
897
- on_fail . react ( cx , sp, & msg, Some ( help) ) ;
705
+ cx . struct_span_err ( sp, & msg) . help ( help) . emit ( ) ;
898
706
// don't bother reporting every source of
899
707
// conflict for a particular element of `last`.
900
708
continue ' each_last;
@@ -909,15 +717,14 @@ fn check_matcher_core(cx: &mut ExtCtxt,
909
717
"may be"
910
718
} ;
911
719
912
- on_fail . react (
913
- cx , sp,
720
+ cx . span_err (
721
+ sp,
914
722
& format ! ( "`${name}:{frag}` {may_be} followed by `{next}`, which \
915
723
is not allowed for `{frag}` fragments",
916
724
name=name,
917
725
frag=frag_spec,
918
726
next=token_to_string( next_token) ,
919
- may_be=may_be) ,
920
- None
727
+ may_be=may_be)
921
728
) ;
922
729
}
923
730
}
@@ -947,33 +754,11 @@ fn token_can_be_followed_by_any(tok: &Token) -> bool {
947
754
/// ANYTHING without fear of future compatibility hazards).
948
755
fn frag_can_be_followed_by_any ( frag : & str ) -> bool {
949
756
match frag {
950
- "item" | // always terminated by `}` or `;`
951
- "block" | // exactly one token tree
952
- "ident" | // exactly one token tree
953
- "meta" | // exactly one token tree
954
- "tt" => // exactly one token tree
955
- true ,
956
-
957
- _ =>
958
- false ,
959
- }
960
- }
961
-
962
- /// True if a fragment of type `frag` can be followed by any sort of
963
- /// token. We use this (among other things) as a useful approximation
964
- /// for when `frag` can be followed by a repetition like `$(...)*` or
965
- /// `$(...)+`. In general, these can be a bit tricky to reason about,
966
- /// so we adopt a conservative position that says that any fragment
967
- /// specifier which consumes at most one token tree can be followed by
968
- /// a fragment specifier (indeed, these fragments can be followed by
969
- /// ANYTHING without fear of future compatibility hazards).
970
- fn can_be_followed_by_any ( frag : & str ) -> bool {
971
- match frag {
972
- "item" | // always terminated by `}` or `;`
757
+ "item" | // always terminated by `}` or `;`
973
758
"block" | // exactly one token tree
974
759
"ident" | // exactly one token tree
975
- "meta" | // exactly one token tree
976
- "tt" => // exactly one token tree
760
+ "meta" | // exactly one token tree
761
+ "tt" => // exactly one token tree
977
762
true ,
978
763
979
764
_ =>
0 commit comments