Skip to content

Commit ea355bc

Browse files
committed
Fix bad diagnostics for anon params with ref
1 parent f5d8117 commit ea355bc

File tree

4 files changed

+96
-35
lines changed

4 files changed

+96
-35
lines changed

compiler/rustc_parse/src/parser/diagnostics.rs

+54-31
Original file line numberDiff line numberDiff line change
@@ -1613,42 +1613,65 @@ 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-
);
1630-
}
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-
);
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 (ident, self_sugg, param_sugg, type_sugg) = match pat.kind {
1622+
PatKind::Ident(_, ident, _) => (
1623+
ident,
1624+
format!("self: {}", ident),
1625+
format!("{}: TypeName", ident),
1626+
format!("_: {}", ident),
1627+
),
1628+
// Also catches `fn foo(&a)`.
1629+
PatKind::Ref(ref pat, mutab) => {
1630+
if let PatKind::Ident(_, ident, _) = pat.clone().into_inner().kind {
1631+
let mutab = mutab.prefix_str();
1632+
(
1633+
ident,
1634+
format!("self: &{}{}", mutab, ident),
1635+
format!("{}: &{}TypeName", ident, mutab),
1636+
format!("_: &{}{}", mutab, ident),
1637+
)
1638+
} else {
1639+
return None;
1640+
}
16401641
}
1642+
// Ignore other `PatKind`.
1643+
_ => return None,
1644+
};
1645+
1646+
// `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
1647+
if first_param {
16411648
err.span_suggestion(
16421649
pat.span,
1643-
"if this is a type, explicitly ignore the parameter name",
1644-
format!("_: {}", ident),
1645-
Applicability::MachineApplicable,
1650+
"if this is a `self` type, give it a parameter name",
1651+
self_sugg,
1652+
Applicability::MaybeIncorrect,
1653+
);
1654+
}
1655+
// Avoid suggesting that `fn foo(HashMap<u32>)` is fixed with a change to
1656+
// `fn foo(HashMap: TypeName<u32>)`.
1657+
if self.token != token::Lt {
1658+
err.span_suggestion(
1659+
pat.span,
1660+
"if this is a parameter name, give it a type",
1661+
param_sugg,
1662+
Applicability::HasPlaceholders,
16461663
);
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) };
16511664
}
1665+
err.span_suggestion(
1666+
pat.span,
1667+
"if this is a type, explicitly ignore the parameter name",
1668+
type_sugg,
1669+
Applicability::MachineApplicable,
1670+
);
1671+
err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)");
1672+
1673+
// Don't attempt to recover by using the `X` in `X<Y>` as the parameter name.
1674+
return if self.token == token::Lt { None } else { Some(ident) };
16521675
}
16531676
None
16541677
}

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

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
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+
812
fn bar_with_default_impl(String, String) {}
913
//~^ ERROR expected one of `:`
1014
//~| ERROR expected one of `:`

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

+24-4
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,28 @@ 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+
2141
error: expected one of `:`, `@`, or `|`, found `,`
22-
--> $DIR/anon-params-denied-2018.rs:8:36
42+
--> $DIR/anon-params-denied-2018.rs:12:36
2343
|
2444
LL | fn bar_with_default_impl(String, String) {}
2545
| ^ expected one of `:`, `@`, or `|`
@@ -39,7 +59,7 @@ LL | fn bar_with_default_impl(_: String, String) {}
3959
| ^^^^^^^^^
4060

4161
error: expected one of `:`, `@`, or `|`, found `)`
42-
--> $DIR/anon-params-denied-2018.rs:8:44
62+
--> $DIR/anon-params-denied-2018.rs:12:44
4363
|
4464
LL | fn bar_with_default_impl(String, String) {}
4565
| ^ expected one of `:`, `@`, or `|`
@@ -55,7 +75,7 @@ LL | fn bar_with_default_impl(String, _: String) {}
5575
| ^^^^^^^^^
5676

5777
error: expected one of `:`, `@`, or `|`, found `,`
58-
--> $DIR/anon-params-denied-2018.rs:13:22
78+
--> $DIR/anon-params-denied-2018.rs:17:22
5979
|
6080
LL | fn baz(a:usize, b, c: usize) -> usize {
6181
| ^ expected one of `:`, `@`, or `|`
@@ -70,5 +90,5 @@ help: if this is a type, explicitly ignore the parameter name
7090
LL | fn baz(a:usize, _: b, c: usize) -> usize {
7191
| ^^^^
7292

73-
error: aborting due to 4 previous errors
93+
error: aborting due to 5 previous errors
7494

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)