Skip to content

Commit 703f2e1

Browse files
committed
Auto merge of rust-lang#85041 - mibac138:suggest-generics, r=estebank
Suggest adding a type parameter for impls Add a new suggestion upon encountering an unknown type in a `impl` that suggests adding a new type parameter. This diagnostic suggests to add a new type parameter even though it may be a const parameter, however after adding the parameter and running rustc again a follow up error steers the user to change the type parameter to a const parameter. ```rust struct X<const C: ()>(); impl X<C> {} ``` suggests ``` error[E0412]: cannot find type `C` in this scope --> bar.rs:2:8 | 1 | struct X<const C: ()>(); | ------------------------ similarly named struct `X` defined here 2 | impl X<C> {} | ^ | help: a struct with a similar name exists | 2 | impl X<X> {} | ^ help: you might be missing a type parameter | 2 | impl<C> X<C> {} | ^^^ ``` After adding a type parameter the code now becomes ```rust struct X<const C: ()>(); impl<C> X<C> {} ``` and the error now fully steers the user towards the correct code ``` error[E0747]: type provided when a constant was expected --> bar.rs:2:11 | 2 | impl<C> X<C> {} | ^ | help: consider changing this type parameter to be a `const` generic | 2 | impl<const C: ()> X<C> {} | ^^^^^^^^^^^ ``` r? `@estebank` Somewhat related rust-lang#84946
2 parents 72d0725 + 4c72efc commit 703f2e1

File tree

6 files changed

+190
-9
lines changed

6 files changed

+190
-9
lines changed

compiler/rustc_resolve/src/late/diagnostics.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot};
66
use crate::{PathResult, PathSource, Segment};
77

