Skip to content

Commit 8e87fe9

Browse files
authored
Rollup merge of rust-lang#82055 - JulianKnodt:ty_where_const, r=estebank
Add diagnostics for specific cases for const/type mismatch err For now, this adds at least more information so better diagnostics can be emitted for const mismatch errors. I'm not sure what exactly we want to emit, so I've left notes there temporarily, also to see if this is the right approach r? ``@lcnr`` cc: ``@estebank``
2 parents f5417bd + f520295 commit 8e87fe9

File tree

6 files changed

+134
-29
lines changed

6 files changed

+134
-29
lines changed

compiler/rustc_typeck/src/astconv/generics.rs

+50-15
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ use crate::astconv::{
66
use crate::errors::AssocTypeBindingNotAllowed;
77
use crate::structured_errors::{StructuredDiagnostic, WrongNumberOfGenericArgs};
88
use rustc_ast::ast::ParamKindOrd;
9-
use rustc_errors::{struct_span_err, Applicability, ErrorReported};
9+
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
1010
use rustc_hir as hir;
11+
use rustc_hir::def::{DefKind, Res};
1112
use rustc_hir::def_id::DefId;
1213
use rustc_hir::GenericArg;
1314
use rustc_middle::ty::{
@@ -43,23 +44,57 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
4344
}
4445
}
4546

