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