about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorDenys Otrishko <shishugi@gmail.com>2019-07-18 18:41:59 +0300
committerDenys Otrishko <shishugi@gmail.com>2019-07-19 18:55:20 +0300
commit469b7a916164d48a78d4bd8a10257bfe3b4a1dbe (patch)
treea2ff62c25a630d0ecaddf93aee7f966460cf8e3a /src
parent527dce7137f7a3c7bf47d9a503abf25f88ea22de (diff)
downloadrust-469b7a916164d48a78d4bd8a10257bfe3b4a1dbe.tar.gz
rust-469b7a916164d48a78d4bd8a10257bfe3b4a1dbe.zip
rustc_typeck: improve diagnostics for _ const/static declarations
Diffstat (limited to 'src')
-rw-r--r--src/librustc_typeck/check/mod.rs31
-rw-r--r--src/librustc_typeck/collect.rs53
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_item.stderr20
3 files changed, 80 insertions, 24 deletions
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index bde6db78aef..21cd4b694ae 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -759,40 +759,40 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> {
 fn primary_body_of(
     tcx: TyCtxt<'_>,
     id: hir::HirId,
-) -> Option<(hir::BodyId, Option<&hir::FnHeader>, Option<&hir::FnDecl>)> {
+) -> Option<(hir::BodyId, Option<&hir::Ty>, Option<&hir::FnHeader>, Option<&hir::FnDecl>)> {
     match tcx.hir().get(id) {
         Node::Item(item) => {
             match item.node {
-                hir::ItemKind::Const(_, body) |
-                hir::ItemKind::Static(_, _, body) =>
-                    Some((body, None, None)),
+                hir::ItemKind::Const(ref ty, body) |
+                hir::ItemKind::Static(ref ty, _, body) =>
+                    Some((body, Some(ty), None, None)),
                 hir::ItemKind::Fn(ref decl, ref header, .., body) =>
-                    Some((body, Some(header), Some(decl))),
+                    Some((body, None, Some(header), Some(decl))),
                 _ =>
                     None,
             }
         }
         Node::TraitItem(item) => {
             match item.node {
-                hir::TraitItemKind::Const(_, Some(body)) =>
-                    Some((body, None, None)),
+                hir::TraitItemKind::Const(ref ty, Some(body)) =>
+                    Some((body, Some(ty), None, None)),
                 hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) =>
-                    Some((body, Some(&sig.header), Some(&sig.decl))),
+                    Some((body, None, Some(&sig.header), Some(&sig.decl))),
                 _ =>
                     None,
             }
         }
         Node::ImplItem(item) => {
             match item.node {
-                hir::ImplItemKind::Const(_, body) =>
-                    Some((body, None, None)),
+                hir::ImplItemKind::Const(ref ty, body) =>
+                    Some((body, Some(ty), None, None)),
                 hir::ImplItemKind::Method(ref sig, body) =>
-                    Some((body, Some(&sig.header), Some(&sig.decl))),
+                    Some((body, None, Some(&sig.header), Some(&sig.decl))),
                 _ =>
                     None,
             }
         }
-        Node::AnonConst(constant) => Some((constant.body, None, None)),
+        Node::AnonConst(constant) => Some((constant.body, None, None, None)),
         _ => None,
     }
 }
@@ -825,7 +825,7 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> {
     let span = tcx.hir().span(id);
 
     // Figure out what primary body this item has.
-    let (body_id, fn_header, fn_decl) = primary_body_of(tcx, id)
+    let (body_id, body_ty, fn_header, fn_decl) = primary_body_of(tcx, id)
         .unwrap_or_else(|| {
             span_bug!(span, "can't type-check body of {:?}", def_id);
         });
@@ -856,7 +856,10 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> {
             fcx
         } else {
             let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
-            let expected_type = tcx.type_of(def_id);
+            let expected_type = body_ty.and_then(|ty| match ty.node {
+                hir::TyKind::Infer => Some(AstConv::ast_ty_to_ty(&fcx, ty)),
+                _ => None
+            }).unwrap_or_else(|| tcx.type_of(def_id));
             let expected_type = fcx.normalize_associated_types_in(body.value.span, &expected_type);
             fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
 
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index a5457c45d37..053ef1f8f82 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1135,6 +1135,26 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
     checked_type_of(tcx, def_id, true).unwrap()
 }
 
+fn infer_placeholder_type(
+    tcx: TyCtxt<'_>,
+    def_id: DefId,
+    body_id: hir::BodyId,
+    span: Span,
+) -> Ty<'_> {
+    let ty = tcx.typeck_tables_of(def_id).node_type(body_id.hir_id);
+    let mut diag = bad_placeholder_type(tcx, span);
+    if ty != tcx.types.err {
+        diag.span_suggestion(
+            span,
+            "replace `_` with the correct type",
+            ty.to_string(),
+            Applicability::MaybeIncorrect,
+        );
+    }
+    diag.emit();
+    ty
+}
+
 /// Same as [`type_of`] but returns [`Option`] instead of failing.
 ///
 /// If you want to fail anyway, you can set the `fail` parameter to true, but in this case,
