Suggest replacing `.` with `::` in more error diagnostics.
First commit makes the existing "help: use the path separator to refer to an item" also work when the base is a type alias, not just a trait/module/struct.
The existing unconditional `DefKind::Mod | DefKind::Trait` match arm is changed to a conditional `DefKind::Mod | DefKind::Trait | DefKind::TyAlias` arm that only matches if the `path_sep` suggestion-adding closure succeeds, so as not to stop the later `DefKind::TyAlias`-specific suggestions if the path-sep suggestion does not apply. This shouldn't change behavior for `Mod` or `Trait` (due to the default arm's `return false` etc).
This commit also updates `tests/ui/resolve/issue-22692.rs` to reflect this, and also renames it to something more meaningful.
This commit also makes the `bad_struct_syntax_suggestion` closure take `err` as a parameter instead of capturing it, since otherwise caused borrowing errors due to the change to using `path_sep` in a pattern guard.
<details> <summary> Type alias diagnostic example </summary>
```rust
type S = String;
fn main() {
let _ = S.new;
}
```
```diff
error[E0423]: expected value, found type alias `S`
--> diag7.rs:4:13
|
4 | let _ = S.new;
| ^
|
- = note: can't use a type alias as a constructor
+ help: use the path separator to refer to an item
+ |
+4 | let _ = S::new;
+ | ~~
```
</details>
Second commit adds some cases for `enum`s, where if there is a field/method expression where the field/method has the name of a unit/tuple variant, we assume the user intended to create that variant[^1] and suggest replacing the `.` from the field/method suggestion with a `::` path separator. If no such variant is found (or if the error is not a field/method expression), we give the existing suggestion that suggests adding `::TupleVariant(/* fields */)` after the enum.
<details> <summary> Enum diagnostic example </summary>
```rust
enum Foo {
A(u32),
B,
C { x: u32 },
}
fn main() {
let _ = Foo.A(42); // changed
let _ = Foo.B; // changed
let _ = Foo.D(42); // no change
let _ = Foo.D; // no change
let _ = Foo(42); // no change
}
```
```diff
error[E0423]: expected value, found enum `Foo`
--> diag8.rs:8:13
|
8 | let _ = Foo.A(42); // changed
| ^^^
|
note: the enum is defined here
--> diag8.rs:1:1
|
1 | / enum Foo {
2 | | A(u32),
3 | | B,
4 | | C { x: u32 },
5 | | }
| |_^
-help: you might have meant to use the following enum variant
- |
-8 | let _ = Foo::B.A(42); // changed
- | ~~~~~~
-help: alternatively, the following enum variant is available
+help: use the path separator to refer to a variant
|
-8 | let _ = (Foo::A(/* fields */)).A(42); // changed
- | ~~~~~~~~~~~~~~~~~~~~~~
+8 | let _ = Foo::A(42); // changed
+ | ~~
error[E0423]: expected value, found enum `Foo`
--> diag8.rs:9:13
|
9 | let _ = Foo.B; // changed
| ^^^
|
note: the enum is defined here
--> diag8.rs:1:1
|
1 | / enum Foo {
2 | | A(u32),
3 | | B,
4 | | C { x: u32 },
5 | | }
| |_^
-help: you might have meant to use the following enum variant
- |
-9 | let _ = Foo::B.B; // changed
- | ~~~~~~
-help: alternatively, the following enum variant is available
+help: use the path separator to refer to a variant
|
-9 | let _ = (Foo::A(/* fields */)).B; // changed
- | ~~~~~~~~~~~~~~~~~~~~~~
+9 | let _ = Foo::B; // changed
+ | ~~
error[E0423]: expected value, found enum `Foo`
--> diag8.rs:10:13
|
10 | let _ = Foo.D(42); // no change
| ^^^
|
note: the enum is defined here
--> diag8.rs:1:1
|
1 | / enum Foo {
2 | | A(u32),
3 | | B,
4 | | C { x: u32 },
5 | | }
| |_^
help: you might have meant to use the following enum variant
|
10 | let _ = Foo::B.D(42); // no change
| ~~~~~~
help: alternatively, the following enum variant is available
|
10 | let _ = (Foo::A(/* fields */)).D(42); // no change
| ~~~~~~~~~~~~~~~~~~~~~~
error[E0423]: expected value, found enum `Foo`
--> diag8.rs:11:13
|
11 | let _ = Foo.D; // no change
| ^^^
|
note: the enum is defined here
--> diag8.rs:1:1
|
1 | / enum Foo {
2 | | A(u32),
3 | | B,
4 | | C { x: u32 },
5 | | }
| |_^
help: you might have meant to use the following enum variant
|
11 | let _ = Foo::B.D; // no change
| ~~~~~~
help: alternatively, the following enum variant is available
|
11 | let _ = (Foo::A(/* fields */)).D; // no change
| ~~~~~~~~~~~~~~~~~~~~~~
error[E0423]: expected function, tuple struct or tuple variant, found enum `Foo`
--> diag8.rs:12:13
|
12 | let _ = Foo(42); // no change
| ^^^ help: try to construct one of the enum's variants: `Foo::A`
|
= help: you might have meant to construct the enum's non-tuple variant
note: the enum is defined here
--> diag8.rs:1:1
|
1 | / enum Foo {
2 | | A(u32),
3 | | B,
4 | | C { x: u32 },
5 | | }
| |_^
error: aborting due to 5 previous errors
```
</details>
[^1]: or if it's a field expression and a tuple variant, that they meant to refer the variant constructor.