47+
let add_braces_suggestion = |arg: &GenericArg<'_>, err: &mut DiagnosticBuilder<'_>| {
48+
let suggestions = vec![
49+
(arg.span().shrink_to_lo(), String::from("{ ")),
50+
(arg.span().shrink_to_hi(), String::from(" }")),
51+
];
52+
err.multipart_suggestion(
53+
"if this generic argument was intended as a const parameter, \
54+
surround it with braces",
55+
suggestions,
56+
Applicability::MaybeIncorrect,
57+
);
58+
};
59+
4660
// Specific suggestion set for diagnostics
4761
match (arg, &param.kind) {
4862
(
49-
GenericArg::Type(hir::Ty { kind: hir::TyKind::Path { .. }, .. }),
50-
GenericParamDefKind::Const { .. },
51-
) => {
52-
let suggestions = vec![
53-
(arg.span().shrink_to_lo(), String::from("{ ")),
54-
(arg.span().shrink_to_hi(), String::from(" }")),
55-
];
56-
err.multipart_suggestion(
57-
"if this generic argument was intended as a const parameter, \
58-
try surrounding it with braces:",
59-
suggestions,
60-
Applicability::MaybeIncorrect,
61-
);
62-
}
63+
GenericArg::Type(hir::Ty {
64+
kind: hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)),
65+
..
66+
}),
67+
GenericParamDefKind::Const,
68+
) => match path.res {
69+
Res::Err => {
70+
add_braces_suggestion(arg, &mut err);
71+
err.set_primary_message(
72+
"unresolved item provided when a constant was expected",
73+
)
74+
.emit();
75+
return;
76+
}
77+
Res::Def(DefKind::TyParam, src_def_id) => {
78+
if let Some(param_local_id) = param.def_id.as_local() {
79+
let param_hir_id = tcx.hir().local_def_id_to_hir_id(param_local_id);
80+
let param_name = tcx.hir().ty_param_name(param_hir_id);
81+
let param_type = tcx.type_of(param.def_id);
82+
if param_type.is_suggestable() {
83+
err.span_suggestion(
84+
tcx.def_span(src_def_id),
85+
"consider changing this type paramater to a `const`-generic",
86+
format!("const {}: {}", param_name, param_type),
87+
Applicability::MaybeIncorrect,
88+
);
89+
};
90+
}
91+
}
92+
_ => add_braces_suggestion(arg, &mut err),
93+
},
94+
(
95+
GenericArg::Type(hir::Ty { kind: hir::TyKind::Path(_), .. }),
96+
GenericParamDefKind::Const,
97+
) => add_braces_suggestion(arg, &mut err),
6398
(
6499
GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
65100
GenericParamDefKind::Const { .. },

src/test/ui/const-generics/const-param-shadowing.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0747]: type provided when a constant was expected
44
LL | fn test<const N: usize>() -> Foo<N> {
55
| ^
66
|
7-
help: if this generic argument was intended as a const parameter, try surrounding it with braces:
7+
help: if this generic argument was intended as a const parameter, surround it with braces
88
|
99
LL | fn test<const N: usize>() -> Foo<{ N }> {
1010
| ^ ^
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![crate_type="lib"]
2+
#![feature(min_const_generics)]
3+
#![allow(incomplete_features)]
4+
5+
struct A<const N: u8>;
6+
trait Foo {}
7+
impl Foo for A<N> {}
8+
//~^ ERROR cannot find type
9+
//~| unresolved item provided when a constant
10+
11+
struct B<const N: u8>;
12+
impl<N> Foo for B<N> {}
13+
//~^ ERROR type provided when a constant
14+
15+
struct C<const C: u8, const N: u8>;
16+
impl<const N: u8> Foo for C<N, T> {}
17+
//~^ ERROR cannot find type
18+
//~| unresolved item provided when a constant
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
error[E0412]: cannot find type `N` in this scope
2+
--> $DIR/diagnostics.rs:7:16
3+
|
4+
LL | struct A<const N: u8>;
5+
| ---------------------- similarly named struct `A` defined here
6+
LL | trait Foo {}
7+
LL | impl Foo for A<N> {}
8+
| ^ help: a struct with a similar name exists: `A`
9+
10+
error[E0412]: cannot find type `T` in this scope
11+
--> $DIR/diagnostics.rs:16:32
12+
|
13+
LL | struct A<const N: u8>;
14+
| ---------------------- similarly named struct `A` defined here
15+
...
16+
LL | impl<const N: u8> Foo for C<N, T> {}
17+
| ^ help: a struct with a similar name exists: `A`
18+
19+
error[E0747]: unresolved item provided when a constant was expected
20+
--> $DIR/diagnostics.rs:7:16
21+
|
22+
LL | impl Foo for A<N> {}
23+
| ^
24+
|
25+
help: if this generic argument was intended as a const parameter, surround it with braces
26+
|
27+
LL | impl Foo for A<{ N }> {}
28+
| ^ ^
29+
30+
error[E0747]: type provided when a constant was expected
31+
--> $DIR/diagnostics.rs:12:19
32+
|
33+
LL | impl<N> Foo for B<N> {}
34+
| - ^
35+
| |
36+
| help: consider changing this type paramater to a `const`-generic: `const N: u8`
37+
38+
error[E0747]: unresolved item provided when a constant was expected
39+
--> $DIR/diagnostics.rs:16:32
40+
|
41+
LL | impl<const N: u8> Foo for C<N, T> {}
42+
| ^
43+
|
44+
help: if this generic argument was intended as a const parameter, surround it with braces
45+
|
46+
LL | impl<const N: u8> Foo for C<N, { T }> {}
47+
| ^ ^
48+
49+
error: aborting due to 5 previous errors
50+
51+
Some errors have detailed explanations: E0412, E0747.
52+
For more information about an error, try `rustc --explain E0412`.

src/test/ui/const-generics/invalid-enum.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33

44
#[derive(PartialEq, Eq)]
55
enum CompileFlag {
6-
A,
7-
B,
6+
A,
7+
B,
88
}
99

1010
pub fn test_1<const CF: CompileFlag>() {}
1111
pub fn test_2<T, const CF: CompileFlag>(x: T) {}
1212
pub struct Example<const CF: CompileFlag, T=u32>{
13-
x: T,
13+
x: T,
1414
}
1515

1616
impl<const CF: CompileFlag, T> Example<CF, T> {
@@ -20,15 +20,15 @@ impl<const CF: CompileFlag, T> Example<CF, T> {
2020
pub fn main() {
2121
test_1::<CompileFlag::A>();
2222
//~^ ERROR: expected type, found variant
23-
//~| ERROR: type provided when a constant was expected
23+
//~| ERROR: unresolved item provided when a constant was expected
2424

2525
test_2::<_, CompileFlag::A>(0);
2626
//~^ ERROR: expected type, found variant
27-
//~| ERROR: type provided when a constant was expected
27+
//~| ERROR: unresolved item provided when a constant was expected
2828

2929
let _: Example<CompileFlag::A, _> = Example { x: 0 };
3030
//~^ ERROR: expected type, found variant
31-
//~| ERROR: type provided when a constant was expected
31+
//~| ERROR: unresolved item provided when a constant was expected
3232

3333
let _: Example<Example::ASSOC_FLAG, _> = Example { x: 0 };
3434
//~^ ERROR: type provided when a constant was expected

src/test/ui/const-generics/invalid-enum.stderr

+7-7
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ LL | let _: Example<CompileFlag::A, _> = Example { x: 0 };
2525
| not a type
2626
| help: try using the variant's enum: `CompileFlag`
2727

28-
error[E0747]: type provided when a constant was expected
28+
error[E0747]: unresolved item provided when a constant was expected
2929
--> $DIR/invalid-enum.rs:29:18
3030
|
3131
LL | let _: Example<CompileFlag::A, _> = Example { x: 0 };
3232
| ^^^^^^^^^^^^^^
3333
|
34-
help: if this generic argument was intended as a const parameter, try surrounding it with braces:
34+
help: if this generic argument was intended as a const parameter, surround it with braces
3535
|
3636
LL | let _: Example<{ CompileFlag::A }, _> = Example { x: 0 };
3737
| ^ ^
@@ -42,29 +42,29 @@ error[E0747]: type provided when a constant was expected
4242
LL | let _: Example<Example::ASSOC_FLAG, _> = Example { x: 0 };
4343
| ^^^^^^^^^^^^^^^^^^^
4444
|
45-
help: if this generic argument was intended as a const parameter, try surrounding it with braces:
45+
help: if this generic argument was intended as a const parameter, surround it with braces
4646
|
4747
LL | let _: Example<{ Example::ASSOC_FLAG }, _> = Example { x: 0 };
4848
| ^ ^
4949

50-
error[E0747]: type provided when a constant was expected
50+
error[E0747]: unresolved item provided when a constant was expected
5151
--> $DIR/invalid-enum.rs:21:12
5252
|
5353
LL | test_1::<CompileFlag::A>();
5454
| ^^^^^^^^^^^^^^
5555
|
56-
help: if this generic argument was intended as a const parameter, try surrounding it with braces:
56+
help: if this generic argument was intended as a const parameter, surround it with braces
5757
|
5858
LL | test_1::<{ CompileFlag::A }>();
5959
| ^ ^
6060

61-
error[E0747]: type provided when a constant was expected
61+
error[E0747]: unresolved item provided when a constant was expected
6262
--> $DIR/invalid-enum.rs:25:15
6363
|
6464
LL | test_2::<_, CompileFlag::A>(0);
6565
| ^^^^^^^^^^^^^^
6666
|
67-
help: if this generic argument was intended as a const parameter, try surrounding it with braces:
67+
help: if this generic argument was intended as a const parameter, surround it with braces
6868
|
6969
LL | test_2::<_, { CompileFlag::A }>(0);
7070
| ^ ^

0 commit comments

Comments
 (0)