about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs5
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs1
-rw-r--r--compiler/rustc_typeck/src/collect.rs73
-rw-r--r--src/test/ui/issues/issue-74086.stderr5
-rw-r--r--src/test/ui/issues/issue-81885.rs10
-rw-r--r--src/test/ui/issues/issue-81885.stderr15
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_item_help.stderr5
7 files changed, 93 insertions, 21 deletions
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<Span>,
+        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<Span>,
     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