diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 9b7ae0993357b..1cd0b67ef05c0 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 569be6e1a55fd..41d493cceec69 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -2,8 +2,10 @@ //! 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::{self, ExprKind, GenericArg, GenericArgs}; use crate::lint; @@ -65,6 +67,9 @@ 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. fn ct_infer( &self, @@ -2591,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) @@ -2756,14 +2761,24 @@ 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. + 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)); let output_ty = match decl.output { - hir::Return(ref output) => self.ast_ty_to_ty(output), + hir::Return(ref output) => { + visitor.visit_ty(output); + self.ast_ty_to_ty(output) + } hir::DefaultReturn(..) => tcx.mk_unit(), }; @@ -2772,6 +2787,19 @@ 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)); + 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), + 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 c6c3ada49e312..67bbc6db49577 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,31 @@ 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> { + 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) +} + +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); @@ -963,7 +988,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) }; @@ -990,7 +1015,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); @@ -1069,6 +1094,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 +2589,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 1e3e6d77b9261..e8193ae944891 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -102,10 +102,90 @@ pub struct ItemCtxt<'tcx> { /////////////////////////////////////////////////////////////////////////// +#[derive(Default)] +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) + } +} + 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, + generics: &[hir::GenericParam<'_>], + placeholder_types: Vec, + suggest: bool, +) { + 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() + .filter_map(|p| match p.name { + hir::ParamName::Plain(ident) => Some(ident.name), + _ => None, + }) + .collect::>(); + + 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 = bad_placeholder_type(tcx, placeholder_types); + 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::TyAlias(_, generics) => (&generics.params[..], false), + // `static`, `fn` and `const` are handled elsewhere to suggest appropriate type. + _ => return, + }; + + let mut visitor = PlaceholderHirTyCollector::default(); + 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 +193,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); } @@ -157,15 +238,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> { @@ -195,9 +282,12 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { None } - fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { - bad_placeholder_type(self.tcx(), span).emit(); + fn allow_ty_infer(&self) -> bool { + false + } + fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { + self.tcx().sess.delay_span_bug(span, "bad placeholder type"); self.tcx().types.err } @@ -207,7 +297,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 } @@ -1132,7 +1222,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;`. @@ -1152,7 +1242,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, @@ -1183,7 +1273,7 @@ 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_suggestable_infer_ty(ty) { Some(infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)) } else { None @@ -1202,7 +1292,7 @@ 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_suggestable_infer_ty(ty) { infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident) } else { icx.to_ty(ty) @@ -1227,7 +1317,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 let hir::TyKind::Infer = ty.kind { + if is_suggestable_infer_ty(ty) { infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident) } else { icx.to_ty(ty) @@ -1699,9 +1789,20 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } } +/// Whether `ty` is a type with `_` placeholders that can be infered. Used in diagnostics only to +/// use inference to provide suggestions for the appropriate type if possible. +fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool { + match &ty.kind { + hir::TyKind::Infer => true, + hir::TyKind::Slice(ty) | hir::TyKind::Array(ty, _) => is_suggestable_infer_ty(ty), + hir::TyKind::Tup(tys) => tys.iter().any(|ty| is_suggestable_infer_ty(ty)), + _ => 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_suggestable_infer_ty(ty) { return Some(&**ty); } } @@ -1719,19 +1820,23 @@ 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]; - let mut diag = bad_placeholder_type(tcx, ty.span); + let mut visitor = PlaceholderHirTyCollector::default(); + 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 `_` with the correct return type", + "replace with the correct return type", ret_ty.to_string(), Applicability::MaybeIncorrect, ); @@ -1739,14 +1844,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 +2472,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..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 `_` 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/self/self-infer.stderr b/src/test/ui/self/self-infer.stderr index f91cfe5eb621b..1475b212b56a6 100644 --- a/src/test/ui/self/self-infer.stderr +++ b/src/test/ui/self/self-infer.stderr @@ -3,12 +3,22 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa | 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..5b0ca2f347ea8 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 @@ -16,16 +15,22 @@ 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 +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 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; @@ -49,8 +54,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() { @@ -59,7 +62,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 @@ -69,7 +71,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 @@ -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; @@ -102,8 +104,30 @@ 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!() } + //~^ 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 } diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index 2b4d9966c3d0b..9fe7af4c822c1 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -5,22 +5,20 @@ LL | fn test() -> _ { 5 } | ^ | | | not allowed in type signatures - | help: replace `_` 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:16 | LL | fn test2() -> (_, _) { (5, 5) } - | ^ not allowed in type signatures + | -^--^- + | || | + | || 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:7:19 - | -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:11:15 + --> $DIR/typeck_type_placeholder_item.rs:10:15 | LL | static TEST3: _ = "test"; | ^ @@ -29,7 +27,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 +36,112 @@ 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:15 | LL | static TEST5: (_, _) = (1, 2); - | ^ 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:17:19 + --> $DIR/typeck_type_placeholder_item.rs:19:13 | -LL | static TEST5: (_, _) = (1, 2); - | ^ not allowed in type signatures +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:21:13 + --> $DIR/typeck_type_placeholder_item.rs:22:18 | -LL | fn test6(_: _) { } - | ^ not allowed in type signatures +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:24:13 + --> $DIR/typeck_type_placeholder_item.rs:28: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: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:49:8 + --> $DIR/typeck_type_placeholder_item.rs:31:22 | -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 +LL | fn test8(_f: fn() -> _) { } + | ^ not allowed in type signatures | -LL | b: (_, _), - | ^ 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:51:12 + --> $DIR/typeck_type_placeholder_item.rs:54:8 | +LL | a: _, + | ^ not allowed in type signatures +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:102:12 + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures | -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 +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:104: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:57:21 + --> $DIR/typeck_type_placeholder_item.rs:60: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 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:63:23 | LL | fn fn_test2() -> (_, _) { (5, 5) } - | ^ not allowed in type signatures + | -^--^- + | || | + | || 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:64:22 + --> $DIR/typeck_type_placeholder_item.rs:66:22 | LL | static FN_TEST3: _ = "test"; | ^ @@ -134,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:67:22 + --> $DIR/typeck_type_placeholder_item.rs:69:22 | LL | static FN_TEST4: _ = 145; | ^ @@ -143,95 +159,253 @@ 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:72:22 | LL | static FN_TEST5: (_, _) = (1, 2); - | ^ 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:70: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:75: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:78: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: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:33:24 + --> $DIR/typeck_type_placeholder_item.rs:81: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:104: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: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:109:28 + | +LL | fn fn_test11(_: _) -> (_, _) { panic!() } + | ^ ^ 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:113:30 + | +LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } + | -^--^- + | || | + | || 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:116:33 + | +LL | fn fn_test13(x: _) -> (i32, _) { (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:121:31 + | +LL | fn method_test1(&self, x: _); + | ^ not allowed in type signatures + | +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:123:31 + | +LL | fn method_test2(&self, x: _) -> _; + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + | +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:125:31 + | +LL | fn method_test3(&self) -> _; + | ^ not allowed in type signatures + | +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:127:26 + | +LL | fn assoc_fn_test1(x: _); + | ^ not allowed in type signatures + | +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:129:26 + | +LL | fn assoc_fn_test2(x: _) -> _; + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + | +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:131:28 + | +LL | fn assoc_fn_test3() -> _; + | ^ not allowed in type signatures + | +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:38:24 | LL | fn test9(&self) -> _ { () } | ^ | | | not allowed in type signatures - | help: replace `_` 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:36:27 + --> $DIR/typeck_type_placeholder_item.rs:41: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:46:24 | LL | fn clone(&self) -> _ { Test9 } | ^ | | | not allowed in type signatures - | help: replace `_` 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:44:37 + --> $DIR/typeck_type_placeholder_item.rs:49: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:88:31 | LL | fn fn_test9(&self) -> _ { () } | ^ | | | not allowed in type signatures - | help: replace `_` 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 + | +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:96:28 | LL | fn clone(&self) -> _ { FnTest9 } | ^ | | | not allowed in type signatures - | help: replace `_` 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 + | +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 40 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..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 `_` 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