@@ -1160,7 +1180,16 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty<
                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
                 tcx.mk_fn_def(def_id, substs)
             }
-            TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
+            TraitItemKind::Const(ref ty, body_id)  => {
+                body_id.and_then(|body_id| {
+                    if let hir::TyKind::Infer = ty.node {
+                        Some(infer_placeholder_type(tcx, def_id, body_id, ty.span))
+                    } else {
+                        None
+                    }
+                }).unwrap_or_else(|| icx.to_ty(ty))
+            },
+            TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
             TraitItemKind::Type(_, None) => {
                 if !fail {
                     return None;
@@ -1174,7 +1203,13 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty<
                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
                 tcx.mk_fn_def(def_id, substs)
             }
-            ImplItemKind::Const(ref ty, _) => icx.to_ty(ty),
+            ImplItemKind::Const(ref ty, body_id) => {
+                if let hir::TyKind::Infer = ty.node {
+                    infer_placeholder_type(tcx, def_id, body_id, ty.span)
+                } else {
+                    icx.to_ty(ty)
+                }
+            },
             ImplItemKind::Existential(_) => {
                 if tcx
                     .impl_trait_ref(tcx.hir().get_parent_did(hir_id))
@@ -1199,10 +1234,16 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty<
 
         Node::Item(item) => {
             match item.node {
-                ItemKind::Static(ref t, ..)
-                | ItemKind::Const(ref t, _)
-                | ItemKind::Ty(ref t, _)
-                | ItemKind::Impl(.., ref t, _) => icx.to_ty(t),
+                ItemKind::Static(ref ty, .., body_id)
+                | ItemKind::Const(ref ty, body_id) => {
+                    if let hir::TyKind::Infer = ty.node {
+                        infer_placeholder_type(tcx, def_id, body_id, ty.span)
+                    } else {
+                        icx.to_ty(ty)
+                    }
+                },
+                ItemKind::Ty(ref ty, _)
+                | ItemKind::Impl(.., ref ty, _) => icx.to_ty(ty),
                 ItemKind::Fn(..) => {
                     let substs = InternalSubsts::identity_for_item(tcx, def_id);
                     tcx.mk_fn_def(def_id, substs)
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr
index ddaa5de4d3e..2b4d9966c3d 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr
+++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr
@@ -23,13 +23,19 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa
   --> $DIR/typeck_type_placeholder_item.rs:11:15
    |
 LL | static TEST3: _ = "test";
-   |               ^ not allowed in type signatures
+   |               ^
+   |               |
+   |               not allowed in type signatures
+   |               help: replace `_` with the correct type: `&'static str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:14:15
    |
 LL | static TEST4: _ = 145;
-   |               ^ not allowed in type signatures
+   |               ^
+   |               |
+   |               not allowed in type signatures
+   |               help: replace `_` with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:17:16
@@ -122,13 +128,19 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa
   --> $DIR/typeck_type_placeholder_item.rs:64:22
    |
 LL |     static FN_TEST3: _ = "test";
-   |                      ^ not allowed in type signatures
+   |                      ^
+   |                      |
+   |                      not allowed in type signatures
+   |                      help: replace `_` with the correct type: `&'static str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:67:22
    |
 LL |     static FN_TEST4: _ = 145;
-   |                      ^ not allowed in type signatures
+   |                      ^
+   |                      |
+   |                      not allowed in type signatures
+   |                      help: replace `_` with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:70:23