about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/collect/type_of.rs54
-rw-r--r--src/test/ui/suggestions/unnamable-types.rs33
-rw-r--r--src/test/ui/suggestions/unnamable-types.stderr66
3 files changed, 140 insertions, 13 deletions
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs
index 29a87b18a9e..38678cc76e0 100644
--- a/compiler/rustc_typeck/src/collect/type_of.rs
+++ b/compiler/rustc_typeck/src/collect/type_of.rs
@@ -749,6 +749,17 @@ fn infer_placeholder_type(
     span: Span,
     item_ident: Ident,
 ) -> Ty<'_> {
+    fn contains_anonymous(ty: Ty<'_>) -> bool {
+        for gen_arg in ty.walk() {
+            if let ty::subst::GenericArgKind::Type(inner_ty) = gen_arg.unpack() {
+                if let ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) = inner_ty.kind() {
+                    return true;
+                }
+            }
+        }
+        false
+    }
+
     let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id);
 
     // If this came from a free `const` or `static mut?` item,
@@ -760,24 +771,41 @@ fn infer_placeholder_type(
             // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
             // We are typeck and have the real type, so remove that and suggest the actual type.
             err.suggestions.clear();
-            err.span_suggestion(
-                span,
-                "provide a type for the item",
-                format!("{}: {}", item_ident, ty),
-                Applicability::MachineApplicable,
-            )
-            .emit_unless(ty.references_error());
+
+            // Suggesting unnameable types won't help.
+            if !contains_anonymous(ty) {
+                err.span_suggestion(
+                    span,
+                    "provide a type for the item",
+                    format!("{}: {}", item_ident, ty),
+                    Applicability::MachineApplicable,
+                );
+            } else {
+                err.span_note(
+                    tcx.hir().body(body_id).value.span,
+                    &format!("however, the inferred type `{}` cannot be named", ty.to_string()),
+                );
+            }
+
+            err.emit_unless(ty.references_error());
         }
         None => {
             let mut diag = bad_placeholder_type(tcx, vec![span]);
 
             if !ty.references_error() {
-                diag.span_suggestion(
-                    span,
-                    "replace with the correct type",
-                    ty.to_string(),
-                    Applicability::MaybeIncorrect,
-                );
+                if !contains_anonymous(ty) {
+                    diag.span_suggestion(
+                        span,
+                        "replace with the correct type",
+                        ty.to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
+                } else {
+                    diag.span_note(
+                        tcx.hir().body(body_id).value.span,
+                        &format!("however, the inferred type `{}` cannot be named", ty.to_string()),
+                    );
+                }
             }
 
             diag.emit();
diff --git a/src/test/ui/suggestions/unnamable-types.rs b/src/test/ui/suggestions/unnamable-types.rs
new file mode 100644
index 00000000000..ed70bcf5484
--- /dev/null
+++ b/src/test/ui/suggestions/unnamable-types.rs
@@ -0,0 +1,33 @@
+// Test that we do not suggest to add type annotations for unnamable types.
+
+#![crate_type="lib"]
+#![feature(generators)]
+
+const A = 5;
+//~^ ERROR: missing type for `const` item
+//~| HELP: provide a type for the item
+
+static B: _ = "abc";
+//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures
+//~| NOTE: not allowed in type signatures
+//~| HELP: replace with the correct type
+
+
+const C: _ = || 42;
+//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures
+//~| NOTE: not allowed in type signatures
+//~| NOTE: however, the inferred type
+
+struct S<T> { t: T }
+const D = S { t: || -> i32 { 42 } };
+//~^ ERROR: missing type for `const` item
+//~| NOTE: however, the inferred type
+
+fn foo() -> i32 { 42 }
+const E = S { t: foo };
+//~^ ERROR: missing type for `const` item
+//~| NOTE: however, the inferred type
+
+const F = || -> i32 { yield 0; return 1; };
+//~^ ERROR: missing type for `const` item
+//~| NOTE: however, the inferred type
diff --git a/src/test/ui/suggestions/unnamable-types.stderr b/src/test/ui/suggestions/unnamable-types.stderr
new file mode 100644
index 00000000000..8082707fd3c
--- /dev/null
+++ b/src/test/ui/suggestions/unnamable-types.stderr
@@ -0,0 +1,66 @@
+error: missing type for `const` item
+  --> $DIR/unnamable-types.rs:6:7
+   |
+LL | const A = 5;
+   |       ^ help: provide a type for the item: `A: i32`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/unnamable-types.rs:10:11
+   |
+LL | static B: _ = "abc";
+   |           ^
+   |           |
+   |           not allowed in type signatures
+   |           help: replace with the correct type: `&str`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/unnamable-types.rs:16:10
+   |
+LL | const C: _ = || 42;
+   |          ^ not allowed in type signatures
+   |
+note: however, the inferred type `[closure@$DIR/unnamable-types.rs:16:14: 16:19]` cannot be named
+  --> $DIR/unnamable-types.rs:16:14
+   |
+LL | const C: _ = || 42;
+   |              ^^^^^
+
+error: missing type for `const` item
+  --> $DIR/unnamable-types.rs:22:7
+   |
+LL | const D = S { t: || -> i32 { 42 } };
+   |       ^
+   |
+note: however, the inferred type `S<[closure@$DIR/unnamable-types.rs:22:18: 22:34]>` cannot be named
+  --> $DIR/unnamable-types.rs:22:11
+   |
+LL | const D = S { t: || -> i32 { 42 } };
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing type for `const` item
+  --> $DIR/unnamable-types.rs:27:7
+   |
+LL | const E = S { t: foo };
+   |       ^
+   |
+note: however, the inferred type `S<fn() -> i32 {foo}>` cannot be named
+  --> $DIR/unnamable-types.rs:27:11
+   |
+LL | const E = S { t: foo };
+   |           ^^^^^^^^^^^^
+
+error: missing type for `const` item
+  --> $DIR/unnamable-types.rs:31:7
+   |
+LL | const F = || -> i32 { yield 0; return 1; };
+   |       ^
+   |
+note: however, the inferred type `[generator@$DIR/unnamable-types.rs:31:11: 31:43 {i32, ()}]` cannot be named
+  --> $DIR/unnamable-types.rs:31:11
+   |
+LL | const F = || -> i32 { yield 0; return 1; };
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0121`.