diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 244eba8ad5e..c9cc47b83e3 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2191,12 +2191,14 @@ 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, &hir::Generics::empty(), None, + Some(ast_ty), )) } hir::TyKind::TraitObject(ref bounds, ref lifetime) => { @@ -2336,6 +2338,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { decl: &hir::FnDecl<'_>, generics: &hir::Generics<'_>, ident_span: Option, + hir_ty: Option<&hir::Ty<'_>>, ) -> ty::PolyFnSig<'tcx> { debug!("ty_of_fn"); @@ -2367,12 +2370,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // only want to emit an error complaining about them if infer types (`_`) are not // allowed. `allow_ty_infer` gates this behavior. We check for the presence of // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`. + crate::collect::placeholder_type_error( tcx, ident_span.map(|sp| sp.shrink_to_hi()), &generics.params[..], visitor.0, true, + hir_ty, ); } diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 229127e95d9..fce7ae8119e 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -502,6 +502,7 @@ fn typeck_with_fallback<'tcx>( decl, &hir::Generics::empty(), None, + None, ) } else { tcx.fn_sig(def_id) diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 2598f3e38ce..e24aa7d76f1 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -143,6 +143,7 @@ crate fn placeholder_type_error( generics: &[hir::GenericParam<'_>], placeholder_types: Vec, suggest: bool, + hir_ty: Option<&hir::Ty<'_>>, ) { if placeholder_types.is_empty() { return; @@ -173,12 +174,40 @@ crate fn placeholder_type_error( } let mut err = bad_placeholder_type(tcx, placeholder_types); + + // Suggest, but only if it is not a function in const or static if suggest { - err.multipart_suggestion( - "use type parameters instead", - sugg, - Applicability::HasPlaceholders, - ); + let mut is_fn = false; + let mut is_const = false; + let mut is_static = false; + + if let Some(hir_ty) = hir_ty { + if let hir::TyKind::BareFn(_) = hir_ty.kind { + is_fn = true; + + // Check if parent is const or static + let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id); + let parent_node = tcx.hir().get(parent_id); + + if let hir::Node::Item(item) = parent_node { + if let hir::ItemKind::Const(_, _) = item.kind { + is_const = true; + } else if let hir::ItemKind::Static(_, _, _) = item.kind { + is_static = true; + } + } + } + } + + // if function is wrapped around a const or static, + // then don't show the suggestion + if !(is_fn && (is_const || is_static)) { + err.multipart_suggestion( + "use type parameters instead", + sugg, + Applicability::HasPlaceholders, + ); + } } err.emit(); } @@ -200,7 +229,14 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_item(item); - placeholder_type_error(tcx, Some(generics.span), &generics.params[..], visitor.0, suggest); + placeholder_type_error( + tcx, + Some(generics.span), + &generics.params[..], + visitor.0, + suggest, + None, + ); } impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { @@ -682,6 +718,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) { let it = tcx.hir().expect_item(item_id); debug!("convert: item {} with id {}", it.ident, it.hir_id); let def_id = tcx.hir().local_def_id(item_id); + match it.kind { // These don't define types. hir::ItemKind::ExternCrate(_) @@ -787,7 +824,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) { // Account for `const C: _;`. let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_trait_item(trait_item); - placeholder_type_error(tcx, None, &[], visitor.0, false); + placeholder_type_error(tcx, None, &[], visitor.0, false, None); } hir::TraitItemKind::Type(_, Some(_)) => { @@ -796,7 +833,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) { // Account for `type T = _;`. let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_trait_item(trait_item); - placeholder_type_error(tcx, None, &[], visitor.0, false); + placeholder_type_error(tcx, None, &[], visitor.0, false, None); } hir::TraitItemKind::Type(_, None) => { @@ -805,7 +842,8 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) { // even if there is no concrete type. let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_trait_item(trait_item); - placeholder_type_error(tcx, None, &[], visitor.0, false); + + placeholder_type_error(tcx, None, &[], visitor.0, false, None); } }; @@ -826,7 +864,8 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) { // Account for `type T = _;` let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_impl_item(impl_item); - placeholder_type_error(tcx, None, &[], visitor.0, false); + + placeholder_type_error(tcx, None, &[], visitor.0, false, None); } hir::ImplItemKind::Const(..) => {} } @@ -1654,6 +1693,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { &sig.decl, &generics, Some(ident.span), + None, ), } } @@ -1663,9 +1703,15 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { ident, generics, .. - }) => { - AstConv::ty_of_fn(&icx, header.unsafety, header.abi, decl, &generics, Some(ident.span)) - } + }) => AstConv::ty_of_fn( + &icx, + header.unsafety, + header.abi, + decl, + &generics, + Some(ident.span), + None, + ), ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(ref fn_decl, _, _), @@ -2335,6 +2381,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( decl, &hir::Generics::empty(), Some(ident.span), + None, ); // Feature gate SIMD types in FFI, since I am not sure that the diff --git a/src/test/ui/issues/issue-74086.stderr b/src/test/ui/issues/issue-74086.stderr index 4127f48a093..e602425059e 100644 --- a/src/test/ui/issues/issue-74086.stderr +++ b/src/test/ui/issues/issue-74086.stderr @@ -2,10 +2,7 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa --> $DIR/issue-74086.rs:2:20 | LL | static BUG: fn(_) -> u8 = |_| 8; - | ^ - | | - | not allowed in type signatures - | help: use type parameters instead: `T` + | ^ not allowed in type signatures error: aborting due to previous error diff --git a/src/test/ui/issues/issue-81885.rs b/src/test/ui/issues/issue-81885.rs new file mode 100644 index 00000000000..86c39d4a48c --- /dev/null +++ b/src/test/ui/issues/issue-81885.rs @@ -0,0 +1,10 @@ +const TEST4: fn() -> _ = 42; + //~^ ERROR the type placeholder `_` is not allowed within types on item + //signatures + +fn main() { + const TEST5: fn() -> _ = 42; + //~^ ERROR the type placeholder `_` is not allowed within types on item + //signatures + +} diff --git a/src/test/ui/issues/issue-81885.stderr b/src/test/ui/issues/issue-81885.stderr new file mode 100644 index 00000000000..955b4283874 --- /dev/null +++ b/src/test/ui/issues/issue-81885.stderr @@ -0,0 +1,15 @@ +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/issue-81885.rs:1:22 + | +LL | const TEST4: fn() -> _ = 42; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/issue-81885.rs:6:26 + | +LL | const TEST5: fn() -> _ = 42; + | ^ not allowed in type signatures + +error: aborting due to 2 previous errors + +For more information about this 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 0121e186316..f868c8d4834 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr @@ -29,10 +29,7 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa --> $DIR/typeck_type_placeholder_item_help.rs:13:22 | LL | const TEST4: fn() -> _ = 42; - | ^ - | | - | not allowed in type signatures - | help: use type parameters instead: `T` + | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item_help.rs:17:18