88
use rustc_ast::visit::FnKind;
9-
use rustc_ast::{self as ast, Expr, ExprKind, Item, ItemKind, NodeId, Path, Ty, TyKind};
9+
use rustc_ast::{
10+
self as ast, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind, NodeId, Path, Ty,
11+
TyKind,
12+
};
1013
use rustc_ast_pretty::pprust::path_segment_to_string;
1114
use rustc_data_structures::fx::FxHashSet;
1215
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, SuggestionStyle};
@@ -1600,8 +1603,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
16001603
if !self.diagnostic_metadata.currently_processing_generics && !single_uppercase_char {
16011604
return None;
16021605
}
1603-
match (self.diagnostic_metadata.current_item, single_uppercase_char) {
1604-
(Some(Item { kind: ItemKind::Fn(..), ident, .. }), _) if ident.name == sym::main => {
1606+
match (self.diagnostic_metadata.current_item, single_uppercase_char, self.diagnostic_metadata.currently_processing_generics) {
1607+
(Some(Item { kind: ItemKind::Fn(..), ident, .. }), _, _) if ident.name == sym::main => {
16051608
// Ignore `fn main()` as we don't want to suggest `fn main<T>()`
16061609
}
16071610
(
@@ -1613,9 +1616,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
16131616
| kind @ ItemKind::Union(..),
16141617
..
16151618
}),
1616-
true,
1619+
true, _
16171620
)
1618-
| (Some(Item { kind, .. }), false) => {
1621+
// Without the 2nd `true`, we'd suggest `impl <T>` for `impl T` when a type `T` isn't found
1622+
| (Some(Item { kind: kind @ ItemKind::Impl(..), .. }), true, true)
1623+
| (Some(Item { kind, .. }), false, _) => {
16191624
// Likely missing type parameter.
16201625
if let Some(generics) = kind.generics() {
16211626
if span.overlaps(generics.span) {
@@ -1633,6 +1638,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
16331638
let (span, sugg) = if let [.., param] = &generics.params[..] {
16341639
let span = if let [.., bound] = &param.bounds[..] {
16351640
bound.span()
1641+
} else if let GenericParam {
1642+
kind: GenericParamKind::Const { ty, kw_span: _, default }, ..
1643+
} = param {
1644+
default.as_ref().map(|def| def.value.span).unwrap_or(ty.span)
16361645
} else {
16371646
param.ident.span
16381647
};

src/test/ui/const-generics/diagnostics.stderr

+20-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,16 @@ LL | struct A<const N: u8>;
55
| ---------------------- similarly named struct `A` defined here
66
LL | trait Foo {}
77
LL | impl Foo for A<N> {}
8-
| ^ help: a struct with a similar name exists: `A`
8+
| ^
9+
|
10+
help: a struct with a similar name exists
11+
|
12+
LL | impl Foo for A<A> {}
13+
| ^
14+
help: you might be missing a type parameter
15+
|
16+
LL | impl<N> Foo for A<N> {}
17+
| ^^^
918

1019
error[E0412]: cannot find type `T` in this scope
1120
--> $DIR/diagnostics.rs:16:32
@@ -14,7 +23,16 @@ LL | struct A<const N: u8>;
1423
| ---------------------- similarly named struct `A` defined here
1524
...
1625
LL | impl<const N: u8> Foo for C<N, T> {}
17-
| ^ help: a struct with a similar name exists: `A`
26+
| ^
27+
|
28+
help: a struct with a similar name exists
29+
|
30+
LL | impl<const N: u8> Foo for C<N, A> {}
31+
| ^
32+
help: you might be missing a type parameter
33+
|
34+
LL | impl<const N: u8, T> Foo for C<N, T> {}
35+
| ^^^
1836

1937
error[E0747]: unresolved item provided when a constant was expected
2038
--> $DIR/diagnostics.rs:7:16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#![allow(incomplete_features)]
2+
#![feature(const_generics_defaults)]
3+
4+
struct X<const N: u8>();
5+
6+
impl X<N> {}
7+
//~^ ERROR cannot find type `N` in this scope
8+
//~| ERROR unresolved item provided when a constant was expected
9+
impl<T, const A: u8 = 2> X<N> {}
10+
//~^ ERROR cannot find type `N` in this scope
11+
//~| ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
12+
//~| ERROR unresolved item provided when a constant was expected
13+
14+
fn foo(_: T) where T: Send {}
15+
//~^ ERROR cannot find type `T` in this scope
16+
//~| ERROR cannot find type `T` in this scope
17+
18+
fn bar<const N: u8>(_: A) {}
19+
//~^ ERROR cannot find type `A` in this scope
20+
21+
fn main() {
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
error[E0412]: cannot find type `N` in this scope
2+
--> $DIR/missing-type-parameter2.rs:6:8
3+
|
4+
LL | struct X<const N: u8>();
5+
| ------------------------ similarly named struct `X` defined here
6+
LL |
7+
LL | impl X<N> {}
8+
| ^
9+
|
10+
help: a struct with a similar name exists
11+
|
12+
LL | impl X<X> {}
13+
| ^
14+
help: you might be missing a type parameter
15+
|
16+
LL | impl<N> X<N> {}
17+
| ^^^
18+
19+
error[E0412]: cannot find type `N` in this scope
20+
--> $DIR/missing-type-parameter2.rs:9:28
21+
|
22+
LL | impl<T, const A: u8 = 2> X<N> {}
23+
| - ^
24+
| |
25+
| similarly named type parameter `T` defined here
26+
|
27+
help: a type parameter with a similar name exists
28+
|
29+
LL | impl<T, const A: u8 = 2> X<T> {}
30+
| ^
31+
help: you might be missing a type parameter
32+
|
33+
LL | impl<T, const A: u8 = 2, N> X<N> {}
34+
| ^^^
35+
36+
error[E0412]: cannot find type `T` in this scope
37+
--> $DIR/missing-type-parameter2.rs:14:20
38+
|
39+
LL | struct X<const N: u8>();
40+
| ------------------------ similarly named struct `X` defined here
41+
...
42+
LL | fn foo(_: T) where T: Send {}
43+
| ^
44+
|
45+
help: a struct with a similar name exists
46+
|
47+
LL | fn foo(_: T) where X: Send {}
48+
| ^
49+
help: you might be missing a type parameter
50+
|
51+
LL | fn foo<T>(_: T) where T: Send {}
52+
| ^^^
53+
54+
error[E0412]: cannot find type `T` in this scope
55+
--> $DIR/missing-type-parameter2.rs:14:11
56+
|
57+
LL | struct X<const N: u8>();
58+
| ------------------------ similarly named struct `X` defined here
59+
...
60+
LL | fn foo(_: T) where T: Send {}
61+
| ^
62+
|
63+
help: a struct with a similar name exists
64+
|
65+
LL | fn foo(_: X) where T: Send {}
66+
| ^
67+
help: you might be missing a type parameter
68+
|
69+
LL | fn foo<T>(_: T) where T: Send {}
70+
| ^^^
71+
72+
error[E0412]: cannot find type `A` in this scope
73+
--> $DIR/missing-type-parameter2.rs:18:24
74+
|
75+
LL | struct X<const N: u8>();
76+
| ------------------------ similarly named struct `X` defined here
77+
...
78+
LL | fn bar<const N: u8>(_: A) {}
79+
| ^
80+
|
81+
help: a struct with a similar name exists
82+
|
83+
LL | fn bar<const N: u8>(_: X) {}
84+
| ^
85+
help: you might be missing a type parameter
86+
|
87+
LL | fn bar<const N: u8, A>(_: A) {}
88+
| ^^^
89+
90+
error[E0747]: unresolved item provided when a constant was expected
91+
--> $DIR/missing-type-parameter2.rs:6:8
92+
|
93+
LL | impl X<N> {}
94+
| ^
95+
|
96+
help: if this generic argument was intended as a const parameter, surround it with braces
97+
|
98+
LL | impl X<{ N }> {}
99+
| ^ ^
100+
101+
error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
102+
--> $DIR/missing-type-parameter2.rs:9:15
103+
|
104+
LL | impl<T, const A: u8 = 2> X<N> {}
105+
| ^
106+
107+
error[E0747]: unresolved item provided when a constant was expected
108+
--> $DIR/missing-type-parameter2.rs:9:28
109+
|
110+
LL | impl<T, const A: u8 = 2> X<N> {}
111+
| ^
112+
|
113+
help: if this generic argument was intended as a const parameter, surround it with braces
114+
|
115+
LL | impl<T, const A: u8 = 2> X<{ N }> {}
116+
| ^ ^
117+
118+
error: aborting due to 8 previous errors
119+
120+
Some errors have detailed explanations: E0412, E0747.
121+
For more information about an error, try `rustc --explain E0412`.

src/test/ui/traits/issue-75627.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error[E0412]: cannot find type `T` in this scope
22
--> $DIR/issue-75627.rs:3:26
33
|
44
LL | unsafe impl Send for Foo<T> {}
5-
| ^ not found in this scope
5+
| - ^ not found in this scope
6+
| |
7+
| help: you might be missing a type parameter: `<T>`
68

79
error: aborting due to previous error
810

src/test/ui/traits/issue-78372.stderr

+10-1
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,18 @@ error[E0412]: cannot find type `U` in this scope
1313
--> $DIR/issue-78372.rs:3:31
1414
|
1515
LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
16-
| - ^ help: a type parameter with a similar name exists: `T`
16+
| - ^
1717
| |
1818
| similarly named type parameter `T` defined here
19+
|
20+
help: a type parameter with a similar name exists
21+
|
22+
LL | impl<T> DispatchFromDyn<Smaht<T, MISC>> for T {}
23+
| ^
24+
help: you might be missing a type parameter
25+
|
26+
LL | impl<T, U> DispatchFromDyn<Smaht<U, MISC>> for T {}
27+
| ^^^
1928

2029
error[E0412]: cannot find type `MISC` in this scope
2130
--> $DIR/issue-78372.rs:3:34

0 commit comments

Comments
 (0)