From be1ed00712ce0b884e1fc9779f25b1758e994d0b Mon Sep 17 00:00:00 2001 From: kadmin Date: Sat, 13 Feb 2021 07:53:28 +0000 Subject: [PATCH] Add additional type info to mismatch err --- compiler/rustc_typeck/src/astconv/generics.rs | 51 ++++++++++++++----- src/test/ui/const-generics/diagnostics.rs | 13 +++++ src/test/ui/const-generics/diagnostics.stderr | 27 ++++++++++ .../ui/const-generics/invalid-enum.stderr | 20 -------- 4 files changed, 79 insertions(+), 32 deletions(-) create mode 100644 src/test/ui/const-generics/diagnostics.rs create mode 100644 src/test/ui/const-generics/diagnostics.stderr diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 67e37ca8d8e..341f6fadba1 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -24,6 +24,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx: TyCtxt<'_>, arg: &GenericArg<'_>, param: &GenericParamDef, + // DefId of the function + //body_def_id: DefId, possible_ordering_error: bool, help: Option<&str>, ) { @@ -46,19 +48,44 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Specific suggestion set for diagnostics match (arg, ¶m.kind) { ( - GenericArg::Type(hir::Ty { kind: hir::TyKind::Path { .. }, .. }), - GenericParamDefKind::Const { .. }, + GenericArg::Type(hir::Ty { + kind: hir::TyKind::Path(rustc_hir::QPath::Resolved(_, 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, - ); + use rustc_hir::def::{DefKind, Res}; + match path.res { + Res::Err => {} + Res::Def(DefKind::TyParam, src_def_id) => (|| { + let param_hir_id = match param.def_id.as_local() { + Some(x) => tcx.hir().local_def_id_to_hir_id(x), + None => return, + }; + 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), + &format!("try changing to a const-generic parameter:"), + format!("const {}: {}", param_name, param_type), + Applicability::MaybeIncorrect, + ); + } + })(), + _ => { + 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::Array(_, len), .. }), diff --git a/src/test/ui/const-generics/diagnostics.rs b/src/test/ui/const-generics/diagnostics.rs new file mode 100644 index 00000000000..c90e3d0e0eb --- /dev/null +++ b/src/test/ui/const-generics/diagnostics.rs @@ -0,0 +1,13 @@ +#![crate_type="lib"] +#![feature(const_generics)] +#![allow(incomplete_features)] + +struct A; +trait Foo {} +impl Foo for A {} +//~^ ERROR type provided when a constant +//~| ERROR cannot find type + +struct B; +impl Foo for B {} +//~^ ERROR type provided when a constant diff --git a/src/test/ui/const-generics/diagnostics.stderr b/src/test/ui/const-generics/diagnostics.stderr new file mode 100644 index 00000000000..a66858a310c --- /dev/null +++ b/src/test/ui/const-generics/diagnostics.stderr @@ -0,0 +1,27 @@ +error[E0412]: cannot find type `N` in this scope + --> $DIR/diagnostics.rs:7:16 + | +LL | struct A; + | ---------------------- similarly named struct `A` defined here +LL | trait Foo {} +LL | impl Foo for A {} + | ^ help: a struct with a similar name exists: `A` + +error[E0747]: type provided when a constant was expected + --> $DIR/diagnostics.rs:7:16 + | +LL | impl Foo for A {} + | ^ + +error[E0747]: type provided when a constant was expected + --> $DIR/diagnostics.rs:12:19 + | +LL | impl Foo for B {} + | - ^ + | | + | help: try changing to a const-generic parameter:: `const N: u8` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0412, E0747. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/const-generics/invalid-enum.stderr b/src/test/ui/const-generics/invalid-enum.stderr index 7822fc072e3..c062fc9ac88 100644 --- a/src/test/ui/const-generics/invalid-enum.stderr +++ b/src/test/ui/const-generics/invalid-enum.stderr @@ -30,44 +30,24 @@ error[E0747]: type provided when a constant was expected | LL | let _: Example = Example { x: 0 }; | ^^^^^^^^^^^^^^ - | -help: if this generic argument was intended as a const parameter, try surrounding it with braces: - | -LL | let _: Example<{ CompileFlag::A }, _> = Example { x: 0 }; - | ^ ^ error[E0747]: type provided when a constant was expected --> $DIR/invalid-enum.rs:33:18 | LL | let _: Example = Example { x: 0 }; | ^^^^^^^^^^^^^^^^^^^ - | -help: if this generic argument was intended as a const parameter, try surrounding it with braces: - | -LL | let _: Example<{ Example::ASSOC_FLAG }, _> = Example { x: 0 }; - | ^ ^ error[E0747]: type provided when a constant was expected --> $DIR/invalid-enum.rs:21:12 | LL | test_1::(); | ^^^^^^^^^^^^^^ - | -help: if this generic argument was intended as a const parameter, try surrounding it with braces: - | -LL | test_1::<{ CompileFlag::A }>(); - | ^ ^ error[E0747]: type 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: - | -LL | test_2::<_, { CompileFlag::A }>(0); - | ^ ^ error: aborting due to 7 previous errors