Skip to content

Commit 2c1008c

Browse files
committed
Add suggestion
1 parent d55936d commit 2c1008c

8 files changed

+156
-85
lines changed

src/libsyntax/ext/tt/macro_rules.rs

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ fn check_matcher_core(sess: &ParseSess,
785785
// against SUFFIX
786786
continue 'each_token;
787787
}
788-
TokenTree::Sequence(sp, ref seq_rep) => {
788+
TokenTree::Sequence(delim_sp, ref seq_rep) => {
789789
suffix_first = build_suffix_first();
790790
// The trick here: when we check the interior, we want
791791
// to include the separator (if any) as a potential
@@ -800,16 +800,16 @@ fn check_matcher_core(sess: &ParseSess,
800800
let mut new;
801801
let my_suffix = if let Some(ref u) = seq_rep.separator {
802802
new = suffix_first.clone();
803-
new.add_one_maybe(TokenTree::Token(sp.entire(), u.clone()));
803+
new.add_one_maybe(TokenTree::Token(delim_sp.entire(), u.clone()));
804804
&new
805805
} else {
806806
if let (
807807
Some(tok),
808808
Some(TokenTree::MetaVarDecl(sp, name, frag_spec)),
809809
) = (seq_rep.tts.first(), seq_rep.tts.last()) {
810810
match is_in_follow(tok, &frag_spec.as_str()) {
811-
Err(_) | Ok(true) => {} // handled elsewhere
812-
Ok(false) => {
811+
IsInFollow::Invalid(..) | IsInFollow::Yes => {} // handled elsewhere
812+
IsInFollow::No(possible) => {
813813
let tok_sp = tok.span();
814814
let next = if *sp == tok_sp {
815815
"itself".to_owned()
@@ -843,6 +843,49 @@ fn check_matcher_core(sess: &ParseSess,
843843
"this is the first fragment in the evaluated repetition",
844844
);
845845
}
846+
let sugg_span = sess.source_map().next_point(delim_sp.close);
847+
let msg = "allowed there are: ";
848+
let sugg_msg = "add a valid separator for the repetition to be \
849+
unambiguous";
850+
match &possible[..] {
851+
&[] => {}
852+
&[t] => {
853+
err.note(&format!(
854+
"only {} is allowed after `{}` fragments",
855+
t,
856+
frag_spec,
857+
));
858+
if t.starts_with('`') && t.ends_with('`') {
859+
err.span_suggestion_with_applicability(
860+
sugg_span,
861+
&format!("{}, for example", sugg_msg),
862+
(&t[1..t.len()-1]).to_owned(),
863+
Applicability::MaybeIncorrect,
864+
);
865+
} else {
866+
err.note(sugg_msg);
867+
}
868+
}
869+
ts => {
870+
err.note(&format!(
871+
"{}{} or {}",
872+
msg,
873+
ts[..ts.len() - 1].iter().map(|s| *s)
874+
.collect::<Vec<_>>().join(", "),
875+
ts[ts.len() - 1],
876+
));
877+
if ts[0].starts_with('`') && ts[0].ends_with('`') {
878+
err.span_suggestion_with_applicability(
879+
sugg_span,
880+
&format!("{}, for example", sugg_msg),
881+
(&ts[0][1..ts[0].len()-1]).to_owned(),
882+
Applicability::MaybeIncorrect,
883+
);
884+
} else {
885+
err.note(sugg_msg);
886+
}
887+
}
888+
}
846889
err.emit();
847890
}
848891
}
@@ -1007,7 +1050,7 @@ fn is_in_follow(tok: &quoted::TokenTree, frag: &str) -> IsInFollow {
10071050
IsInFollow::Yes
10081051
},
10091052
"stmt" | "expr" => {
1010-
let tokens = vec!["`=>`", "`,`", "`;`"];
1053+
let tokens = vec!["`;`", "`=>`", "`,`"];
10111054
match *tok {
10121055
TokenTree::Token(_, ref tok) => match *tok {
10131056
FatArrow | Comma | Semi => IsInFollow::Yes,
@@ -1029,7 +1072,7 @@ fn is_in_follow(tok: &quoted::TokenTree, frag: &str) -> IsInFollow {
10291072
},
10301073
"path" | "ty" => {
10311074
let tokens = vec![
1032-
"`{`", "`[`", "`=>`", "`,`", "`>`","`=`", "`:`", "`;`", "`|`", "`as`",
1075+
"`,`", "`{`", "`[`", "`=>`", "`>`","`=`", "`:`", "`;`", "`|`", "`as`",
10331076
"`where`",
10341077
];
10351078
match *tok {

src/test/ui/issues/issue-42755.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ error: `$p:vis` is followed (through repetition) by itself, which is not allowed
33
|
44
LL | ($($p:vis)*) => {}
55
| ^^^^^^ this fragment is followed by itself without a valid separator
6+
|
7+
= note: allowed there are: `,`, an ident or a type
8+
help: add a valid separator for the repetition to be unambiguous, for example
9+
|
10+
LL | ($($p:vis),*) => {}
11+
| ^
612

713
error: repetition matches empty token tree
814
--> $DIR/issue-42755.rs:13:7

src/test/ui/macros/incorrrect-repetition-2.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ error: `$a:expr` is followed (through repetition) by itself, which is not allowe
33
|
44
LL | ($($a:expr)*) => {};
55
| ^^^^^^^ this fragment is followed by itself without a valid separator
6+
|
7+
= note: allowed there are: `;`, `=>` or `,`
8+
help: add a valid separator for the repetition to be unambiguous, for example
9+
|
10+
LL | ($($a:expr);*) => {};
11+
| ^
612

713
error[E0601]: `main` function not found in crate `incorrrect_repetition_2`
814
|

src/test/ui/macros/incorrrect-repetition.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ LL | ($($i:ident $e:expr)*) => {}
55
| -------- ^^^^^^^ this fragment is followed by the first fragment in this repetition without a valid separator
66
| |
77
| this is the first fragment in the evaluated repetition
8+
|
9+
= note: allowed there are: `;`, `=>` or `,`
10+
help: add a valid separator for the repetition to be unambiguous, for example
11+
|
12+
LL | ($($i:ident $e:expr);*) => {}
13+
| ^
814

915
error: aborting due to previous error
1016

0 commit comments

Comments
 (0)