Rollup merge of #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```
This commit is contained in:
commit
0c25d154bd
6 changed files with 134 additions and 29 deletions
|
@ -6,8 +6,9 @@ use crate::astconv::{
|
|||
use crate::errors::AssocTypeBindingNotAllowed;
|
||||
use crate::structured_errors::{StructuredDiagnostic, WrongNumberOfGenericArgs};
|
||||
use rustc_ast::ast::ParamKindOrd;
|
||||
use rustc_errors::{struct_span_err, Applicability, ErrorReported};
|
||||
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::GenericArg;
|
||||
use rustc_middle::ty::{
|
||||
|
@ -43,23 +44,57 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
}
|
||||
}
|
||||
|
||||
let add_braces_suggestion = |arg: &GenericArg<'_>, err: &mut DiagnosticBuilder<'_>| {
|
||||
let suggestions = vec![
|
||||
(arg.span().shrink_to_lo(), String::from("{ ")),
|
||||
(arg.span().shrink_to_hi(), String::from(" }")),
|
||||
];
|
||||
err.multipart_suggestion(
|
||||
"if this generic argument was intended as a const parameter, \
|
||||
surround it with braces",
|
||||
suggestions,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
};
|
||||
|
||||
// Specific suggestion set for diagnostics
|
||||
match (arg, ¶m.kind) {
|
||||
(
|
||||
GenericArg::Type(hir::Ty { kind: hir::TyKind::Path { .. }, .. }),
|
||||
GenericParamDefKind::Const { .. },
|
||||
) => {
|
||||
let suggestions = vec![
|
||||
(arg.span().shrink_to_lo(), String::from("{ ")),
|
||||
(arg.span().shrink_to_hi(), String::from(" }")),
|
||||
];
|
||||
err.multipart_suggestion(
|
||||
"if this generic argument was intended as a const parameter, \
|
||||
try surrounding it with braces:",
|
||||
suggestions,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
GenericArg::Type(hir::Ty {
|
||||
kind: hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)),
|
||||
..
|
||||
}),
|
||||
GenericParamDefKind::Const,
|
||||
) => match path.res {
|
||||
Res::Err => {
|
||||
add_braces_suggestion(arg, &mut err);
|
||||
err.set_primary_message(
|
||||
"unresolved item provided when a constant was expected",
|
||||
)
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
Res::Def(DefKind::TyParam, src_def_id) => {
|
||||
if let Some(param_local_id) = param.def_id.as_local() {
|
||||
let param_hir_id = tcx.hir().local_def_id_to_hir_id(param_local_id);
|
||||
let param_name = tcx.hir().ty_param_name(param_hir_id);
|
||||
let param_type = tcx.type_of(param.def_id);
|
||||
if param_type.is_suggestable() {
|
||||
err.span_suggestion(
|
||||
tcx.def_span(src_def_id),
|
||||
"consider changing this type paramater to a `const`-generic",
|
||||
format!("const {}: {}", param_name, param_type),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
_ => add_braces_suggestion(arg, &mut err),
|
||||
},
|
||||
(
|
||||
GenericArg::Type(hir::Ty { kind: hir::TyKind::Path(_), .. }),
|
||||
GenericParamDefKind::Const,
|
||||
) => add_braces_suggestion(arg, &mut err),
|
||||
(
|
||||
GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
|
||||
GenericParamDefKind::Const { .. },
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0747]: type provided when a constant was expected
|
|||
LL | fn test<const N: usize>() -> Foo<N> {
|
||||
| ^
|
||||
|
|
||||
help: if this generic argument was intended as a const parameter, try surrounding it with braces:
|
||||
help: if this generic argument was intended as a const parameter, surround it with braces
|
||||
|
|
||||
LL | fn test<const N: usize>() -> Foo<{ N }> {
|
||||
| ^ ^
|
||||
|
|
18
src/test/ui/const-generics/diagnostics.rs
Normal file
18
src/test/ui/const-generics/diagnostics.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
#![crate_type="lib"]
|
||||
#![feature(min_const_generics)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
struct A<const N: u8>;
|
||||
trait Foo {}
|
||||
impl Foo for A<N> {}
|
||||
//~^ ERROR cannot find type
|
||||
//~| unresolved item provided when a constant
|
||||
|
||||
struct B<const N: u8>;
|
||||
impl<N> Foo for B<N> {}
|
||||
//~^ ERROR type provided when a constant
|
||||
|
||||
struct C<const C: u8, const N: u8>;
|
||||
impl<const N: u8> Foo for C<N, T> {}
|
||||
//~^ ERROR cannot find type
|
||||
//~| unresolved item provided when a constant
|
52
src/test/ui/const-generics/diagnostics.stderr
Normal file
52
src/test/ui/const-generics/diagnostics.stderr
Normal file
|
@ -0,0 +1,52 @@
|
|||
error[E0412]: cannot find type `N` in this scope
|
||||
--> $DIR/diagnostics.rs:7:16
|
||||
|
|
||||
LL | struct A<const N: u8>;
|
||||
| ---------------------- similarly named struct `A` defined here
|
||||
LL | trait Foo {}
|
||||
LL | impl Foo for A<N> {}
|
||||
| ^ help: a struct with a similar name exists: `A`
|
||||
|
||||
error[E0412]: cannot find type `T` in this scope
|
||||
--> $DIR/diagnostics.rs:16:32
|
||||
|
|
||||
LL | struct A<const N: u8>;
|
||||
| ---------------------- similarly named struct `A` defined here
|
||||
...
|
||||
LL | impl<const N: u8> Foo for C<N, T> {}
|
||||
| ^ help: a struct with a similar name exists: `A`
|
||||
|
||||
error[E0747]: unresolved item provided when a constant was expected
|
||||
--> $DIR/diagnostics.rs:7:16
|
||||
|
|
||||
LL | impl Foo for A<N> {}
|
||||
| ^
|
||||
|
|
||||
help: if this generic argument was intended as a const parameter, surround it with braces
|
||||
|
|
||||
LL | impl Foo for A<{ N }> {}
|
||||
| ^ ^
|
||||
|
||||
error[E0747]: type provided when a constant was expected
|
||||
--> $DIR/diagnostics.rs:12:19
|
||||
|
|
||||
LL | impl<N> Foo for B<N> {}
|
||||
| - ^
|
||||
| |
|
||||
| help: consider changing this type paramater to a `const`-generic: `const N: u8`
|
||||
|
||||
error[E0747]: unresolved item provided when a constant was expected
|
||||
--> $DIR/diagnostics.rs:16:32
|
||||
|
|
||||
LL | impl<const N: u8> Foo for C<N, T> {}
|
||||
| ^
|
||||
|
|
||||
help: if this generic argument was intended as a const parameter, surround it with braces
|
||||
|
|
||||
LL | impl<const N: u8> Foo for C<N, { T }> {}
|
||||
| ^ ^
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0412, E0747.
|
||||
For more information about an error, try `rustc --explain E0412`.
|
|
@ -3,14 +3,14 @@
|
|||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum CompileFlag {
|
||||
A,
|
||||
B,
|
||||
A,
|
||||
B,
|
||||
}
|
||||
|
||||
pub fn test_1<const CF: CompileFlag>() {}
|
||||
pub fn test_2<T, const CF: CompileFlag>(x: T) {}
|
||||
pub struct Example<const CF: CompileFlag, T=u32>{
|
||||
x: T,
|
||||
x: T,
|
||||
}
|
||||
|
||||
impl<const CF: CompileFlag, T> Example<CF, T> {
|
||||
|
@ -20,15 +20,15 @@ impl<const CF: CompileFlag, T> Example<CF, T> {
|
|||
pub fn main() {
|
||||
test_1::<CompileFlag::A>();
|
||||
//~^ ERROR: expected type, found variant
|
||||
//~| ERROR: type provided when a constant was expected
|
||||
//~| ERROR: unresolved item provided when a constant was expected
|
||||
|
||||
test_2::<_, CompileFlag::A>(0);
|
||||
//~^ ERROR: expected type, found variant
|
||||
//~| ERROR: type provided when a constant was expected
|
||||
//~| ERROR: unresolved item provided when a constant was expected
|
||||
|
||||
let _: Example<CompileFlag::A, _> = Example { x: 0 };
|
||||
//~^ ERROR: expected type, found variant
|
||||
//~| ERROR: type provided when a constant was expected
|
||||
//~| ERROR: unresolved item provided when a constant was expected
|
||||
|
||||
let _: Example<Example::ASSOC_FLAG, _> = Example { x: 0 };
|
||||
//~^ ERROR: type provided when a constant was expected
|
||||
|
|
|
@ -25,13 +25,13 @@ LL | let _: Example<CompileFlag::A, _> = Example { x: 0 };
|
|||
| not a type
|
||||
| help: try using the variant's enum: `CompileFlag`
|
||||
|
||||
error[E0747]: type provided when a constant was expected
|
||||
error[E0747]: unresolved item provided when a constant was expected
|
||||
--> $DIR/invalid-enum.rs:29:18
|
||||
|
|
||||
LL | let _: Example<CompileFlag::A, _> = Example { x: 0 };
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
help: if this generic argument was intended as a const parameter, try surrounding it with braces:
|
||||
help: if this generic argument was intended as a const parameter, surround it with braces
|
||||
|
|
||||
LL | let _: Example<{ CompileFlag::A }, _> = Example { x: 0 };
|
||||
| ^ ^
|
||||
|
@ -42,29 +42,29 @@ error[E0747]: type provided when a constant was expected
|
|||
LL | let _: Example<Example::ASSOC_FLAG, _> = Example { x: 0 };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: if this generic argument was intended as a const parameter, try surrounding it with braces:
|
||||
help: if this generic argument was intended as a const parameter, surround it with braces
|
||||
|
|
||||
LL | let _: Example<{ Example::ASSOC_FLAG }, _> = Example { x: 0 };
|
||||
| ^ ^
|
||||
|
||||
error[E0747]: type provided when a constant was expected
|
||||
error[E0747]: unresolved item provided when a constant was expected
|
||||
--> $DIR/invalid-enum.rs:21:12
|
||||
|
|
||||
LL | test_1::<CompileFlag::A>();
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
help: if this generic argument was intended as a const parameter, try surrounding it with braces:
|
||||
help: if this generic argument was intended as a const parameter, surround it with braces
|
||||
|
|
||||
LL | test_1::<{ CompileFlag::A }>();
|
||||
| ^ ^
|
||||
|
||||
error[E0747]: type provided when a constant was expected
|
||||
error[E0747]: unresolved item provided when a constant was expected
|
||||
--> $DIR/invalid-enum.rs:25:15
|
||||
|
|
||||
LL | test_2::<_, CompileFlag::A>(0);
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
help: if this generic argument was intended as a const parameter, try surrounding it with braces:
|
||||
help: if this generic argument was intended as a const parameter, surround it with braces
|
||||
|
|
||||
LL | test_2::<_, { CompileFlag::A }>(0);
|
||||
| ^ ^
|
||||
|
|
Loading…
Add table
Reference in a new issue