From 8cb193a5cb694ba62c83fb63a804f22720a118cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 23 Dec 2019 14:16:34 -0800 Subject: [PATCH 1/8] Suggest type param when encountering `_` in fn defs When encountering `_` type placeholder in fn arguments and return type, suggest using generic type parameters. Expand what counts as an inferable return type to slice, array and tuples of `_`. --- src/librustc_typeck/astconv.rs | 83 +++++- src/librustc_typeck/check/mod.rs | 7 +- src/librustc_typeck/collect.rs | 53 +++- src/test/ui/error-codes/E0121.stderr | 2 +- src/test/ui/self/self-infer.stderr | 14 +- .../ui/typeck/typeck_type_placeholder_item.rs | 26 +- .../typeck_type_placeholder_item.stderr | 269 ++++++++++++++---- .../typeck_type_placeholder_item_help.stderr | 2 +- 8 files changed, 376 insertions(+), 80 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index f3ac159a3aa2a..6a681be6f3ef7 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -7,6 +7,7 @@ use crate::hir::def_id::DefId; use crate::hir::print; use crate::hir::ptr::P; use crate::hir::{self, ExprKind, GenericArg, GenericArgs, HirVec}; +use crate::hir::intravisit::{NestedVisitorMap, Visitor}; use crate::lint; use crate::middle::lang_items::SizedTraitLangItem; use crate::middle::resolve_lifetime as rl; @@ -66,6 +67,8 @@ pub trait AstConv<'tcx> { /// Returns the type to use when a type is omitted. fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>; + fn allow_ty_infer(&self) -> bool; + /// Returns the const to use when a const is omitted. fn ct_infer( &self, @@ -2593,7 +2596,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } hir::TyKind::BareFn(ref bf) => { require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span); - tcx.mk_fn_ptr(self.ty_of_fn(bf.unsafety, bf.abi, &bf.decl)) + tcx.mk_fn_ptr(self.ty_of_fn(bf.unsafety, bf.abi, &bf.decl, &[], None)) } hir::TyKind::TraitObject(ref bounds, ref lifetime) => { self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime) @@ -2758,14 +2761,55 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { unsafety: hir::Unsafety, abi: abi::Abi, decl: &hir::FnDecl<'_>, + generic_params: &[hir::GenericParam<'_>], + ident_span: Option, ) -> ty::PolyFnSig<'tcx> { debug!("ty_of_fn"); let tcx = self.tcx(); - let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None)); + // We proactively collect all the infered type params to emit a single error per fn def. + struct PlaceholderHirTyCollector(Vec); + impl<'v> Visitor<'v> for PlaceholderHirTyCollector { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> { + NestedVisitorMap::None + } + fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { + if let hir::TyKind::Infer = t.kind { + self.0.push(t.span); + } + hir::intravisit::walk_ty(self, t) + } + } + let mut placeholder_types = vec![]; + let mut output_placeholder_types = vec![]; + + let input_tys = decl.inputs.iter().map(|a| { + let mut visitor = PlaceholderHirTyCollector(vec![]); + visitor.visit_ty(&a); + if visitor.0.is_empty() || self.allow_ty_infer() { + self.ty_of_arg(a, None) + } else { + placeholder_types.extend(visitor.0); + tcx.types.err + } + }); let output_ty = match decl.output { - hir::Return(ref output) => self.ast_ty_to_ty(output), + hir::Return(ref output) => { + let mut visitor = PlaceholderHirTyCollector(vec![]); + visitor.visit_ty(output); + let is_infer = if let hir::TyKind::Infer = output.kind { + true + } else { + false + }; + if (is_infer || !visitor.0.is_empty()) && !self.allow_ty_infer() { + output_placeholder_types.extend(visitor.0); + tcx.types.err + } else { + self.ast_ty_to_ty(output) + } + } hir::DefaultReturn(..) => tcx.mk_unit(), }; @@ -2774,6 +2818,39 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let bare_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi)); + placeholder_types.extend(output_placeholder_types); + + if !placeholder_types.is_empty() { + let mut sugg = placeholder_types.iter().cloned() + .map(|sp| (sp, "T".to_owned())) + .collect::>(); + if let Some(span) = ident_span { + if generic_params.is_empty() { + sugg.push((span.shrink_to_hi(), "".to_string())); + } else { + sugg.push(( + generic_params.iter().last().unwrap().span.shrink_to_hi(), + ", T".to_string(), + )); + } + } + let mut err = struct_span_err!( + tcx.sess, + placeholder_types, + E0121, + "the type placeholder `_` is not allowed within types on item signatures", + ); + if ident_span.is_some() { + err.multipart_suggestion( + "use type parameters instead", + sugg, + Applicability::HasPlaceholders, + ); + } + err.emit(); + } + + // Find any late-bound regions declared in return type that do // not appear in the arguments. These are not well-formed. // diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c6c3ada49e312..d9beb8ee3bd87 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -963,7 +963,7 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> { let fcx = if let (Some(header), Some(decl)) = (fn_header, fn_decl) { let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() { let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); - AstConv::ty_of_fn(&fcx, header.unsafety, header.abi, decl) + AstConv::ty_of_fn(&fcx, header.unsafety, header.abi, decl, &[], None) } else { tcx.fn_sig(def_id) }; @@ -1069,6 +1069,7 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> { let ty = fcx.normalize_ty(span, ty); fcx.require_type_is_sized(ty, span, code); } + fcx.select_all_obligations_or_error(); if fn_decl.is_some() { @@ -2563,6 +2564,10 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { Some(self.next_region_var(v)) } + fn allow_ty_infer(&self) -> bool { + true + } + fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { if let Some(param) = param { if let GenericArgKind::Type(ty) = self.var_for_def(span, param).unpack() { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 9604a9ade929e..6ab30c4b7e7ee 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -195,6 +195,10 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { None } + fn allow_ty_infer(&self) -> bool { + false + } + fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { bad_placeholder_type(self.tcx(), span).emit(); @@ -1699,9 +1703,26 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } } +fn is_infer_ty(ty: &hir::Ty<'_>) -> bool { + match &ty.kind { + hir::TyKind::Infer => true, + hir::TyKind::Slice(ty) | hir::TyKind::Array(ty, _) => is_infer_ty(ty), + hir::TyKind::Tup(tys) + if !tys.is_empty() + && tys.iter().all(|ty| match ty.kind { + hir::TyKind::Infer => true, + _ => false, + }) => + { + true + } + _ => false, + } +} + pub fn get_infer_ret_ty(output: &'hir hir::FunctionRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> { if let hir::FunctionRetTy::Return(ref ty) = output { - if let hir::TyKind::Infer = ty.kind { + if is_infer_ty(ty) { return Some(&**ty); } } @@ -1719,10 +1740,12 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { match tcx.hir().get(hir_id) { TraitItem(hir::TraitItem { kind: TraitItemKind::Method(sig, TraitMethod::Provided(_)), + ident, + generics, .. }) - | ImplItem(hir::ImplItem { kind: ImplItemKind::Method(sig, _), .. }) - | Item(hir::Item { kind: ItemKind::Fn(sig, _, _), .. }) => { + | ImplItem(hir::ImplItem { kind: ImplItemKind::Method(sig, _), ident, generics, .. }) + | Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), ident, .. }) => { match get_infer_ret_ty(&sig.decl.output) { Some(ty) => { let fn_sig = tcx.typeck_tables_of(def_id).liberated_fn_sigs()[hir_id]; @@ -1731,7 +1754,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { if ret_ty != tcx.types.err { diag.span_suggestion( ty.span, - "replace `_` with the correct return type", + "replace this with the correct return type", ret_ty.to_string(), Applicability::MaybeIncorrect, ); @@ -1739,14 +1762,30 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { diag.emit(); ty::Binder::bind(fn_sig) } - None => AstConv::ty_of_fn(&icx, sig.header.unsafety, sig.header.abi, &sig.decl), + None => AstConv::ty_of_fn( + &icx, + sig.header.unsafety, + sig.header.abi, + &sig.decl, + &generics.params[..], + Some(ident.span), + ), } } TraitItem(hir::TraitItem { kind: TraitItemKind::Method(FnSig { header, decl }, _), + ident, + generics, .. - }) => AstConv::ty_of_fn(&icx, header.unsafety, header.abi, decl), + }) => AstConv::ty_of_fn( + &icx, + header.unsafety, + header.abi, + decl, + &generics.params[..], + Some(ident.span), + ), ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(ref fn_decl, _, _), .. }) => { let abi = tcx.hir().get_foreign_abi(hir_id); @@ -2351,7 +2390,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( } else { hir::Unsafety::Unsafe }; - let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), unsafety, abi, decl); + let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), unsafety, abi, decl, &[], None); // Feature gate SIMD types in FFI, since I am not sure that the // ABIs are handled at all correctly. -huonw diff --git a/src/test/ui/error-codes/E0121.stderr b/src/test/ui/error-codes/E0121.stderr index beb8941320bc2..5da9a4c080f90 100644 --- a/src/test/ui/error-codes/E0121.stderr +++ b/src/test/ui/error-codes/E0121.stderr @@ -5,7 +5,7 @@ LL | fn foo() -> _ { 5 } | ^ | | | not allowed in type signatures - | help: replace `_` with the correct return type: `i32` + | help: replace this with the correct return type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/E0121.rs:3:13 diff --git a/src/test/ui/self/self-infer.stderr b/src/test/ui/self/self-infer.stderr index f91cfe5eb621b..b064928d8a34f 100644 --- a/src/test/ui/self/self-infer.stderr +++ b/src/test/ui/self/self-infer.stderr @@ -2,13 +2,23 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa --> $DIR/self-infer.rs:4:16 | LL | fn f(self: _) {} - | ^ not allowed in type signatures + | ^ + | +help: use type parameters instead + | +LL | fn f(self: T) {} + | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/self-infer.rs:5:17 | LL | fn g(self: &_) {} - | ^ not allowed in type signatures + | ^ + | +help: use type parameters instead + | +LL | fn g(self: &T) {} + | ^^^ ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index 46a5b8580dc5b..03ee61486c6cf 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -6,7 +6,6 @@ fn test() -> _ { 5 } fn test2() -> (_, _) { (5, 5) } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures static TEST3: _ = "test"; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures @@ -59,7 +58,6 @@ pub fn main() { fn fn_test2() -> (_, _) { (5, 5) } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures static FN_TEST3: _ = "test"; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures @@ -106,4 +104,28 @@ pub fn main() { //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures } + fn fn_test11(_: _) -> (_, _) { panic!() } + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR type annotations needed + + fn fn_test12(x: i32) -> (_, _) { (x, x) } + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + + fn fn_test13(x: _) -> (i32, _) { (x, x) } + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures } + +trait T { + fn method_test1(&self, x: _); + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + fn method_test2(&self, x: _) -> _; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + fn method_test3(&self) -> _; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + fn assoc_fn_test1(x: _); + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + fn assoc_fn_test2(x: _) -> _; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + fn assoc_fn_test3() -> _; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +} \ No newline at end of file diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index 2b4d9966c3d0b..0edfa07a6569a 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -5,22 +5,19 @@ LL | fn test() -> _ { 5 } | ^ | | | not allowed in type signatures - | help: replace `_` with the correct return type: `i32` + | help: replace this 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:7:15 | LL | fn test2() -> (_, _) { (5, 5) } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:7:19 - | -LL | fn test2() -> (_, _) { (5, 5) } - | ^ not allowed in type signatures + | ^^^^^^ + | | + | not allowed in type signatures + | help: replace this 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:11:15 + --> $DIR/typeck_type_placeholder_item.rs:10:15 | LL | static TEST3: _ = "test"; | ^ @@ -29,7 +26,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:14:15 + --> $DIR/typeck_type_placeholder_item.rs:13:15 | LL | static TEST4: _ = 145; | ^ @@ -38,94 +35,106 @@ 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:17:16 + --> $DIR/typeck_type_placeholder_item.rs:16:16 | 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:17:19 + --> $DIR/typeck_type_placeholder_item.rs:16:19 | 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:21:13 + --> $DIR/typeck_type_placeholder_item.rs:20:13 | LL | fn test6(_: _) { } - | ^ not allowed in type signatures + | ^ + | +help: use type parameters instead + | +LL | fn test6(_: T) { } + | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:24:13 + --> $DIR/typeck_type_placeholder_item.rs:23:13 | LL | fn test7(x: _) { let _x: usize = x; } - | ^ not allowed in type signatures + | ^ + | +help: use type parameters instead + | +LL | fn test7(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:27:22 + --> $DIR/typeck_type_placeholder_item.rs:26:22 | LL | fn test8(_f: fn() -> _) { } - | ^ not allowed in type signatures + | ^ + | +help: use type parameters instead + | +LL | fn test8(_f: fn() -> T) { } + | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:49:8 + --> $DIR/typeck_type_placeholder_item.rs:48:8 | LL | a: _, | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:51:9 + --> $DIR/typeck_type_placeholder_item.rs:50:9 | LL | b: (_, _), | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:51:12 + --> $DIR/typeck_type_placeholder_item.rs:50:12 | LL | b: (_, _), | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:102:12 + --> $DIR/typeck_type_placeholder_item.rs:100:12 | LL | a: _, | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:104:13 + --> $DIR/typeck_type_placeholder_item.rs:102:13 | LL | b: (_, _), | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:104:16 + --> $DIR/typeck_type_placeholder_item.rs:102:16 | LL | b: (_, _), | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:57:21 + --> $DIR/typeck_type_placeholder_item.rs:56:21 | LL | fn fn_test() -> _ { 5 } | ^ | | | not allowed in type signatures - | 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:60:23 - | -LL | fn fn_test2() -> (_, _) { (5, 5) } - | ^ not allowed in type signatures + | help: replace this 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:60:26 + --> $DIR/typeck_type_placeholder_item.rs:59:22 | LL | fn fn_test2() -> (_, _) { (5, 5) } - | ^ not allowed in type signatures + | ^^^^^^ + | | + | not allowed in type signatures + | help: replace this 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:64:22 + --> $DIR/typeck_type_placeholder_item.rs:62:22 | LL | static FN_TEST3: _ = "test"; | ^ @@ -134,7 +143,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:67:22 + --> $DIR/typeck_type_placeholder_item.rs:65:22 | LL | static FN_TEST4: _ = 145; | ^ @@ -143,95 +152,229 @@ 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:70:23 + --> $DIR/typeck_type_placeholder_item.rs:68:23 | 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:70:26 + --> $DIR/typeck_type_placeholder_item.rs:68:26 | 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:74:20 + --> $DIR/typeck_type_placeholder_item.rs:72:20 | LL | fn fn_test6(_: _) { } - | ^ not allowed in type signatures + | ^ + | +help: use type parameters instead + | +LL | fn fn_test6(_: T) { } + | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:77:20 + --> $DIR/typeck_type_placeholder_item.rs:75:20 | LL | fn fn_test7(x: _) { let _x: usize = x; } - | ^ not allowed in type signatures + | ^ + | +help: use type parameters instead + | +LL | fn fn_test7(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:80:29 + --> $DIR/typeck_type_placeholder_item.rs:78:29 | LL | fn fn_test8(_f: fn() -> _) { } - | ^ not allowed in type signatures + | ^ + | +help: use type parameters instead + | +LL | fn fn_test8(_f: fn() -> T) { } + | ^^^ ^ + +error[E0282]: type annotations needed + --> $DIR/typeck_type_placeholder_item.rs:107: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:33:24 + --> $DIR/typeck_type_placeholder_item.rs:107:27 + | +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:111:29 + | +LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } + | ^^^^^^ + | | + | not allowed in type signatures + | help: replace this 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:114:21 + | +LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } + | ^ ^ + | +help: use type parameters instead + | +LL | fn fn_test13(x: T) -> (i32, T) { (x, x) } + | ^^^ ^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:119:31 + | +LL | fn method_test1(&self, x: _); + | ^ + | +help: use type parameters instead + | +LL | fn method_test1(&self, x: T); + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:121:31 + | +LL | fn method_test2(&self, x: _) -> _; + | ^ ^ + | +help: use type parameters instead + | +LL | fn method_test2(&self, x: T) -> T; + | ^^^ ^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:123:31 + | +LL | fn method_test3(&self) -> _; + | ^ + | +help: use type parameters instead + | +LL | fn method_test3(&self) -> T; + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:125:26 + | +LL | fn assoc_fn_test1(x: _); + | ^ + | +help: use type parameters instead + | +LL | fn assoc_fn_test1(x: T); + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:127:26 + | +LL | fn assoc_fn_test2(x: _) -> _; + | ^ ^ + | +help: use type parameters instead + | +LL | fn assoc_fn_test2(x: T) -> T; + | ^^^ ^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:129:28 + | +LL | fn assoc_fn_test3() -> _; + | ^ + | +help: use type parameters instead + | +LL | fn assoc_fn_test3() -> T; + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:32:24 | LL | fn test9(&self) -> _ { () } | ^ | | | not allowed in type signatures - | help: replace `_` with the correct return type: `()` + | help: replace this with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:36:27 + --> $DIR/typeck_type_placeholder_item.rs:35:27 | LL | fn test10(&self, _x : _) { } - | ^ not allowed in type signatures + | ^ + | +help: use type parameters instead + | +LL | fn test10(&self, _x : T) { } + | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:41:24 + --> $DIR/typeck_type_placeholder_item.rs:40:24 | LL | fn clone(&self) -> _ { Test9 } | ^ | | | not allowed in type signatures - | help: replace `_` with the correct return type: `Test9` + | help: replace this 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:44:37 + --> $DIR/typeck_type_placeholder_item.rs:43:37 | LL | fn clone_from(&mut self, other: _) { *self = Test9; } - | ^ not allowed in type signatures + | ^ + | +help: use type parameters instead + | +LL | fn clone_from(&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:86:31 + --> $DIR/typeck_type_placeholder_item.rs:84:31 | LL | fn fn_test9(&self) -> _ { () } | ^ | | | not allowed in type signatures - | help: replace `_` with the correct return type: `()` + | help: replace this with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:89:34 + --> $DIR/typeck_type_placeholder_item.rs:87:34 | LL | fn fn_test10(&self, _x : _) { } - | ^ not allowed in type signatures + | ^ + | +help: use type parameters instead + | +LL | fn fn_test10(&self, _x : T) { } + | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:94:28 + --> $DIR/typeck_type_placeholder_item.rs:92:28 | LL | fn clone(&self) -> _ { FnTest9 } | ^ | | | not allowed in type signatures - | help: replace `_` with the correct return type: `main::FnTest9` + | help: replace this 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:97:41 + --> $DIR/typeck_type_placeholder_item.rs:95:41 | LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } - | ^ not allowed in type signatures + | ^ + | +help: use type parameters instead + | +LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } + | ^^^ ^ -error: aborting due to 34 previous errors +error: aborting due to 42 previous errors -For more information about this error, try `rustc --explain E0121`. +Some errors have detailed explanations: E0121, E0282. +For more information about an error, try `rustc --explain E0121`. diff --git a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr index c5b9566290c11..ab002381b1f79 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr @@ -5,7 +5,7 @@ LL | fn test1() -> _ { Some(42) } | ^ | | | not allowed in type signatures - | help: replace `_` with the correct return type: `std::option::Option` + | help: replace this with the correct return type: `std::option::Option` error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item_help.rs:7:14 From 6c8b2dcb1944a1b693778b7d96a99aaad635bbd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 24 Dec 2019 13:18:09 -0800 Subject: [PATCH 2/8] Account for all item kinds when collecting and gateing `_` in item defs --- src/librustc_typeck/astconv.rs | 67 ++----- src/librustc_typeck/collect.rs | 96 +++++++++- src/test/ui/self/self-infer.stderr | 4 +- .../ui/typeck/typeck_type_placeholder_item.rs | 6 - .../typeck_type_placeholder_item.stderr | 176 +++++++++--------- 5 files changed, 199 insertions(+), 150 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 6a681be6f3ef7..7ce26696e606e 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -7,7 +7,7 @@ use crate::hir::def_id::DefId; use crate::hir::print; use crate::hir::ptr::P; use crate::hir::{self, ExprKind, GenericArg, GenericArgs, HirVec}; -use crate::hir::intravisit::{NestedVisitorMap, Visitor}; +use crate::hir::intravisit::Visitor; use crate::lint; use crate::middle::lang_items::SizedTraitLangItem; use crate::middle::resolve_lifetime as rl; @@ -16,6 +16,7 @@ use crate::require_c_abi_if_c_variadic; use crate::util::common::ErrorReported; use crate::util::nodemap::FxHashMap; use errors::{Applicability, DiagnosticId}; +use crate::collect::PlaceholderHirTyCollector; use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc::traits; use rustc::ty::subst::{self, InternalSubsts, Subst, SubstsRef}; @@ -2747,12 +2748,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option>) -> Ty<'tcx> { - match ty.kind { - hir::TyKind::Infer if expected_ty.is_some() => { - self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span); - expected_ty.unwrap() - } - _ => self.ast_ty_to_ty(ty), + if crate::collect::is_infer_ty(ty) && expected_ty.is_some() { + self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span); + expected_ty.unwrap() + } else { + self.ast_ty_to_ty(ty) } } @@ -2769,23 +2769,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.tcx(); // We proactively collect all the infered type params to emit a single error per fn def. - struct PlaceholderHirTyCollector(Vec); - impl<'v> Visitor<'v> for PlaceholderHirTyCollector { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> { - NestedVisitorMap::None - } - fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { - if let hir::TyKind::Infer = t.kind { - self.0.push(t.span); - } - hir::intravisit::walk_ty(self, t) - } - } let mut placeholder_types = vec![]; let mut output_placeholder_types = vec![]; let input_tys = decl.inputs.iter().map(|a| { - let mut visitor = PlaceholderHirTyCollector(vec![]); + let mut visitor = PlaceholderHirTyCollector::new(); visitor.visit_ty(&a); if visitor.0.is_empty() || self.allow_ty_infer() { self.ty_of_arg(a, None) @@ -2796,7 +2784,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }); let output_ty = match decl.output { hir::Return(ref output) => { - let mut visitor = PlaceholderHirTyCollector(vec![]); + let mut visitor = PlaceholderHirTyCollector::new(); visitor.visit_ty(output); let is_infer = if let hir::TyKind::Infer = output.kind { true @@ -2820,36 +2808,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { placeholder_types.extend(output_placeholder_types); - if !placeholder_types.is_empty() { - let mut sugg = placeholder_types.iter().cloned() - .map(|sp| (sp, "T".to_owned())) - .collect::>(); - if let Some(span) = ident_span { - if generic_params.is_empty() { - sugg.push((span.shrink_to_hi(), "".to_string())); - } else { - sugg.push(( - generic_params.iter().last().unwrap().span.shrink_to_hi(), - ", T".to_string(), - )); - } - } - let mut err = struct_span_err!( - tcx.sess, - placeholder_types, - E0121, - "the type placeholder `_` is not allowed within types on item signatures", - ); - if ident_span.is_some() { - err.multipart_suggestion( - "use type parameters instead", - sugg, - Applicability::HasPlaceholders, - ); - } - err.emit(); - } - + crate::collect::placeholder_type_error( + tcx, + ident_span.unwrap_or(DUMMY_SP), + generic_params, + placeholder_types, + ident_span.is_some(), + ); // Find any late-bound regions declared in return type that do // not appear in the arguments. These are not well-formed. diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 6ab30c4b7e7ee..440b894fcf7e5 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -102,10 +102,88 @@ pub struct ItemCtxt<'tcx> { /////////////////////////////////////////////////////////////////////////// +crate struct PlaceholderHirTyCollector(crate Vec); + +impl<'v> Visitor<'v> for PlaceholderHirTyCollector { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> { + NestedVisitorMap::None + } + fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { + if let hir::TyKind::Infer = t.kind { + self.0.push(t.span); + } + hir::intravisit::walk_ty(self, t) + } +} + +impl PlaceholderHirTyCollector { + pub fn new() -> PlaceholderHirTyCollector { + PlaceholderHirTyCollector(vec![]) + } +} + struct CollectItemTypesVisitor<'tcx> { tcx: TyCtxt<'tcx>, } +crate fn placeholder_type_error( + tcx: TyCtxt<'tcx>, + ident_span: Span, + generics: &[hir::GenericParam<'_>], + placeholder_types: Vec, + suggest: bool, +) { + if !placeholder_types.is_empty() { + let mut sugg: Vec<_> = placeholder_types.iter().map(|sp| (*sp, "T".to_string())).collect(); + if generics.is_empty() { + sugg.push((ident_span.shrink_to_hi(), "".to_string())); + } else { + sugg.push((generics.iter().last().unwrap().span.shrink_to_hi(), ", T".to_string())); + } + let mut err = struct_span_err!( + tcx.sess, + placeholder_types.clone(), + E0121, + "the type placeholder `_` is not allowed within types on item signatures", + ); + for span in &placeholder_types { + err.span_label(*span, "not allowed in type signatures"); + } + if suggest { + err.multipart_suggestion( + "use type parameters instead", + sugg, + Applicability::HasPlaceholders, + ); + } + err.emit(); + } +} + +fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { + let (generics, suggest) = match &item.kind { + hir::ItemKind::Union(_, generics) + | hir::ItemKind::Enum(_, generics) + | hir::ItemKind::Struct(_, generics) => (&generics.params[..], true), + hir::ItemKind::Static(ty, ..) => { + if let hir::TyKind::Infer = ty.kind { + return; // We handle it elsewhere to attempt to suggest an appropriate type. + } else { + (&[][..], false) + } + } + hir::ItemKind::TyAlias(_, generics) => (&generics.params[..], false), + // hir::ItemKind::Fn(..) | + // hir::ItemKind::Const(..) => {} // We handle these elsewhere to suggest appropriate type. + _ => return, + }; + + let mut visitor = PlaceholderHirTyCollector::new(); + visitor.visit_item(item); + + placeholder_type_error(tcx, item.ident.span, generics, visitor.0, suggest); +} + impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::OnlyBodies(&self.tcx.hir()) @@ -113,6 +191,7 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { convert_item(self.tcx, item.hir_id); + reject_placeholder_type_signatures_in_item(self.tcx, item); intravisit::walk_item(self, item); } @@ -200,8 +279,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { } fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { - bad_placeholder_type(self.tcx(), span).emit(); - + self.tcx().sess.delay_span_bug(span, "bad placeholder type, but no error was emitted"); self.tcx().types.err } @@ -1189,6 +1267,10 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { .and_then(|body_id| { if let hir::TyKind::Infer = ty.kind { Some(infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)) + } else if is_infer_ty(ty) { + // Infering this would cause a cycle error. + tcx.sess.delay_span_bug(ty.span, "`_` placeholder but no error emitted"); + Some(tcx.types.err) } else { None } @@ -1208,6 +1290,10 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { ImplItemKind::Const(ref ty, body_id) => { if let hir::TyKind::Infer = ty.kind { infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident) + } else if is_infer_ty(ty) { + // Infering this would cause a cycle error. + tcx.sess.delay_span_bug(ty.span, "`_` placeholder but no error emitted"); + tcx.types.err } else { icx.to_ty(ty) } @@ -1233,6 +1319,10 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { ItemKind::Static(ref ty, .., body_id) | ItemKind::Const(ref ty, body_id) => { if let hir::TyKind::Infer = ty.kind { infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident) + } else if is_infer_ty(ty) { + // Infering this would cause a cycle error. + tcx.sess.delay_span_bug(ty.span, "`_` placeholder but no error emitted"); + tcx.types.err } else { icx.to_ty(ty) } @@ -1703,7 +1793,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } } -fn is_infer_ty(ty: &hir::Ty<'_>) -> bool { +crate fn is_infer_ty(ty: &hir::Ty<'_>) -> bool { match &ty.kind { hir::TyKind::Infer => true, hir::TyKind::Slice(ty) | hir::TyKind::Array(ty, _) => is_infer_ty(ty), diff --git a/src/test/ui/self/self-infer.stderr b/src/test/ui/self/self-infer.stderr index b064928d8a34f..1475b212b56a6 100644 --- a/src/test/ui/self/self-infer.stderr +++ b/src/test/ui/self/self-infer.stderr @@ -2,7 +2,7 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa --> $DIR/self-infer.rs:4:16 | LL | fn f(self: _) {} - | ^ + | ^ not allowed in type signatures | help: use type parameters instead | @@ -13,7 +13,7 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa --> $DIR/self-infer.rs:5:17 | LL | fn g(self: &_) {} - | ^ + | ^ not allowed in type signatures | help: use type parameters instead | diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index 03ee61486c6cf..0ec5d80f2414f 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -15,7 +15,6 @@ static TEST4: _ = 145; static TEST5: (_, _) = (1, 2); //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures fn test6(_: _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures @@ -48,8 +47,6 @@ struct Test10 { a: _, //~^ ERROR the type placeholder `_` is not allowed within types on item signatures b: (_, _), - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures } pub fn main() { @@ -67,7 +64,6 @@ pub fn main() { static FN_TEST5: (_, _) = (1, 2); //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures fn fn_test6(_: _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures @@ -100,8 +96,6 @@ pub fn main() { a: _, //~^ ERROR the type placeholder `_` is not allowed within types on item signatures b: (_, _), - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures } fn fn_test11(_: _) -> (_, _) { panic!() } diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index 0edfa07a6569a..dbb014edd426c 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -38,19 +38,15 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa --> $DIR/typeck_type_placeholder_item.rs:16:16 | LL | static TEST5: (_, _) = (1, 2); - | ^ not allowed in type signatures + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:16:19 - | -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:20:13 + --> $DIR/typeck_type_placeholder_item.rs:19:13 | LL | fn test6(_: _) { } - | ^ + | ^ not allowed in type signatures | help: use type parameters instead | @@ -58,10 +54,10 @@ LL | fn test6(_: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:23:13 + --> $DIR/typeck_type_placeholder_item.rs:22:13 | LL | fn test7(x: _) { let _x: usize = x; } - | ^ + | ^ not allowed in type signatures | help: use type parameters instead | @@ -69,10 +65,10 @@ LL | fn test7(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:26:22 + --> $DIR/typeck_type_placeholder_item.rs:25:22 | LL | fn test8(_f: fn() -> _) { } - | ^ + | ^ not allowed in type signatures | help: use type parameters instead | @@ -80,43 +76,26 @@ LL | fn test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:48:8 + --> $DIR/typeck_type_placeholder_item.rs:47:8 | LL | a: _, | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:50:9 - | +LL | LL | b: (_, _), - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:50:12 + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures | -LL | b: (_, _), - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:100:12 - | -LL | a: _, - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:102:13 +help: use type parameters instead | -LL | b: (_, _), - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:102:16 +LL | struct Test10 { +LL | a: T, +LL | +LL | b: (T, T), | -LL | b: (_, _), - | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:56:21 + --> $DIR/typeck_type_placeholder_item.rs:53:21 | LL | fn fn_test() -> _ { 5 } | ^ @@ -125,7 +104,7 @@ LL | fn fn_test() -> _ { 5 } | help: replace this 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:59:22 + --> $DIR/typeck_type_placeholder_item.rs:56:22 | LL | fn fn_test2() -> (_, _) { (5, 5) } | ^^^^^^ @@ -134,7 +113,7 @@ LL | fn fn_test2() -> (_, _) { (5, 5) } | help: replace this 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:62:22 + --> $DIR/typeck_type_placeholder_item.rs:59:22 | LL | static FN_TEST3: _ = "test"; | ^ @@ -143,7 +122,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:65:22 + --> $DIR/typeck_type_placeholder_item.rs:62:22 | LL | static FN_TEST4: _ = 145; | ^ @@ -152,22 +131,18 @@ 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:68:23 - | -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:68:26 + --> $DIR/typeck_type_placeholder_item.rs:65:23 | LL | static FN_TEST5: (_, _) = (1, 2); - | ^ not allowed in type signatures + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:72:20 + --> $DIR/typeck_type_placeholder_item.rs:68:20 | LL | fn fn_test6(_: _) { } - | ^ + | ^ not allowed in type signatures | help: use type parameters instead | @@ -175,10 +150,10 @@ LL | fn fn_test6(_: T) { } | ^^^ ^ 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:71:20 | LL | fn fn_test7(x: _) { let _x: usize = x; } - | ^ + | ^ not allowed in type signatures | help: use type parameters instead | @@ -186,30 +161,49 @@ LL | fn fn_test7(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:78:29 + --> $DIR/typeck_type_placeholder_item.rs:74:29 | LL | fn fn_test8(_f: fn() -> _) { } - | ^ + | ^ not allowed in type signatures | help: use type parameters instead | LL | fn fn_test8(_f: fn() -> T) { } | ^^^ ^ +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:96:12 + | +LL | a: _, + | ^ not allowed in type signatures +LL | +LL | b: (_, _), + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + | +help: use type parameters instead + | +LL | struct FnTest10 { +LL | a: T, +LL | +LL | b: (T, T), + | + error[E0282]: type annotations needed - --> $DIR/typeck_type_placeholder_item.rs:107:27 + --> $DIR/typeck_type_placeholder_item.rs:101: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:107:27 + --> $DIR/typeck_type_placeholder_item.rs:101:27 | 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:111:29 + --> $DIR/typeck_type_placeholder_item.rs:105:29 | LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | ^^^^^^ @@ -218,10 +212,12 @@ LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | help: replace this 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:114:21 + --> $DIR/typeck_type_placeholder_item.rs:108:21 | LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } - | ^ ^ + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures | help: use type parameters instead | @@ -229,10 +225,10 @@ LL | fn fn_test13(x: T) -> (i32, T) { (x, x) } | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:119:31 + --> $DIR/typeck_type_placeholder_item.rs:113:31 | LL | fn method_test1(&self, x: _); - | ^ + | ^ not allowed in type signatures | help: use type parameters instead | @@ -240,10 +236,12 @@ LL | fn method_test1(&self, x: T); | ^^^ ^ 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:115:31 | LL | fn method_test2(&self, x: _) -> _; - | ^ ^ + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures | help: use type parameters instead | @@ -251,10 +249,10 @@ LL | fn method_test2(&self, x: T) -> 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:117:31 | LL | fn method_test3(&self) -> _; - | ^ + | ^ not allowed in type signatures | help: use type parameters instead | @@ -262,10 +260,10 @@ LL | fn method_test3(&self) -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:125:26 + --> $DIR/typeck_type_placeholder_item.rs:119:26 | LL | fn assoc_fn_test1(x: _); - | ^ + | ^ not allowed in type signatures | help: use type parameters instead | @@ -273,10 +271,12 @@ LL | fn assoc_fn_test1(x: 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:121:26 | LL | fn assoc_fn_test2(x: _) -> _; - | ^ ^ + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures | help: use type parameters instead | @@ -284,10 +284,10 @@ LL | fn assoc_fn_test2(x: T) -> T; | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:129:28 + --> $DIR/typeck_type_placeholder_item.rs:123:28 | LL | fn assoc_fn_test3() -> _; - | ^ + | ^ not allowed in type signatures | help: use type parameters instead | @@ -295,7 +295,7 @@ LL | fn assoc_fn_test3() -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:32:24 + --> $DIR/typeck_type_placeholder_item.rs:31:24 | LL | fn test9(&self) -> _ { () } | ^ @@ -304,10 +304,10 @@ LL | fn test9(&self) -> _ { () } | help: replace this with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:35:27 + --> $DIR/typeck_type_placeholder_item.rs:34:27 | LL | fn test10(&self, _x : _) { } - | ^ + | ^ not allowed in type signatures | help: use type parameters instead | @@ -315,7 +315,7 @@ LL | fn test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:40:24 + --> $DIR/typeck_type_placeholder_item.rs:39:24 | LL | fn clone(&self) -> _ { Test9 } | ^ @@ -324,10 +324,10 @@ LL | fn clone(&self) -> _ { Test9 } | help: replace this 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:43:37 + --> $DIR/typeck_type_placeholder_item.rs:42:37 | LL | fn clone_from(&mut self, other: _) { *self = Test9; } - | ^ + | ^ not allowed in type signatures | help: use type parameters instead | @@ -335,7 +335,7 @@ LL | fn clone_from(&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:84:31 + --> $DIR/typeck_type_placeholder_item.rs:80:31 | LL | fn fn_test9(&self) -> _ { () } | ^ @@ -344,10 +344,10 @@ LL | fn fn_test9(&self) -> _ { () } | help: replace this with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:87:34 + --> $DIR/typeck_type_placeholder_item.rs:83:34 | LL | fn fn_test10(&self, _x : _) { } - | ^ + | ^ not allowed in type signatures | help: use type parameters instead | @@ -355,7 +355,7 @@ LL | fn fn_test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:92:28 + --> $DIR/typeck_type_placeholder_item.rs:88:28 | LL | fn clone(&self) -> _ { FnTest9 } | ^ @@ -364,17 +364,17 @@ LL | fn clone(&self) -> _ { FnTest9 } | help: replace this 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:95:41 + --> $DIR/typeck_type_placeholder_item.rs:91:41 | LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } - | ^ + | ^ not allowed in type signatures | help: use type parameters instead | LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } | ^^^ ^ -error: aborting due to 42 previous errors +error: aborting due to 36 previous errors Some errors have detailed explanations: E0121, E0282. For more information about an error, try `rustc --explain E0121`. From fb52883690831a0bbb8b97d75eadc696dd2fd422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 24 Dec 2019 15:12:01 -0800 Subject: [PATCH 3/8] Account for existing type params when suggesting replacing `_` for a new one --- src/librustc_typeck/collect.rs | 25 +++++- .../ui/typeck/typeck_type_placeholder_item.rs | 6 ++ .../typeck_type_placeholder_item.stderr | 84 ++++++++++++------- 3 files changed, 81 insertions(+), 34 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 440b894fcf7e5..ccff01755e93a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -134,11 +134,30 @@ crate fn placeholder_type_error( suggest: bool, ) { if !placeholder_types.is_empty() { - let mut sugg: Vec<_> = placeholder_types.iter().map(|sp| (*sp, "T".to_string())).collect(); + let possible_names = ["T", "K", "L", "A", "B", "C"]; + let used_names = generics.iter().filter_map(|p| match p.name { + hir::ParamName::Plain(ident) => Some(ident.name), + _ => None, + }).collect::>(); + + let mut type_name = "ParamName"; + for name in &possible_names { + if !used_names.contains(&Symbol::intern(name)) { + type_name = name; + break; + } + } + + 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(), "".to_string())); + sugg.push((ident_span.shrink_to_hi(), format!("<{}>", type_name))); } else { - sugg.push((generics.iter().last().unwrap().span.shrink_to_hi(), ", T".to_string())); + sugg.push(( + generics.iter().last().unwrap().span.shrink_to_hi(), + format!(", {}", type_name), + )); } let mut err = struct_span_err!( tcx.sess, diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index 0ec5d80f2414f..d1fb51e0fe244 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -19,6 +19,12 @@ static TEST5: (_, _) = (1, 2); fn test6(_: _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +fn test6_b(_: _, _: T) { } +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures + +fn test6_c(_: _, _: (T, K, L, A, B)) { } +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures + fn test7(x: _) { let _x: usize = x; } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index dbb014edd426c..20a74b3dac332 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -54,7 +54,29 @@ LL | fn test6(_: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:22:13 + --> $DIR/typeck_type_placeholder_item.rs:22:18 + | +LL | fn test6_b(_: _, _: T) { } + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn test6_b(_: K, _: T) { } + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:25:30 + | +LL | fn test6_c(_: _, _: (T, K, L, A, B)) { } + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn test6_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 | LL | fn test7(x: _) { let _x: usize = x; } | ^ not allowed in type signatures @@ -65,7 +87,7 @@ LL | fn test7(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:25:22 + --> $DIR/typeck_type_placeholder_item.rs:31:22 | LL | fn test8(_f: fn() -> _) { } | ^ not allowed in type signatures @@ -76,7 +98,7 @@ LL | fn test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:47:8 + --> $DIR/typeck_type_placeholder_item.rs:53:8 | LL | a: _, | ^ not allowed in type signatures @@ -95,7 +117,7 @@ LL | b: (T, T), | error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:53:21 + --> $DIR/typeck_type_placeholder_item.rs:59:21 | LL | fn fn_test() -> _ { 5 } | ^ @@ -104,7 +126,7 @@ LL | fn fn_test() -> _ { 5 } | help: replace this 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:56:22 + --> $DIR/typeck_type_placeholder_item.rs:62:22 | LL | fn fn_test2() -> (_, _) { (5, 5) } | ^^^^^^ @@ -113,7 +135,7 @@ LL | fn fn_test2() -> (_, _) { (5, 5) } | help: replace this 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:59:22 + --> $DIR/typeck_type_placeholder_item.rs:65:22 | LL | static FN_TEST3: _ = "test"; | ^ @@ -122,7 +144,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:62:22 + --> $DIR/typeck_type_placeholder_item.rs:68:22 | LL | static FN_TEST4: _ = 145; | ^ @@ -131,7 +153,7 @@ 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:65:23 + --> $DIR/typeck_type_placeholder_item.rs:71:23 | LL | static FN_TEST5: (_, _) = (1, 2); | ^ ^ not allowed in type signatures @@ -139,7 +161,7 @@ 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:68:20 + --> $DIR/typeck_type_placeholder_item.rs:74:20 | LL | fn fn_test6(_: _) { } | ^ not allowed in type signatures @@ -150,7 +172,7 @@ LL | fn fn_test6(_: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:71:20 + --> $DIR/typeck_type_placeholder_item.rs:77:20 | LL | fn fn_test7(x: _) { let _x: usize = x; } | ^ not allowed in type signatures @@ -161,7 +183,7 @@ LL | fn fn_test7(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:74:29 + --> $DIR/typeck_type_placeholder_item.rs:80:29 | LL | fn fn_test8(_f: fn() -> _) { } | ^ not allowed in type signatures @@ -172,7 +194,7 @@ LL | fn fn_test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:96:12 + --> $DIR/typeck_type_placeholder_item.rs:102:12 | LL | a: _, | ^ not allowed in type signatures @@ -191,19 +213,19 @@ LL | b: (T, T), | error[E0282]: type annotations needed - --> $DIR/typeck_type_placeholder_item.rs:101:27 + --> $DIR/typeck_type_placeholder_item.rs:107: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:101:27 + --> $DIR/typeck_type_placeholder_item.rs:107:27 | 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:105:29 + --> $DIR/typeck_type_placeholder_item.rs:111:29 | LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | ^^^^^^ @@ -212,7 +234,7 @@ LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | help: replace this 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:108:21 + --> $DIR/typeck_type_placeholder_item.rs:114:21 | LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | ^ ^ not allowed in type signatures @@ -225,7 +247,7 @@ LL | fn fn_test13(x: T) -> (i32, T) { (x, x) } | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:113:31 + --> $DIR/typeck_type_placeholder_item.rs:119:31 | LL | fn method_test1(&self, x: _); | ^ not allowed in type signatures @@ -236,7 +258,7 @@ LL | fn method_test1(&self, x: T); | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:115:31 + --> $DIR/typeck_type_placeholder_item.rs:121:31 | LL | fn method_test2(&self, x: _) -> _; | ^ ^ not allowed in type signatures @@ -249,7 +271,7 @@ LL | fn method_test2(&self, x: T) -> T; | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:117:31 + --> $DIR/typeck_type_placeholder_item.rs:123:31 | LL | fn method_test3(&self) -> _; | ^ not allowed in type signatures @@ -260,7 +282,7 @@ LL | fn method_test3(&self) -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:119:26 + --> $DIR/typeck_type_placeholder_item.rs:125:26 | LL | fn assoc_fn_test1(x: _); | ^ not allowed in type signatures @@ -271,7 +293,7 @@ LL | fn assoc_fn_test1(x: T); | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:121:26 + --> $DIR/typeck_type_placeholder_item.rs:127:26 | LL | fn assoc_fn_test2(x: _) -> _; | ^ ^ not allowed in type signatures @@ -284,7 +306,7 @@ LL | fn assoc_fn_test2(x: T) -> T; | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:123:28 + --> $DIR/typeck_type_placeholder_item.rs:129:28 | LL | fn assoc_fn_test3() -> _; | ^ not allowed in type signatures @@ -295,7 +317,7 @@ LL | fn assoc_fn_test3() -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:31:24 + --> $DIR/typeck_type_placeholder_item.rs:37:24 | LL | fn test9(&self) -> _ { () } | ^ @@ -304,7 +326,7 @@ LL | fn test9(&self) -> _ { () } | help: replace this with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:34:27 + --> $DIR/typeck_type_placeholder_item.rs:40:27 | LL | fn test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -315,7 +337,7 @@ LL | fn test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:39:24 + --> $DIR/typeck_type_placeholder_item.rs:45:24 | LL | fn clone(&self) -> _ { Test9 } | ^ @@ -324,7 +346,7 @@ LL | fn clone(&self) -> _ { Test9 } | help: replace this 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:42:37 + --> $DIR/typeck_type_placeholder_item.rs:48:37 | LL | fn clone_from(&mut self, other: _) { *self = Test9; } | ^ not allowed in type signatures @@ -335,7 +357,7 @@ LL | fn clone_from(&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:80:31 + --> $DIR/typeck_type_placeholder_item.rs:86:31 | LL | fn fn_test9(&self) -> _ { () } | ^ @@ -344,7 +366,7 @@ LL | fn fn_test9(&self) -> _ { () } | help: replace this with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:83:34 + --> $DIR/typeck_type_placeholder_item.rs:89:34 | LL | fn fn_test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -355,7 +377,7 @@ LL | fn fn_test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:88:28 + --> $DIR/typeck_type_placeholder_item.rs:94:28 | LL | fn clone(&self) -> _ { FnTest9 } | ^ @@ -364,7 +386,7 @@ LL | fn clone(&self) -> _ { FnTest9 } | help: replace this 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:91:41 + --> $DIR/typeck_type_placeholder_item.rs:97:41 | LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } | ^ not allowed in type signatures @@ -374,7 +396,7 @@ help: use type parameters instead LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } | ^^^ ^ -error: aborting due to 36 previous errors +error: aborting due to 38 previous errors Some errors have detailed explanations: E0121, E0282. For more information about an error, try `rustc --explain E0121`. From 3a9c3f92ccc2056e73a88840afde6b9df0dbf7ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 26 Dec 2019 13:25:04 -0800 Subject: [PATCH 4/8] Format and fix rebase --- src/librustc_typeck/astconv.rs | 10 +++------- src/librustc_typeck/collect.rs | 18 ++++++++++-------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 7ce26696e606e..9916d1b8999f8 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -2,12 +2,13 @@ //! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an //! instance of `AstConv`. +use crate::collect::PlaceholderHirTyCollector; use crate::hir::def::{CtorOf, DefKind, Res}; use crate::hir::def_id::DefId; +use crate::hir::intravisit::Visitor; use crate::hir::print; use crate::hir::ptr::P; use crate::hir::{self, ExprKind, GenericArg, GenericArgs, HirVec}; -use crate::hir::intravisit::Visitor; use crate::lint; use crate::middle::lang_items::SizedTraitLangItem; use crate::middle::resolve_lifetime as rl; @@ -16,7 +17,6 @@ use crate::require_c_abi_if_c_variadic; use crate::util::common::ErrorReported; use crate::util::nodemap::FxHashMap; use errors::{Applicability, DiagnosticId}; -use crate::collect::PlaceholderHirTyCollector; use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc::traits; use rustc::ty::subst::{self, InternalSubsts, Subst, SubstsRef}; @@ -2786,11 +2786,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::Return(ref output) => { let mut visitor = PlaceholderHirTyCollector::new(); visitor.visit_ty(output); - let is_infer = if let hir::TyKind::Infer = output.kind { - true - } else { - false - }; + let is_infer = if let hir::TyKind::Infer = output.kind { true } else { false }; if (is_infer || !visitor.0.is_empty()) && !self.allow_ty_infer() { output_placeholder_types.extend(visitor.0); tcx.types.err diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index ccff01755e93a..fd173bfbb9267 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -135,10 +135,13 @@ crate fn placeholder_type_error( ) { if !placeholder_types.is_empty() { let possible_names = ["T", "K", "L", "A", "B", "C"]; - let used_names = generics.iter().filter_map(|p| match p.name { - hir::ParamName::Plain(ident) => Some(ident.name), - _ => None, - }).collect::>(); + let used_names = generics + .iter() + .filter_map(|p| match p.name { + hir::ParamName::Plain(ident) => Some(ident.name), + _ => None, + }) + .collect::>(); let mut type_name = "ParamName"; for name in &possible_names { @@ -147,10 +150,9 @@ crate fn placeholder_type_error( break; } } - - let mut sugg: Vec<_> = placeholder_types.iter() - .map(|sp| (*sp, type_name.to_string())) - .collect(); + + 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))); } else { From e843245716586222fe997b8ffe10ab8bf91fc399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 26 Dec 2019 14:01:45 -0800 Subject: [PATCH 5/8] review comments --- src/librustc_typeck/astconv.rs | 11 ++--- src/librustc_typeck/collect.rs | 82 +++++++++++++++++----------------- 2 files changed, 46 insertions(+), 47 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 9916d1b8999f8..e0908d5d18b19 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -2748,11 +2748,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option>) -> Ty<'tcx> { - if crate::collect::is_infer_ty(ty) && expected_ty.is_some() { - self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span); - expected_ty.unwrap() - } else { - self.ast_ty_to_ty(ty) + match ty.kind { + hir::TyKind::Infer if expected_ty.is_some() => { + self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span); + expected_ty.unwrap() + } + _ => self.ast_ty_to_ty(ty), } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index fd173bfbb9267..6b968155e744c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -133,52 +133,50 @@ crate fn placeholder_type_error( placeholder_types: Vec, suggest: bool, ) { - if !placeholder_types.is_empty() { - let possible_names = ["T", "K", "L", "A", "B", "C"]; - let used_names = generics - .iter() - .filter_map(|p| match p.name { - hir::ParamName::Plain(ident) => Some(ident.name), - _ => None, - }) - .collect::>(); + if placeholder_types.is_empty() { + return; + } + let possible_names = ["T", "K", "L", "A", "B", "C"]; + let used_names = generics + .iter() + .filter_map(|p| match p.name { + hir::ParamName::Plain(ident) => Some(ident.name), + _ => None, + }) + .collect::>(); - let mut type_name = "ParamName"; - for name in &possible_names { - if !used_names.contains(&Symbol::intern(name)) { - type_name = name; - break; - } - } + let type_name = possible_names + .iter() + .find(|n| !used_names.contains(&Symbol::intern(n))) + .unwrap_or(&"ParamName"); - 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))); - } else { - sugg.push(( - generics.iter().last().unwrap().span.shrink_to_hi(), - format!(", {}", type_name), - )); - } - let mut err = struct_span_err!( - tcx.sess, - placeholder_types.clone(), - E0121, - "the type placeholder `_` is not allowed within types on item signatures", + 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))); + } else { + sugg.push(( + generics.iter().last().unwrap().span.shrink_to_hi(), + format!(", {}", type_name), + )); + } + let mut err = struct_span_err!( + tcx.sess, + placeholder_types.clone(), + E0121, + "the type placeholder `_` is not allowed within types on item signatures", + ); + for span in &placeholder_types { + err.span_label(*span, "not allowed in type signatures"); + } + if suggest { + err.multipart_suggestion( + "use type parameters instead", + sugg, + Applicability::HasPlaceholders, ); - for span in &placeholder_types { - err.span_label(*span, "not allowed in type signatures"); - } - if suggest { - err.multipart_suggestion( - "use type parameters instead", - sugg, - Applicability::HasPlaceholders, - ); - } - err.emit(); } + err.emit(); } fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { From cfa0b07c8d7e4c63e01549b1b026bb7494a7c4f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 27 Dec 2019 04:15:48 -0800 Subject: [PATCH 6/8] clean up logic --- src/librustc/query/mod.rs | 10 ++ src/librustc_typeck/astconv.rs | 45 ++---- src/librustc_typeck/check/mod.rs | 24 ++- src/librustc_typeck/collect.rs | 68 ++++----- src/test/ui/error-codes/E0121.stderr | 2 +- .../ui/typeck/typeck_type_placeholder_item.rs | 4 +- .../typeck_type_placeholder_item.stderr | 137 ++++++++++-------- .../typeck_type_placeholder_item_help.stderr | 2 +- 8 files changed, 150 insertions(+), 142 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 24841a1ccf456..364348e64386a 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -398,6 +398,16 @@ rustc_queries! { typeck_tables.map(|tables| &*tcx.arena.alloc(tables)) } } + query diagnostic_only_typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> { + cache_on_disk_if { key.is_local() } + load_cached(tcx, id) { + let typeck_tables: Option> = tcx + .queries.on_disk_cache + .try_load_query_result(tcx, id); + + typeck_tables.map(|tables| &*tcx.arena.alloc(tables)) + } + } } Other { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index e0908d5d18b19..b7ab9e30b94ee 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -2770,30 +2770,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.tcx(); // We proactively collect all the infered type params to emit a single error per fn def. - let mut placeholder_types = vec![]; - let mut output_placeholder_types = vec![]; - - let input_tys = decl.inputs.iter().map(|a| { - let mut visitor = PlaceholderHirTyCollector::new(); - visitor.visit_ty(&a); - if visitor.0.is_empty() || self.allow_ty_infer() { - self.ty_of_arg(a, None) - } else { - placeholder_types.extend(visitor.0); - tcx.types.err - } - }); + let mut visitor = PlaceholderHirTyCollector::new(); + for ty in &decl.inputs { + visitor.visit_ty(ty); + } + let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None)); let output_ty = match decl.output { hir::Return(ref output) => { - let mut visitor = PlaceholderHirTyCollector::new(); visitor.visit_ty(output); - let is_infer = if let hir::TyKind::Infer = output.kind { true } else { false }; - if (is_infer || !visitor.0.is_empty()) && !self.allow_ty_infer() { - output_placeholder_types.extend(visitor.0); - tcx.types.err - } else { - self.ast_ty_to_ty(output) - } + self.ast_ty_to_ty(output) } hir::DefaultReturn(..) => tcx.mk_unit(), }; @@ -2803,15 +2788,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let bare_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi)); - placeholder_types.extend(output_placeholder_types); - - crate::collect::placeholder_type_error( - tcx, - ident_span.unwrap_or(DUMMY_SP), - generic_params, - placeholder_types, - ident_span.is_some(), - ); + if !self.allow_ty_infer() { + crate::collect::placeholder_type_error( + tcx, + ident_span.unwrap_or(DUMMY_SP), + generic_params, + visitor.0, + ident_span.is_some(), + ); + } // Find any late-bound regions declared in return type that do // not appear in the arguments. These are not well-formed. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d9beb8ee3bd87..acdbd4832e96d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -756,6 +756,7 @@ pub fn provide(providers: &mut Providers<'_>) { *providers = Providers { typeck_item_bodies, typeck_tables_of, + diagnostic_only_typeck_tables_of, has_typeck_tables, adt_destructor, used_trait_imports, @@ -941,7 +942,26 @@ where val.fold_with(&mut FixupFolder { tcx }) } -fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> { +fn typeck_tables_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &ty::TypeckTables<'tcx> { + let fallback = move || tcx.type_of(def_id); + typeck_tables_of_with_fallback(tcx, def_id, fallback) +} + +/// Used only to get `TypeckTables` for type inference during error recovery. +/// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors. +fn diagnostic_only_typeck_tables_of<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, +) -> &ty::TypeckTables<'tcx> { + let fallback = move || tcx.types.err; + typeck_tables_of_with_fallback(tcx, def_id, fallback) +} + +fn typeck_tables_of_with_fallback<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + fallback: impl Fn() -> Ty<'tcx> + 'tcx, +) -> &'tcx ty::TypeckTables<'tcx> { // Closures' tables come from their outermost function, // as they are part of the same "inference environment". let outer_def_id = tcx.closure_base_def_id(def_id); @@ -990,7 +1010,7 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> { hir::TyKind::Infer => Some(AstConv::ast_ty_to_ty(&fcx, ty)), _ => None, }) - .unwrap_or_else(|| tcx.type_of(def_id)); + .unwrap_or_else(fallback); 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 6b968155e744c..53b63fe0b419c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -160,15 +160,7 @@ crate fn placeholder_type_error( format!(", {}", type_name), )); } - let mut err = struct_span_err!( - tcx.sess, - placeholder_types.clone(), - E0121, - "the type placeholder `_` is not allowed within types on item signatures", - ); - for span in &placeholder_types { - err.span_label(*span, "not allowed in type signatures"); - } + let mut err = bad_placeholder_type(tcx, placeholder_types); if suggest { err.multipart_suggestion( "use type parameters instead", @@ -184,14 +176,8 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir hir::ItemKind::Union(_, generics) | hir::ItemKind::Enum(_, generics) | hir::ItemKind::Struct(_, generics) => (&generics.params[..], true), - hir::ItemKind::Static(ty, ..) => { - if let hir::TyKind::Infer = ty.kind { - return; // We handle it elsewhere to attempt to suggest an appropriate type. - } else { - (&[][..], false) - } - } hir::ItemKind::TyAlias(_, generics) => (&generics.params[..], false), + // hir::ItemKind::Static(ty, ..) => { // hir::ItemKind::Fn(..) | // hir::ItemKind::Const(..) => {} // We handle these elsewhere to suggest appropriate type. _ => return, @@ -255,15 +241,21 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { /////////////////////////////////////////////////////////////////////////// // Utility types and common code for the above passes. -fn bad_placeholder_type(tcx: TyCtxt<'tcx>, span: Span) -> errors::DiagnosticBuilder<'tcx> { - let mut diag = struct_span_err!( +fn bad_placeholder_type( + tcx: TyCtxt<'tcx>, + mut spans: Vec, +) -> errors::DiagnosticBuilder<'tcx> { + spans.sort(); + let mut err = struct_span_err!( tcx.sess, - span, + spans.clone(), E0121, "the type placeholder `_` is not allowed within types on item signatures", ); - diag.span_label(span, "not allowed in type signatures"); - diag + for span in spans { + err.span_label(span, "not allowed in type signatures"); + } + err } impl ItemCtxt<'tcx> { @@ -298,7 +290,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { } fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { - self.tcx().sess.delay_span_bug(span, "bad placeholder type, but no error was emitted"); + self.tcx().sess.delay_span_bug(span, "bad placeholder type"); self.tcx().types.err } @@ -308,7 +300,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { _: Option<&ty::GenericParamDef>, span: Span, ) -> &'tcx Const<'tcx> { - bad_placeholder_type(self.tcx(), span).emit(); + bad_placeholder_type(self.tcx(), vec![span]).emit(); self.tcx().consts.err } @@ -1233,7 +1225,7 @@ fn infer_placeholder_type( span: Span, item_ident: Ident, ) -> Ty<'_> { - let ty = tcx.typeck_tables_of(def_id).node_type(body_id.hir_id); + let ty = tcx.diagnostic_only_typeck_tables_of(def_id).node_type(body_id.hir_id); // If this came from a free `const` or `static mut?` item, // then the user may have written e.g. `const A = 42;`. @@ -1253,7 +1245,7 @@ fn infer_placeholder_type( .emit(); } None => { - let mut diag = bad_placeholder_type(tcx, span); + let mut diag = bad_placeholder_type(tcx, vec![span]); if ty != tcx.types.err { diag.span_suggestion( span, @@ -1284,12 +1276,8 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } TraitItemKind::Const(ref ty, body_id) => body_id .and_then(|body_id| { - if let hir::TyKind::Infer = ty.kind { + if is_infer_ty(ty) { Some(infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)) - } else if is_infer_ty(ty) { - // Infering this would cause a cycle error. - tcx.sess.delay_span_bug(ty.span, "`_` placeholder but no error emitted"); - Some(tcx.types.err) } else { None } @@ -1307,12 +1295,8 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { tcx.mk_fn_def(def_id, substs) } ImplItemKind::Const(ref ty, body_id) => { - if let hir::TyKind::Infer = ty.kind { + if is_infer_ty(ty) { infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident) - } else if is_infer_ty(ty) { - // Infering this would cause a cycle error. - tcx.sess.delay_span_bug(ty.span, "`_` placeholder but no error emitted"); - tcx.types.err } else { icx.to_ty(ty) } @@ -1336,12 +1320,8 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { Node::Item(item) => { match item.kind { ItemKind::Static(ref ty, .., body_id) | ItemKind::Const(ref ty, body_id) => { - if let hir::TyKind::Infer = ty.kind { + if is_infer_ty(ty) { infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident) - } else if is_infer_ty(ty) { - // Infering this would cause a cycle error. - tcx.sess.delay_span_bug(ty.span, "`_` placeholder but no error emitted"); - tcx.types.err } else { icx.to_ty(ty) } @@ -1818,7 +1798,7 @@ crate fn is_infer_ty(ty: &hir::Ty<'_>) -> bool { hir::TyKind::Slice(ty) | hir::TyKind::Array(ty, _) => is_infer_ty(ty), hir::TyKind::Tup(tys) if !tys.is_empty() - && tys.iter().all(|ty| match ty.kind { + && tys.iter().any(|ty| match ty.kind { hir::TyKind::Infer => true, _ => false, }) => @@ -1858,12 +1838,14 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { match get_infer_ret_ty(&sig.decl.output) { Some(ty) => { let fn_sig = tcx.typeck_tables_of(def_id).liberated_fn_sigs()[hir_id]; - let mut diag = bad_placeholder_type(tcx, ty.span); + let mut visitor = PlaceholderHirTyCollector::new(); + visitor.visit_ty(ty); + let mut diag = bad_placeholder_type(tcx, visitor.0); let ret_ty = fn_sig.output(); if ret_ty != tcx.types.err { diag.span_suggestion( ty.span, - "replace this with the correct return type", + "replace with the correct return type", ret_ty.to_string(), Applicability::MaybeIncorrect, ); diff --git a/src/test/ui/error-codes/E0121.stderr b/src/test/ui/error-codes/E0121.stderr index 5da9a4c080f90..5a5c6b40c5afe 100644 --- a/src/test/ui/error-codes/E0121.stderr +++ b/src/test/ui/error-codes/E0121.stderr @@ -5,7 +5,7 @@ LL | fn foo() -> _ { 5 } | ^ | | | not allowed in type signatures - | help: replace this with the correct return type: `i32` + | help: replace with the correct return type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/E0121.rs:3:13 diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index d1fb51e0fe244..5b0ca2f347ea8 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -30,6 +30,7 @@ fn test7(x: _) { let _x: usize = x; } fn test8(_f: fn() -> _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures struct Test9; @@ -79,6 +80,7 @@ pub fn main() { fn fn_test8(_f: fn() -> _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures struct FnTest9; @@ -128,4 +130,4 @@ trait T { //~^ ERROR the type placeholder `_` is not allowed within types on item signatures fn assoc_fn_test3() -> _; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -} \ No newline at end of file +} diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index 20a74b3dac332..9fe7af4c822c1 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -5,16 +5,17 @@ LL | fn test() -> _ { 5 } | ^ | | | not allowed in type signatures - | help: replace this with the correct return type: `i32` + | 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:15 + --> $DIR/typeck_type_placeholder_item.rs:7:16 | LL | fn test2() -> (_, _) { (5, 5) } - | ^^^^^^ - | | - | not allowed in type signatures - | help: replace this with the correct return type: `(i32, i32)` + | -^--^- + | || | + | || not allowed in type signatures + | |not allowed in type signatures + | 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 @@ -35,12 +36,10 @@ 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:16 + --> $DIR/typeck_type_placeholder_item.rs:16:15 | LL | static TEST5: (_, _) = (1, 2); - | ^ ^ not allowed in type signatures - | | - | not allowed in type signatures + | ^^^^^^ 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 @@ -86,6 +85,12 @@ help: use type parameters instead LL | fn test7(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 + | +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 | @@ -98,7 +103,7 @@ LL | fn test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:53:8 + --> $DIR/typeck_type_placeholder_item.rs:54:8 | LL | a: _, | ^ not allowed in type signatures @@ -117,25 +122,26 @@ LL | b: (T, T), | error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:59:21 + --> $DIR/typeck_type_placeholder_item.rs:60:21 | LL | fn fn_test() -> _ { 5 } | ^ | | | not allowed in type signatures - | help: replace this with the correct return type: `i32` + | 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:62:22 + --> $DIR/typeck_type_placeholder_item.rs:63:23 | LL | fn fn_test2() -> (_, _) { (5, 5) } - | ^^^^^^ - | | - | not allowed in type signatures - | help: replace this with the correct return type: `(i32, i32)` + | -^--^- + | || | + | || not allowed in type signatures + | |not allowed in type signatures + | 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:65:22 + --> $DIR/typeck_type_placeholder_item.rs:66:22 | LL | static FN_TEST3: _ = "test"; | ^ @@ -144,7 +150,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:68:22 + --> $DIR/typeck_type_placeholder_item.rs:69:22 | LL | static FN_TEST4: _ = 145; | ^ @@ -153,15 +159,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:71:23 + --> $DIR/typeck_type_placeholder_item.rs:72:22 | LL | static FN_TEST5: (_, _) = (1, 2); - | ^ ^ not allowed in type signatures - | | - | not allowed in type signatures + | ^^^^^^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:74:20 + --> $DIR/typeck_type_placeholder_item.rs:75:20 | LL | fn fn_test6(_: _) { } | ^ not allowed in type signatures @@ -172,7 +176,7 @@ LL | fn fn_test6(_: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:77:20 + --> $DIR/typeck_type_placeholder_item.rs:78:20 | LL | fn fn_test7(x: _) { let _x: usize = x; } | ^ not allowed in type signatures @@ -183,7 +187,13 @@ LL | fn fn_test7(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:80:29 + --> $DIR/typeck_type_placeholder_item.rs:81: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 | LL | fn fn_test8(_f: fn() -> _) { } | ^ not allowed in type signatures @@ -194,7 +204,7 @@ LL | fn fn_test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:102:12 + --> $DIR/typeck_type_placeholder_item.rs:104:12 | LL | a: _, | ^ not allowed in type signatures @@ -213,41 +223,40 @@ LL | b: (T, T), | error[E0282]: type annotations needed - --> $DIR/typeck_type_placeholder_item.rs:107:27 + --> $DIR/typeck_type_placeholder_item.rs:109: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:107:27 + --> $DIR/typeck_type_placeholder_item.rs:109:28 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } - | ^^^^^^ not allowed in type signatures + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:111:29 + --> $DIR/typeck_type_placeholder_item.rs:113:30 | LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } - | ^^^^^^ - | | - | not allowed in type signatures - | help: replace this with the correct return type: `(i32, i32)` + | -^--^- + | || | + | || not allowed in type signatures + | |not allowed in type signatures + | 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:114:21 + --> $DIR/typeck_type_placeholder_item.rs:116:33 | LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } - | ^ ^ not allowed in type signatures - | | - | not allowed in type signatures - | -help: use type parameters instead - | -LL | fn fn_test13(x: T) -> (i32, T) { (x, x) } - | ^^^ ^ ^ + | ------^- + | | | + | | not allowed in type signatures + | 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:119:31 + --> $DIR/typeck_type_placeholder_item.rs:121:31 | LL | fn method_test1(&self, x: _); | ^ not allowed in type signatures @@ -258,7 +267,7 @@ LL | fn method_test1(&self, x: T); | ^^^ ^ 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:123:31 | LL | fn method_test2(&self, x: _) -> _; | ^ ^ not allowed in type signatures @@ -271,7 +280,7 @@ LL | fn method_test2(&self, x: T) -> 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:125:31 | LL | fn method_test3(&self) -> _; | ^ not allowed in type signatures @@ -282,7 +291,7 @@ LL | fn method_test3(&self) -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:125:26 + --> $DIR/typeck_type_placeholder_item.rs:127:26 | LL | fn assoc_fn_test1(x: _); | ^ not allowed in type signatures @@ -293,7 +302,7 @@ LL | fn assoc_fn_test1(x: 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:129:26 | LL | fn assoc_fn_test2(x: _) -> _; | ^ ^ not allowed in type signatures @@ -306,7 +315,7 @@ LL | fn assoc_fn_test2(x: T) -> T; | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:129:28 + --> $DIR/typeck_type_placeholder_item.rs:131:28 | LL | fn assoc_fn_test3() -> _; | ^ not allowed in type signatures @@ -317,16 +326,16 @@ LL | fn assoc_fn_test3() -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:37:24 + --> $DIR/typeck_type_placeholder_item.rs:38:24 | LL | fn test9(&self) -> _ { () } | ^ | | | not allowed in type signatures - | help: replace this with the correct return type: `()` + | 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:40:27 + --> $DIR/typeck_type_placeholder_item.rs:41:27 | LL | fn test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -337,16 +346,16 @@ LL | fn test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:45:24 + --> $DIR/typeck_type_placeholder_item.rs:46:24 | LL | fn clone(&self) -> _ { Test9 } | ^ | | | not allowed in type signatures - | help: replace this with the correct return type: `Test9` + | 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:48:37 + --> $DIR/typeck_type_placeholder_item.rs:49:37 | LL | fn clone_from(&mut self, other: _) { *self = Test9; } | ^ not allowed in type signatures @@ -357,16 +366,16 @@ LL | fn clone_from(&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:86:31 + --> $DIR/typeck_type_placeholder_item.rs:88:31 | LL | fn fn_test9(&self) -> _ { () } | ^ | | | not allowed in type signatures - | help: replace this with the correct return type: `()` + | 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:89:34 + --> $DIR/typeck_type_placeholder_item.rs:91:34 | LL | fn fn_test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -377,16 +386,16 @@ LL | fn fn_test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:94:28 + --> $DIR/typeck_type_placeholder_item.rs:96:28 | LL | fn clone(&self) -> _ { FnTest9 } | ^ | | | not allowed in type signatures - | help: replace this with the correct return type: `main::FnTest9` + | 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:97:41 + --> $DIR/typeck_type_placeholder_item.rs:99:41 | LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } | ^ not allowed in type signatures @@ -396,7 +405,7 @@ help: use type parameters instead LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } | ^^^ ^ -error: aborting due to 38 previous errors +error: aborting due to 40 previous errors Some errors have detailed explanations: E0121, E0282. For more information about an error, try `rustc --explain E0121`. diff --git a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr index ab002381b1f79..e3bc059d1f181 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr @@ -5,7 +5,7 @@ LL | fn test1() -> _ { Some(42) } | ^ | | | not allowed in type signatures - | help: replace this with the correct return type: `std::option::Option` + | help: replace with the correct return type: `std::option::Option` error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item_help.rs:7:14 From 8a3872ea9c2692edd84d8841a8d43175e3725319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 27 Dec 2019 15:45:39 -0800 Subject: [PATCH 7/8] review comments --- src/librustc_typeck/check/mod.rs | 7 ++++++- src/librustc_typeck/collect.rs | 18 +++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index acdbd4832e96d..67bbc6db49577 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -953,7 +953,12 @@ fn diagnostic_only_typeck_tables_of<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, ) -> &ty::TypeckTables<'tcx> { - let fallback = move || tcx.types.err; + assert!(def_id.is_local()); + let fallback = move || { + let span = tcx.hir().span(tcx.hir().as_local_hir_id(def_id).unwrap()); + tcx.sess.delay_span_bug(span, "diagnostic only typeck table used"); + tcx.types.err + }; typeck_tables_of_with_fallback(tcx, def_id, fallback) } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 53b63fe0b419c..abc0bc21fda08 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -177,9 +177,7 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir | hir::ItemKind::Enum(_, generics) | hir::ItemKind::Struct(_, generics) => (&generics.params[..], true), hir::ItemKind::TyAlias(_, generics) => (&generics.params[..], false), - // hir::ItemKind::Static(ty, ..) => { - // hir::ItemKind::Fn(..) | - // hir::ItemKind::Const(..) => {} // We handle these elsewhere to suggest appropriate type. + // `static`, `fn` and `const` are handled elsewhere to suggest appropriate type. _ => return, }; @@ -1276,7 +1274,7 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } TraitItemKind::Const(ref ty, body_id) => body_id .and_then(|body_id| { - if is_infer_ty(ty) { + if is_suggestable_infer_ty(ty) { Some(infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)) } else { None @@ -1295,7 +1293,7 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { tcx.mk_fn_def(def_id, substs) } ImplItemKind::Const(ref ty, body_id) => { - if is_infer_ty(ty) { + if is_suggestable_infer_ty(ty) { infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident) } else { icx.to_ty(ty) @@ -1320,7 +1318,7 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { Node::Item(item) => { match item.kind { ItemKind::Static(ref ty, .., body_id) | ItemKind::Const(ref ty, body_id) => { - if is_infer_ty(ty) { + if is_suggestable_infer_ty(ty) { infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident) } else { icx.to_ty(ty) @@ -1792,10 +1790,12 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } } -crate fn is_infer_ty(ty: &hir::Ty<'_>) -> bool { +/// 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 { match &ty.kind { hir::TyKind::Infer => true, - hir::TyKind::Slice(ty) | hir::TyKind::Array(ty, _) => is_infer_ty(ty), + hir::TyKind::Slice(ty) | hir::TyKind::Array(ty, _) => is_suggestable_infer_ty(ty), hir::TyKind::Tup(tys) if !tys.is_empty() && tys.iter().any(|ty| match ty.kind { @@ -1811,7 +1811,7 @@ crate fn is_infer_ty(ty: &hir::Ty<'_>) -> bool { pub fn get_infer_ret_ty(output: &'hir hir::FunctionRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> { if let hir::FunctionRetTy::Return(ref ty) = output { - if is_infer_ty(ty) { + if is_suggestable_infer_ty(ty) { return Some(&**ty); } } From 261b606ddc12cfb027659562f3e22fbf77bfe448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 30 Dec 2019 11:45:48 -0800 Subject: [PATCH 8/8] review comments and fix rebase --- src/librustc_typeck/astconv.rs | 8 ++++++-- src/librustc_typeck/collect.rs | 25 ++++++++----------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index b7ab9e30b94ee..91b062b45060a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -68,6 +68,7 @@ pub trait AstConv<'tcx> { /// Returns the type to use when a type is omitted. fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>; + /// Returns `true` if `_` is allowed in type signatures in the current context. fn allow_ty_infer(&self) -> bool; /// Returns the const to use when a const is omitted. @@ -2770,8 +2771,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.tcx(); // We proactively collect all the infered type params to emit a single error per fn def. - let mut visitor = PlaceholderHirTyCollector::new(); - for ty in &decl.inputs { + let mut visitor = PlaceholderHirTyCollector::default(); + for ty in decl.inputs { visitor.visit_ty(ty); } let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None)); @@ -2789,6 +2790,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ty::Binder::bind(tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi)); if !self.allow_ty_infer() { + // We always collect the spans for placeholder types when evaluating `fn`s, but we + // only want to emit an error complaining about them if infer types (`_`) are not + // allowed. `allow_ty_infer` gates this behavior. crate::collect::placeholder_type_error( tcx, ident_span.unwrap_or(DUMMY_SP), diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index abc0bc21fda08..7e04c9487a728 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -102,6 +102,7 @@ pub struct ItemCtxt<'tcx> { /////////////////////////////////////////////////////////////////////////// +#[derive(Default)] crate struct PlaceholderHirTyCollector(crate Vec); impl<'v> Visitor<'v> for PlaceholderHirTyCollector { @@ -116,16 +117,13 @@ impl<'v> Visitor<'v> for PlaceholderHirTyCollector { } } -impl PlaceholderHirTyCollector { - pub fn new() -> PlaceholderHirTyCollector { - PlaceholderHirTyCollector(vec![]) - } -} - struct CollectItemTypesVisitor<'tcx> { tcx: TyCtxt<'tcx>, } +/// If there are any placeholder types (`_`), emit an error explaining that this is not allowed +/// and suggest adding type parameters in the appropriate place, taking into consideration any and +/// 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, @@ -136,6 +134,7 @@ crate fn placeholder_type_error( if placeholder_types.is_empty() { return; } + // This is the whitelist of possible parameter names that we might suggest. let possible_names = ["T", "K", "L", "A", "B", "C"]; let used_names = generics .iter() @@ -181,7 +180,7 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir _ => return, }; - let mut visitor = PlaceholderHirTyCollector::new(); + let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_item(item); placeholder_type_error(tcx, item.ident.span, generics, visitor.0, suggest); @@ -1796,15 +1795,7 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool { match &ty.kind { hir::TyKind::Infer => true, hir::TyKind::Slice(ty) | hir::TyKind::Array(ty, _) => is_suggestable_infer_ty(ty), - hir::TyKind::Tup(tys) - if !tys.is_empty() - && tys.iter().any(|ty| match ty.kind { - hir::TyKind::Infer => true, - _ => false, - }) => - { - true - } + hir::TyKind::Tup(tys) => tys.iter().any(|ty| is_suggestable_infer_ty(ty)), _ => false, } } @@ -1838,7 +1829,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { match get_infer_ret_ty(&sig.decl.output) { Some(ty) => { let fn_sig = tcx.typeck_tables_of(def_id).liberated_fn_sigs()[hir_id]; - let mut visitor = PlaceholderHirTyCollector::new(); + let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_ty(ty); let mut diag = bad_placeholder_type(tcx, visitor.0); let ret_ty = fn_sig.output();