about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2020-01-10 02:47:34 +0100
committerGitHub <noreply@github.com>2020-01-10 02:47:34 +0100
commit2307f0c4ea74d96ab64d27a2ef5efc6b75a02df5 (patch)
treef0372c1648a4b6544d306e986393f4071bfbbb64
parent3bfa28c3a8e09364207c4f5c437c8e73dac67716 (diff)
parent6e04cf062f605fbd70d728dcd364ad3eac0f822c (diff)
downloadrust-2307f0c4ea74d96ab64d27a2ef5efc6b75a02df5.tar.gz
rust-2307f0c4ea74d96ab64d27a2ef5efc6b75a02df5.zip
Rollup merge of #68071 - estebank:ice-67995, r=Centril
Extend support of `_` in type parameters

 - Account for `impl Trait<_>`.
 - Provide a reasonable `Span` for empty `Generics` in `impl`s.
 - Account for `fn foo<_>(_: _) {}` to suggest `fn foo<T>(_: T) {}`.
 - Fix #67995. Follow up to #67597.
-rw-r--r--src/librustc_parse/parser/generics.rs2
-rw-r--r--src/librustc_parse/parser/item.rs6
-rw-r--r--src/librustc_typeck/astconv.rs2
-rw-r--r--src/librustc_typeck/collect.rs36
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_item.rs45
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_item.stderr280
6 files changed, 280 insertions, 91 deletions
diff --git a/src/librustc_parse/parser/generics.rs b/src/librustc_parse/parser/generics.rs
index 1b816e2b90d..075583711f5 100644
--- a/src/librustc_parse/parser/generics.rs
+++ b/src/librustc_parse/parser/generics.rs
@@ -156,7 +156,7 @@ impl<'a> Parser<'a> {
             self.expect_gt()?;
             (params, span_lo.to(self.prev_span))
         } else {
-            (vec![], self.prev_span.between(self.token.span))
+            (vec![], self.prev_span.shrink_to_hi())
         };
         Ok(ast::Generics {
             params,
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index b209e5a7826..c53f132ff3d 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -556,7 +556,11 @@ impl<'a> Parser<'a> {
         let mut generics = if self.choose_generics_over_qpath() {
             self.parse_generics()?
         } else {
-            Generics::default()
+            let mut generics = Generics::default();
+            // impl A for B {}
+            //    /\ this is where `generics.span` should point when there are no type params.
+            generics.span = self.prev_span.shrink_to_hi();
+            generics
         };
 
         let constness = if self.eat_keyword(kw::Const) {
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 0233b68a7ce..7c7480339a5 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -2803,7 +2803,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             // allowed. `allow_ty_infer` gates this behavior.
             crate::collect::placeholder_type_error(
                 tcx,
-                ident_span.unwrap_or(DUMMY_SP),
+                ident_span.map(|sp| sp.shrink_to_hi()).unwrap_or(DUMMY_SP),
                 generic_params,
                 visitor.0,
                 ident_span.is_some(),
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 3ec09e5f19a..3bb06d76349 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -127,7 +127,7 @@ struct CollectItemTypesVisitor<'tcx> {
 /// all already existing generic type parameters to avoid suggesting a name that is already in use.
 crate fn placeholder_type_error(
     tcx: TyCtxt<'tcx>,
-    ident_span: Span,
+    span: Span,
     generics: &[hir::GenericParam<'_>],
     placeholder_types: Vec<Span>,
     suggest: bool,
@@ -153,7 +153,14 @@ crate fn placeholder_type_error(
     let mut sugg: Vec<_> =
         placeholder_types.iter().map(|sp| (*sp, type_name.to_string())).collect();
     if generics.is_empty() {
-        sugg.push((ident_span.shrink_to_hi(), format!("<{}>", type_name)));
+        sugg.push((span, format!("<{}>", type_name)));
+    } else if let Some(arg) = generics.iter().find(|arg| match arg.name {
+        hir::ParamName::Plain(Ident { name: kw::Underscore, .. }) => true,
+        _ => false,
+    }) {
+        // Account for `_` already present in cases like `struct S<_>(_);` and suggest
+        // `struct S<T>(T);` instead of `struct S<_, T>(T);`.
+        sugg.push((arg.span, format!("{}", type_name)));
     } else {
         sugg.push((
             generics.iter().last().unwrap().span.shrink_to_hi(),
@@ -175,8 +182,12 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir
     let (generics, suggest) = match &item.kind {
         hir::ItemKind::Union(_, generics)
         | hir::ItemKind::Enum(_, generics)
-        | hir::ItemKind::Struct(_, generics) => (&generics.params[..], true),
-        hir::ItemKind::TyAlias(_, generics) => (&generics.params[..], false),
+        | hir::ItemKind::TraitAlias(generics, _)
+        | hir::ItemKind::Trait(_, _, generics, ..)
+        | hir::ItemKind::Impl(_, _, _, generics, ..)
+        | hir::ItemKind::Struct(_, generics) => (generics, true),
+        hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. })
+        | hir::ItemKind::TyAlias(_, generics) => (generics, false),
         // `static`, `fn` and `const` are handled elsewhere to suggest appropriate type.
         _ => return,
     };
@@ -184,7 +195,7 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir
     let mut visitor = PlaceholderHirTyCollector::default();
     visitor.visit_item(item);
 
-    placeholder_type_error(tcx, item.ident.span, generics, visitor.0, suggest);
+    placeholder_type_error(tcx, generics.span, &generics.params[..], visitor.0, suggest);
 }
 
 impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
@@ -1798,10 +1809,19 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
 /// Whether `ty` is a type with `_` placeholders that can be infered. Used in diagnostics only to
 /// use inference to provide suggestions for the appropriate type if possible.
 fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
+    use hir::TyKind::*;
     match &ty.kind {
-        hir::TyKind::Infer => true,
-        hir::TyKind::Slice(ty) | hir::TyKind::Array(ty, _) => is_suggestable_infer_ty(ty),
-        hir::TyKind::Tup(tys) => tys.iter().any(|ty| is_suggestable_infer_ty(ty)),
+        Infer => true,
+        Slice(ty) | Array(ty, _) => is_suggestable_infer_ty(ty),
+        Tup(tys) => tys.iter().any(is_suggestable_infer_ty),
+        Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
+        Def(_, generic_args) => generic_args
+            .iter()
+            .filter_map(|arg| match arg {
+                hir::GenericArg::Type(ty) => Some(ty),
+                _ => None,
+            })
+            .any(is_suggestable_infer_ty),
         _ => false,
     }
 }
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs
index 5b0ca2f347e..adecbd7e5b4 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item.rs
+++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs
@@ -1,3 +1,4 @@
+#![feature(type_alias_impl_trait)] // Needed for single test `type Y = impl Trait<_>`
 // This test checks that it is not possible to enable global type
 // inference by using the `_` type placeholder.
 
@@ -42,6 +43,16 @@ impl Test9 {
     //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
 }
 
+fn test11(x: &usize) -> &_ {
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    &x
+}
+
+unsafe fn test12(x: *const usize) -> *const *const _ {
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    &x
+}
+
 impl Clone for Test9 {
     fn clone(&self) -> _ { Test9 }
     //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
@@ -131,3 +142,37 @@ trait T {
     fn assoc_fn_test3() -> _;
     //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
 }
+
+struct BadStruct<_>(_);
+//~^ ERROR expected identifier, found reserved identifier `_`
+//~| ERROR the type placeholder `_` is not allowed within types on item signatures
+trait BadTrait<_> {}
+//~^ ERROR expected identifier, found reserved identifier `_`
+impl BadTrait<_> for BadStruct<_> {}
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+fn impl_trait() -> impl BadTrait<_> {
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+    unimplemented!()
+}
+
+struct BadStruct1<_, _>(_);
+//~^ ERROR expected identifier, found reserved identifier `_`
+//~| ERROR expected identifier, found reserved identifier `_`
+//~| ERROR the name `_` is already used
+//~| ERROR the type placeholder `_` is not allowed within types on item signatures
+struct BadStruct2<_, T>(_, T);
+//~^ ERROR expected identifier, found reserved identifier `_`
+//~| ERROR the type placeholder `_` is not allowed within types on item signatures
+
+type X = Box<_>;
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+
+struct Struct;
+trait Trait<T> {}
+impl Trait<usize> for Struct {}
+type Y = impl Trait<_>;
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
+fn foo() -> Y {
+    Struct
+}
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr
index 9fe7af4c822..05326a3e07a 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr
+++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr
@@ -1,5 +1,43 @@
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/typeck_type_placeholder_item.rs:146:18
+   |
+LL | struct BadStruct<_>(_);
+   |                  ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/typeck_type_placeholder_item.rs:149:16
+   |
+LL | trait BadTrait<_> {}
+   |                ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/typeck_type_placeholder_item.rs:159:19
+   |
+LL | struct BadStruct1<_, _>(_);
+   |                   ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/typeck_type_placeholder_item.rs:159:22
+   |
+LL | struct BadStruct1<_, _>(_);
+   |                      ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/typeck_type_placeholder_item.rs:164:19
+   |
+LL | struct BadStruct2<_, T>(_, T);
+   |                   ^ expected identifier, found reserved identifier
+
+error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters
+  --> $DIR/typeck_type_placeholder_item.rs:159:22
+   |
+LL | struct BadStruct1<_, _>(_);
+   |                   -  ^ already used
+   |                   |
+   |                   first use of `_`
+
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:4:14
+  --> $DIR/typeck_type_placeholder_item.rs:5:14
    |
 LL | fn test() -> _ { 5 }
    |              ^
@@ -8,7 +46,7 @@ LL | fn test() -> _ { 5 }
    |              help: replace with the correct return type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:7:16
+  --> $DIR/typeck_type_placeholder_item.rs:8:16
    |
 LL | fn test2() -> (_, _) { (5, 5) }
    |               -^--^-
@@ -18,7 +56,7 @@ LL | fn test2() -> (_, _) { (5, 5) }
    |               help: replace with the correct return type: `(i32, i32)`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:10:15
+  --> $DIR/typeck_type_placeholder_item.rs:11:15
    |
 LL | static TEST3: _ = "test";
    |               ^
@@ -27,7 +65,7 @@ LL | static TEST3: _ = "test";
    |               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:13:15
+  --> $DIR/typeck_type_placeholder_item.rs:14:15
    |
 LL | static TEST4: _ = 145;
    |               ^
@@ -36,13 +74,13 @@ LL | static TEST4: _ = 145;
    |               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:16:15
+  --> $DIR/typeck_type_placeholder_item.rs:17:15
    |
 LL | static TEST5: (_, _) = (1, 2);
    |               ^^^^^^ not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:19:13
+  --> $DIR/typeck_type_placeholder_item.rs:20:13
    |
 LL | fn test6(_: _) { }
    |             ^ not allowed in type signatures
@@ -53,7 +91,7 @@ LL | fn test6<T>(_: T) { }
    |         ^^^    ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:22:18
+  --> $DIR/typeck_type_placeholder_item.rs:23:18
    |
 LL | fn test6_b<T>(_: _, _: T) { }
    |                  ^ not allowed in type signatures
@@ -64,7 +102,7 @@ LL | fn test6_b<T, K>(_: K, _: T) { }
    |             ^^^     ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:25:30
+  --> $DIR/typeck_type_placeholder_item.rs:26:30
    |
 LL | fn test6_c<T, K, L, A, B>(_: _, _: (T, K, L, A, B)) { }
    |                              ^ not allowed in type signatures
@@ -75,7 +113,7 @@ LL | fn test6_c<T, K, L, A, B, C>(_: C, _: (T, K, L, A, B)) { }
    |                         ^^^     ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:28:13
+  --> $DIR/typeck_type_placeholder_item.rs:29:13
    |
 LL | fn test7(x: _) { let _x: usize = x; }
    |             ^ not allowed in type signatures
@@ -86,13 +124,13 @@ LL | fn test7<T>(x: T) { let _x: usize = x; }
    |         ^^^    ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:31:22
+  --> $DIR/typeck_type_placeholder_item.rs:32:22
    |
 LL | fn test8(_f: fn() -> _) { }
    |                      ^ not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:31:22
+  --> $DIR/typeck_type_placeholder_item.rs:32:22
    |
 LL | fn test8(_f: fn() -> _) { }
    |                      ^ not allowed in type signatures
@@ -103,7 +141,25 @@ LL | fn test8<T>(_f: fn() -> T) { }
    |         ^^^             ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:54:8
+  --> $DIR/typeck_type_placeholder_item.rs:46:26
+   |
+LL | fn test11(x: &usize) -> &_ {
+   |                         -^
+   |                         ||
+   |                         |not allowed in type signatures
+   |                         help: replace with the correct return type: `&&usize`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:51:52
+   |
+LL | unsafe fn test12(x: *const usize) -> *const *const _ {
+   |                                      --------------^
+   |                                      |             |
+   |                                      |             not allowed in type signatures
+   |                                      help: replace with the correct return type: `*const *const usize`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:65:8
    |
 LL |     a: _,
    |        ^ not allowed in type signatures
@@ -122,7 +178,7 @@ LL |     b: (T, T),
    |
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:60:21
+  --> $DIR/typeck_type_placeholder_item.rs:71:21
    |
 LL |     fn fn_test() -> _ { 5 }
    |                     ^
@@ -131,7 +187,7 @@ LL |     fn fn_test() -> _ { 5 }
    |                     help: replace with the correct return type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:63:23
+  --> $DIR/typeck_type_placeholder_item.rs:74:23
    |
 LL |     fn fn_test2() -> (_, _) { (5, 5) }
    |                      -^--^-
@@ -141,7 +197,7 @@ LL |     fn fn_test2() -> (_, _) { (5, 5) }
    |                      help: replace with the correct return type: `(i32, i32)`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:66:22
+  --> $DIR/typeck_type_placeholder_item.rs:77:22
    |
 LL |     static FN_TEST3: _ = "test";
    |                      ^
@@ -150,7 +206,7 @@ LL |     static FN_TEST3: _ = "test";
    |                      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:69:22
+  --> $DIR/typeck_type_placeholder_item.rs:80:22
    |
 LL |     static FN_TEST4: _ = 145;
    |                      ^
@@ -159,13 +215,13 @@ LL |     static FN_TEST4: _ = 145;
    |                      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:72:22
+  --> $DIR/typeck_type_placeholder_item.rs:83:22
    |
 LL |     static FN_TEST5: (_, _) = (1, 2);
    |                      ^^^^^^ not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:75:20
+  --> $DIR/typeck_type_placeholder_item.rs:86:20
    |
 LL |     fn fn_test6(_: _) { }
    |                    ^ not allowed in type signatures
@@ -176,7 +232,7 @@ LL |     fn fn_test6<T>(_: T) { }
    |                ^^^    ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:78:20
+  --> $DIR/typeck_type_placeholder_item.rs:89:20
    |
 LL |     fn fn_test7(x: _) { let _x: usize = x; }
    |                    ^ not allowed in type signatures
@@ -187,13 +243,13 @@ LL |     fn fn_test7<T>(x: T) { let _x: usize = x; }
    |                ^^^    ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:81:29
+  --> $DIR/typeck_type_placeholder_item.rs:92:29
    |
 LL |     fn fn_test8(_f: fn() -> _) { }
    |                             ^ not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:81:29
+  --> $DIR/typeck_type_placeholder_item.rs:92:29
    |
 LL |     fn fn_test8(_f: fn() -> _) { }
    |                             ^ not allowed in type signatures
@@ -204,7 +260,7 @@ LL |     fn fn_test8<T>(_f: fn() -> T) { }
    |                ^^^             ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:104:12
+  --> $DIR/typeck_type_placeholder_item.rs:115:12
    |
 LL |         a: _,
    |            ^ not allowed in type signatures
@@ -223,13 +279,13 @@ LL |         b: (T, T),
    |
 
 error[E0282]: type annotations needed
-  --> $DIR/typeck_type_placeholder_item.rs:109:27
+  --> $DIR/typeck_type_placeholder_item.rs:120:27
    |
 LL |     fn fn_test11(_: _) -> (_, _) { panic!() }
    |                           ^^^^^^ cannot infer type
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:109:28
+  --> $DIR/typeck_type_placeholder_item.rs:120:28
    |
 LL |     fn fn_test11(_: _) -> (_, _) { panic!() }
    |                            ^  ^ not allowed in type signatures
@@ -237,7 +293,7 @@ LL |     fn fn_test11(_: _) -> (_, _) { panic!() }
    |                            not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:113:30
+  --> $DIR/typeck_type_placeholder_item.rs:124:30
    |
 LL |     fn fn_test12(x: i32) -> (_, _) { (x, x) }
    |                             -^--^-
@@ -247,7 +303,7 @@ LL |     fn fn_test12(x: i32) -> (_, _) { (x, x) }
    |                             help: replace with the correct return type: `(i32, i32)`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:116:33
+  --> $DIR/typeck_type_placeholder_item.rs:127:33
    |
 LL |     fn fn_test13(x: _) -> (i32, _) { (x, x) }
    |                           ------^-
@@ -256,7 +312,76 @@ LL |     fn fn_test13(x: _) -> (i32, _) { (x, x) }
    |                           help: replace with the correct return type: `(i32, i32)`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:121:31
+  --> $DIR/typeck_type_placeholder_item.rs:146:21
+   |
+LL | struct BadStruct<_>(_);
+   |                     ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | struct BadStruct<T>(T);
+   |                  ^  ^
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:151:15
+   |
+LL | impl BadTrait<_> for BadStruct<_> {}
+   |               ^                ^ not allowed in type signatures
+   |               |
+   |               not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | impl<T> BadTrait<T> for BadStruct<T> {}
+   |     ^^^          ^                ^
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:154:34
+   |
+LL | fn impl_trait() -> impl BadTrait<_> {
+   |                                  ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:159:25
+   |
+LL | struct BadStruct1<_, _>(_);
+   |                         ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | struct BadStruct1<T, _>(T);
+   |                   ^     ^
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:164:25
+   |
+LL | struct BadStruct2<_, T>(_, T);
+   |                         ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | struct BadStruct2<K, T>(K, T);
+   |                   ^     ^
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:168:14
+   |
+LL | type X = Box<_>;
+   |              ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:42:27
+   |
+LL |     fn test10(&self, _x : _) { }
+   |                           ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL |     fn test10<T>(&self, _x : T) { }
+   |              ^^^             ^
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:132:31
    |
 LL |     fn method_test1(&self, x: _);
    |                               ^ not allowed in type signatures
@@ -267,7 +392,7 @@ LL |     fn method_test1<T>(&self, x: T);
    |                    ^^^           ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:123:31
+  --> $DIR/typeck_type_placeholder_item.rs:134:31
    |
 LL |     fn method_test2(&self, x: _) -> _;
    |                               ^     ^ not allowed in type signatures
@@ -280,7 +405,7 @@ LL |     fn method_test2<T>(&self, x: T) -> T;
    |                    ^^^           ^     ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:125:31
+  --> $DIR/typeck_type_placeholder_item.rs:136:31
    |
 LL |     fn method_test3(&self) -> _;
    |                               ^ not allowed in type signatures
@@ -291,7 +416,7 @@ LL |     fn method_test3<T>(&self) -> T;
    |                    ^^^           ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:127:26
+  --> $DIR/typeck_type_placeholder_item.rs:138:26
    |
 LL |     fn assoc_fn_test1(x: _);
    |                          ^ not allowed in type signatures
@@ -302,7 +427,7 @@ LL |     fn assoc_fn_test1<T>(x: T);
    |                      ^^^    ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:129:26
+  --> $DIR/typeck_type_placeholder_item.rs:140:26
    |
 LL |     fn assoc_fn_test2(x: _) -> _;
    |                          ^     ^ not allowed in type signatures
@@ -315,7 +440,7 @@ LL |     fn assoc_fn_test2<T>(x: T) -> T;
    |                      ^^^    ^     ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:131:28
+  --> $DIR/typeck_type_placeholder_item.rs:142:28
    |
 LL |     fn assoc_fn_test3() -> _;
    |                            ^ not allowed in type signatures
@@ -326,47 +451,64 @@ LL |     fn assoc_fn_test3<T>() -> T;
    |                      ^^^      ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:38:24
+  --> $DIR/typeck_type_placeholder_item.rs:60:37
    |
-LL |     fn test9(&self) -> _ { () }
-   |                        ^
-   |                        |
-   |                        not allowed in type signatures
-   |                        help: replace with the correct return type: `()`
+LL |     fn clone_from(&mut self, other: _) { *self = Test9; }
+   |                                     ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL |     fn clone_from<T>(&mut self, other: T) { *self = Test9; }
+   |                  ^^^                   ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:41:27
+  --> $DIR/typeck_type_placeholder_item.rs:102:34
    |
-LL |     fn test10(&self, _x : _) { }
-   |                           ^ not allowed in type signatures
+LL |         fn fn_test10(&self, _x : _) { }
+   |                                  ^ not allowed in type signatures
    |
 help: use type parameters instead
    |
-LL |     fn test10<T>(&self, _x : T) { }
-   |              ^^^             ^
+LL |         fn fn_test10<T>(&self, _x : T) { }
+   |                     ^^^             ^
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:46:24
+  --> $DIR/typeck_type_placeholder_item.rs:110:41
    |
-LL |     fn clone(&self) -> _ { Test9 }
+LL |         fn clone_from(&mut self, other: _) { *self = FnTest9; }
+   |                                         ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL |         fn clone_from<T>(&mut self, other: T) { *self = FnTest9; }
+   |                      ^^^                   ^
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:174:21
+   |
+LL | type Y = impl Trait<_>;
+   |                     ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:39:24
+   |
+LL |     fn test9(&self) -> _ { () }
    |                        ^
    |                        |
    |                        not allowed in type signatures
-   |                        help: replace with the correct return type: `Test9`
+   |                        help: replace with the correct return type: `()`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:49:37
+  --> $DIR/typeck_type_placeholder_item.rs:57:24
    |
-LL |     fn clone_from(&mut self, other: _) { *self = Test9; }
-   |                                     ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |     fn clone_from<T>(&mut self, other: T) { *self = Test9; }
-   |                  ^^^                   ^
+LL |     fn clone(&self) -> _ { Test9 }
+   |                        ^
+   |                        |
+   |                        not allowed in type signatures
+   |                        help: replace with the correct return type: `Test9`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:88:31
+  --> $DIR/typeck_type_placeholder_item.rs:99:31
    |
 LL |         fn fn_test9(&self) -> _ { () }
    |                               ^
@@ -375,18 +517,7 @@ LL |         fn fn_test9(&self) -> _ { () }
    |                               help: replace with the correct return type: `()`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:91:34
-   |
-LL |         fn fn_test10(&self, _x : _) { }
-   |                                  ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |         fn fn_test10<T>(&self, _x : T) { }
-   |                     ^^^             ^
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:96:28
+  --> $DIR/typeck_type_placeholder_item.rs:107:28
    |
 LL |         fn clone(&self) -> _ { FnTest9 }
    |                            ^
@@ -394,18 +525,7 @@ LL |         fn clone(&self) -> _ { FnTest9 }
    |                            not allowed in type signatures
    |                            help: replace with the correct return type: `main::FnTest9`
 
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:99:41
-   |
-LL |         fn clone_from(&mut self, other: _) { *self = FnTest9; }
-   |                                         ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |         fn clone_from<T>(&mut self, other: T) { *self = FnTest9; }
-   |                      ^^^                   ^
-
-error: aborting due to 40 previous errors
+error: aborting due to 55 previous errors
 
-Some errors have detailed explanations: E0121, E0282.
+Some errors have detailed explanations: E0121, E0282, E0403.
 For more information about an error, try `rustc --explain E0121`.