about summary refs log tree commit diff
diff options
context:
space:
mode:
authorkadmin <julianknodt@gmail.com>2021-02-13 07:53:28 +0000
committerkadmin <julianknodt@gmail.com>2021-02-13 20:37:38 +0000
commitbe1ed00712ce0b884e1fc9779f25b1758e994d0b (patch)
treea4e45989e1dfc58aa8663eeb13d704c0079d7f25
parent3f5aee2d5241139d808f4fdece0026603489afd1 (diff)
downloadrust-be1ed00712ce0b884e1fc9779f25b1758e994d0b.tar.gz
rust-be1ed00712ce0b884e1fc9779f25b1758e994d0b.zip
Add additional type info to mismatch err
-rw-r--r--compiler/rustc_typeck/src/astconv/generics.rs51
-rw-r--r--src/test/ui/const-generics/diagnostics.rs13
-rw-r--r--src/test/ui/const-generics/diagnostics.stderr27
-rw-r--r--src/test/ui/const-generics/invalid-enum.stderr20
4 files changed, 79 insertions, 32 deletions
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, &param.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<const N: u8>;
+trait Foo {}
+impl Foo for A<N> {}
+//~^ ERROR type provided when a constant
+//~| ERROR cannot find type
+
+struct B<const N: u8>;
+impl<N> Foo for B<N> {}
+//~^ 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<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[E0747]: type provided when a constant was expected
+  --> $DIR/diagnostics.rs:7:16
+   |
+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: 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<CompileFlag::A, _> = 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::ASSOC_FLAG, _> = 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::<CompileFlag::A>();
    |            ^^^^^^^^^^^^^^
-   |
-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