Skip to content

Commit a16db3d

Browse files
authored
Rollup merge of #82774 - JohnTitor:bad-diag-for-anon-params-with-ref, r=estebank
Fix bad diagnostics for anon params with ref and/or qualified paths Fixes #82729 It's easier to review with hiding whitespace changes.
2 parents e655fb6 + 55bdf7f commit a16db3d

File tree

4 files changed

+172
-36
lines changed

4 files changed

+172
-36
lines changed

compiler/rustc_parse/src/parser/diagnostics.rs

+72-32
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ impl<'a> Parser<'a> {
640640
}
641641
}
642642
Err(mut err) => {
643-
// We could't parse generic parameters, unlikely to be a turbofish. Rely on
643+
// We couldn't parse generic parameters, unlikely to be a turbofish. Rely on
644644
// generic parse error instead.
645645
err.cancel();
646646
*self = snapshot;
@@ -1242,7 +1242,7 @@ impl<'a> Parser<'a> {
12421242
let is_question = self.eat(&token::Question); // Handle `await? <expr>`.
12431243
let expr = if self.token == token::OpenDelim(token::Brace) {
12441244
// Handle `await { <expr> }`.
1245-
// This needs to be handled separatedly from the next arm to avoid
1245+
// This needs to be handled separately from the next arm to avoid
12461246
// interpreting `await { <expr> }?` as `<expr>?.await`.
12471247
self.parse_block_expr(None, self.token.span, BlockCheckMode::Default, AttrVec::new())
12481248
} else {
@@ -1613,42 +1613,82 @@ impl<'a> Parser<'a> {
16131613
Applicability::HasPlaceholders,
16141614
);
16151615
return Some(ident);
1616-
} else if let PatKind::Ident(_, ident, _) = pat.kind {
1617-
if require_name
1618-
&& (self.token == token::Comma
1619-
|| self.token == token::Lt
1620-
|| self.token == token::CloseDelim(token::Paren))
1621-
{
1622-
// `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
1623-
if first_param {
1624-
err.span_suggestion(
1625-
pat.span,
1626-
"if this is a `self` type, give it a parameter name",
1627-
format!("self: {}", ident),
1628-
Applicability::MaybeIncorrect,
1629-
);
1616+
} else if require_name
1617+
&& (self.token == token::Comma
1618+
|| self.token == token::Lt
1619+
|| self.token == token::CloseDelim(token::Paren))
1620+
{
1621+
let rfc_note = "anonymous parameters are removed in the 2018 edition (see RFC 1685)";
1622+
1623+
let (ident, self_sugg, param_sugg, type_sugg) = match pat.kind {
1624+
PatKind::Ident(_, ident, _) => (
1625+
ident,
1626+
format!("self: {}", ident),
1627+
format!("{}: TypeName", ident),
1628+
format!("_: {}", ident),
1629+
),
1630+
// Also catches `fn foo(&a)`.
1631+
PatKind::Ref(ref pat, mutab)
1632+
if matches!(pat.clone().into_inner().kind, PatKind::Ident(..)) =>
1633+
{
1634+
match pat.clone().into_inner().kind {
1635+
PatKind::Ident(_, ident, _) => {
1636+
let mutab = mutab.prefix_str();
1637+
(
1638+
ident,
1639+
format!("self: &{}{}", mutab, ident),
1640+
format!("{}: &{}TypeName", ident, mutab),
1641+
format!("_: &{}{}", mutab, ident),
1642+
)
1643+
}
1644+
_ => unreachable!(),
1645+
}
16301646
}
1631-
// Avoid suggesting that `fn foo(HashMap<u32>)` is fixed with a change to
1632-
// `fn foo(HashMap: TypeName<u32>)`.
1633-
if self.token != token::Lt {
1634-
err.span_suggestion(
1635-
pat.span,
1636-
"if this is a parameter name, give it a type",
1637-
format!("{}: TypeName", ident),
1638-
Applicability::HasPlaceholders,
1639-
);
1647+
_ => {
1648+
// Otherwise, try to get a type and emit a suggestion.
1649+
if let Some(ty) = pat.to_ty() {
1650+
err.span_suggestion_verbose(
1651+
pat.span,
1652+
"explicitly ignore the parameter name",
1653+
format!("_: {}", pprust::ty_to_string(&ty)),
1654+
Applicability::MachineApplicable,
1655+
);
1656+
err.note(rfc_note);
1657+
}
1658+
1659+
return None;
16401660
}
1661+
};
1662+
1663+
// `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
1664+
if first_param {
16411665
err.span_suggestion(
16421666
pat.span,
1643-
"if this is a type, explicitly ignore the parameter name",
1644-
format!("_: {}", ident),
1645-
Applicability::MachineApplicable,
1667+
"if this is a `self` type, give it a parameter name",
1668+
self_sugg,
1669+
Applicability::MaybeIncorrect,
16461670
);
1647-
err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)");
1648-
1649-
// Don't attempt to recover by using the `X` in `X<Y>` as the parameter name.
1650-
return if self.token == token::Lt { None } else { Some(ident) };
16511671
}
1672+
// Avoid suggesting that `fn foo(HashMap<u32>)` is fixed with a change to
1673+
// `fn foo(HashMap: TypeName<u32>)`.
1674+
if self.token != token::Lt {
1675+
err.span_suggestion(
1676+
pat.span,
1677+
"if this is a parameter name, give it a type",
1678+
param_sugg,
1679+
Applicability::HasPlaceholders,
1680+
);
1681+
}
1682+
err.span_suggestion(
1683+
pat.span,
1684+
"if this is a type, explicitly ignore the parameter name",
1685+
type_sugg,
1686+
Applicability::MachineApplicable,
1687+
);
1688+
err.note(rfc_note);
1689+
1690+
// Don't attempt to recover by using the `X` in `X<Y>` as the parameter name.
1691+
return if self.token == token::Lt { None } else { Some(ident) };
16521692
}
16531693
None
16541694
}

src/test/ui/anon-params/anon-params-denied-2018.rs

+14
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,20 @@
55
trait T {
66
fn foo(i32); //~ expected one of `:`, `@`, or `|`, found `)`
77

8+
// Also checks with `&`
9+
fn foo_with_ref(&mut i32);
10+
//~^ ERROR expected one of `:`, `@`, or `|`, found `)`
11+
12+
fn foo_with_qualified_path(<Bar as T>::Baz);
13+
//~^ ERROR expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
14+
15+
fn foo_with_qualified_path_and_ref(&<Bar as T>::Baz);
16+
//~^ ERROR expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
17+
18+
fn foo_with_multiple_qualified_paths(<Bar as T>::Baz, <Bar as T>::Baz);
19+
//~^ ERROR expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `,`
20+
//~| ERROR expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
21+
822
fn bar_with_default_impl(String, String) {}
923
//~^ ERROR expected one of `:`
1024
//~| ERROR expected one of `:`

src/test/ui/anon-params/anon-params-denied-2018.stderr

+72-4
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,76 @@ help: if this is a type, explicitly ignore the parameter name
1818
LL | fn foo(_: i32);
1919
| ^^^^^^
2020

21+
error: expected one of `:`, `@`, or `|`, found `)`
22+
--> $DIR/anon-params-denied-2018.rs:9:29
23+
|
24+
LL | fn foo_with_ref(&mut i32);
25+
| ^ expected one of `:`, `@`, or `|`
26+
|
27+
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
28+
help: if this is a `self` type, give it a parameter name
29+
|
30+
LL | fn foo_with_ref(self: &mut i32);
31+
| ^^^^^^^^^^^^^^
32+
help: if this is a parameter name, give it a type
33+
|
34+
LL | fn foo_with_ref(i32: &mut TypeName);
35+
| ^^^^^^^^^^^^^^^^^^
36+
help: if this is a type, explicitly ignore the parameter name
37+
|
38+
LL | fn foo_with_ref(_: &mut i32);
39+
| ^^^^^^^^^^^
40+
41+
error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
42+
--> $DIR/anon-params-denied-2018.rs:12:47
43+
|
44+
LL | fn foo_with_qualified_path(<Bar as T>::Baz);
45+
| ^ expected one of 8 possible tokens
46+
|
47+
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
48+
help: explicitly ignore the parameter name
49+
|
50+
LL | fn foo_with_qualified_path(_: <Bar as T>::Baz);
51+
| ^^^^^^^^^^^^^^^^^^
52+
53+
error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
54+
--> $DIR/anon-params-denied-2018.rs:15:56
55+
|
56+
LL | fn foo_with_qualified_path_and_ref(&<Bar as T>::Baz);
57+
| ^ expected one of 8 possible tokens
58+
|
59+
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
60+
help: explicitly ignore the parameter name
61+
|
62+
LL | fn foo_with_qualified_path_and_ref(_: &<Bar as T>::Baz);
63+
| ^^^^^^^^^^^^^^^^^^^
64+
65+
error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `,`
66+
--> $DIR/anon-params-denied-2018.rs:18:57
67+
|
68+
LL | fn foo_with_multiple_qualified_paths(<Bar as T>::Baz, <Bar as T>::Baz);
69+
| ^ expected one of 8 possible tokens
70+
|
71+
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
72+
help: explicitly ignore the parameter name
73+
|
74+
LL | fn foo_with_multiple_qualified_paths(_: <Bar as T>::Baz, <Bar as T>::Baz);
75+
| ^^^^^^^^^^^^^^^^^^
76+
77+
error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
78+
--> $DIR/anon-params-denied-2018.rs:18:74
79+
|
80+
LL | fn foo_with_multiple_qualified_paths(<Bar as T>::Baz, <Bar as T>::Baz);
81+
| ^ expected one of 8 possible tokens
82+
|
83+
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
84+
help: explicitly ignore the parameter name
85+
|
86+
LL | fn foo_with_multiple_qualified_paths(<Bar as T>::Baz, _: <Bar as T>::Baz);
87+
| ^^^^^^^^^^^^^^^^^^
88+
2189
error: expected one of `:`, `@`, or `|`, found `,`
22-
--> $DIR/anon-params-denied-2018.rs:8:36
90+
--> $DIR/anon-params-denied-2018.rs:22:36
2391
|
2492
LL | fn bar_with_default_impl(String, String) {}
2593
| ^ expected one of `:`, `@`, or `|`
@@ -39,7 +107,7 @@ LL | fn bar_with_default_impl(_: String, String) {}
39107
| ^^^^^^^^^
40108

41109
error: expected one of `:`, `@`, or `|`, found `)`
42-
--> $DIR/anon-params-denied-2018.rs:8:44
110+
--> $DIR/anon-params-denied-2018.rs:22:44
43111
|
44112
LL | fn bar_with_default_impl(String, String) {}
45113
| ^ expected one of `:`, `@`, or `|`
@@ -55,7 +123,7 @@ LL | fn bar_with_default_impl(String, _: String) {}
55123
| ^^^^^^^^^
56124

57125
error: expected one of `:`, `@`, or `|`, found `,`
58-
--> $DIR/anon-params-denied-2018.rs:13:22
126+
--> $DIR/anon-params-denied-2018.rs:27:22
59127
|
60128
LL | fn baz(a:usize, b, c: usize) -> usize {
61129
| ^ expected one of `:`, `@`, or `|`
@@ -70,5 +138,5 @@ help: if this is a type, explicitly ignore the parameter name
70138
LL | fn baz(a:usize, _: b, c: usize) -> usize {
71139
| ^^^^
72140

73-
error: aborting due to 4 previous errors
141+
error: aborting due to 9 previous errors
74142

src/test/ui/parser/lifetime-in-pattern.stderr

+14
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,20 @@ error: expected one of `:`, `@`, or `|`, found `)`
99
|
1010
LL | fn test(&'a str) {
1111
| ^ expected one of `:`, `@`, or `|`
12+
|
13+
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
14+
help: if this is a `self` type, give it a parameter name
15+
|
16+
LL | fn test(self: &str) {
17+
| ^^^^^^^^^^
18+
help: if this is a parameter name, give it a type
19+
|
20+
LL | fn test(str: &TypeName) {
21+
| ^^^^^^^^^^^^^^
22+
help: if this is a type, explicitly ignore the parameter name
23+
|
24+
LL | fn test(_: &str) {
25+
| ^^^^^^^
1226

1327
error: aborting due to 2 previous errors
1428

0 commit comments

Comments
 (0)