Skip to content

Commit 3401ecb

Browse files
committed
Add suggestion
1 parent b5bbea0 commit 3401ecb

8 files changed

+156
-85
lines changed

src/libsyntax/ext/tt/macro_rules.rs

+49-6
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,7 @@ fn check_matcher_core(sess: &ParseSess,
757757
// against SUFFIX
758758
continue 'each_token;
759759
}
760-
TokenTree::Sequence(sp, ref seq_rep) => {
760+
TokenTree::Sequence(delim_sp, ref seq_rep) => {
761761
suffix_first = build_suffix_first();
762762
// The trick here: when we check the interior, we want
763763
// to include the separator (if any) as a potential
@@ -772,16 +772,16 @@ fn check_matcher_core(sess: &ParseSess,
772772
let mut new;
773773
let my_suffix = if let Some(ref u) = seq_rep.separator {
774774
new = suffix_first.clone();
775-
new.add_one_maybe(TokenTree::Token(sp.entire(), u.clone()));
775+
new.add_one_maybe(TokenTree::Token(delim_sp.entire(), u.clone()));
776776
&new
777777
} else {
778778
if let (
779779
Some(tok),
780780
Some(TokenTree::MetaVarDecl(sp, name, frag_spec)),
781781
) = (seq_rep.tts.first(), seq_rep.tts.last()) {
782782
match is_in_follow(tok, &frag_spec.as_str()) {
783-
Err(_) | Ok(true) => {} // handled elsewhere
784-
Ok(false) => {
783+
IsInFollow::Invalid(..) | IsInFollow::Yes => {} // handled elsewhere
784+
IsInFollow::No(possible) => {
785785
let tok_sp = tok.span();
786786
let next = if *sp == tok_sp {
787787
"itself".to_owned()
@@ -815,6 +815,49 @@ fn check_matcher_core(sess: &ParseSess,
815815
"this is the first fragment in the evaluated repetition",
816816
);
817817
}
818+
let sugg_span = sess.source_map().next_point(delim_sp.close);
819+
let msg = "allowed there are: ";
820+
let sugg_msg = "add a valid separator for the repetition to be \
821+
unambiguous";
822+
match &possible[..] {
823+
&[] => {}
824+
&[t] => {
825+
err.note(&format!(
826+
"only {} is allowed after `{}` fragments",
827+
t,
828+
frag_spec,
829+
));
830+
if t.starts_with('`') && t.ends_with('`') {
831+
err.span_suggestion_with_applicability(
832+
sugg_span,
833+
&format!("{}, for example", sugg_msg),
834+
(&t[1..t.len()-1]).to_owned(),
835+
Applicability::MaybeIncorrect,
836+
);
837+
} else {
838+
err.note(sugg_msg);
839+
}
840+
}
841+
ts => {
842+
err.note(&format!(
843+
"{}{} or {}",
844+
msg,
845+
ts[..ts.len() - 1].iter().map(|s| *s)
846+
.collect::<Vec<_>>().join(", "),
847+
ts[ts.len() - 1],
848+
));
849+
if ts[0].starts_with('`') && ts[0].ends_with('`') {
850+
err.span_suggestion_with_applicability(
851+
sugg_span,
852+
&format!("{}, for example", sugg_msg),
853+
(&ts[0][1..ts[0].len()-1]).to_owned(),
854+
Applicability::MaybeIncorrect,
855+
);
856+
} else {
857+
err.note(sugg_msg);
858+
}
859+
}
860+
}
818861
err.emit();
819862
}
820863
}
@@ -979,7 +1022,7 @@ fn is_in_follow(tok: &quoted::TokenTree, frag: &str) -> IsInFollow {
9791022
IsInFollow::Yes
9801023
},
9811024
"stmt" | "expr" => {
982-
let tokens = vec!["`=>`", "`,`", "`;`"];
1025+
let tokens = vec!["`;`", "`=>`", "`,`"];
9831026
match *tok {
9841027
TokenTree::Token(_, ref tok) => match *tok {
9851028
FatArrow | Comma | Semi => IsInFollow::Yes,
@@ -1001,7 +1044,7 @@ fn is_in_follow(tok: &quoted::TokenTree, frag: &str) -> IsInFollow {
10011044
},
10021045
"path" | "ty" => {
10031046
let tokens = vec![
1004-
"`{`", "`[`", "`=>`", "`,`", "`>`","`=`", "`:`", "`;`", "`|`", "`as`",
1047+
"`,`", "`{`", "`[`", "`=>`", "`>`","`=`", "`:`", "`;`", "`|`", "`as`",
10051048
"`where`",
10061049
];
10071050
match *tok {

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

+6
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

+6
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

+6
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)