From 531505f1826941db43c4ccd7643a549e78b53832 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Wed, 31 Jan 2024 14:28:40 +0000
Subject: [PATCH] Check signature of intrinsics with fallback bodies

---
 .../rustc_hir_analysis/src/check/check.rs     | 21 +++++-
 .../rustc_hir_analysis/src/check/intrinsic.rs | 18 +++--
 library/core/src/intrinsics.rs                |  2 +-
 tests/ui/feature-gates/feature-gate-abi.rs    |  2 +
 .../ui/feature-gates/feature-gate-abi.stderr  | 67 +++++++++++--------
 .../feature-gates/feature-gate-intrinsics.rs  |  1 +
 .../feature-gate-intrinsics.stderr            |  8 ++-
 tests/ui/intrinsics-always-extern.rs          |  1 +
 tests/ui/intrinsics-always-extern.stderr      | 10 ++-
 9 files changed, 92 insertions(+), 38 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 6bc36176602..e213ebfb344 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -472,7 +472,18 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         DefKind::Enum => {
             check_enum(tcx, def_id);
         }
-        DefKind::Fn => {} // entirely within check_item_body
+        DefKind::Fn => {
+            if let Some(name) = tcx.intrinsic(def_id) {
+                intrinsic::check_intrinsic_type(
+                    tcx,
+                    def_id,
+                    tcx.def_ident_span(def_id).unwrap(),
+                    name,
+                    Abi::Rust,
+                )
+            }
+            // Everything else is checked entirely within check_item_body
+        }
         DefKind::Impl { of_trait } => {
             if of_trait && let Some(impl_trait_ref) = tcx.impl_trait_ref(def_id) {
                 check_impl_items_against_trait(tcx, def_id, impl_trait_ref.instantiate_identity());
@@ -533,7 +544,13 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
             match abi {
                 Abi::RustIntrinsic => {
                     for item in items {
-                        intrinsic::check_intrinsic_type(tcx, item.id.owner_id.def_id, item.span);
+                        intrinsic::check_intrinsic_type(
+                            tcx,
+                            item.id.owner_id.def_id,
+                            item.span,
+                            item.ident.name,
+                            abi,
+                        );
                     }
                 }
 
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index fe1a5a28964..b0cf1d1656d 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -26,7 +26,8 @@ fn equate_intrinsic_type<'tcx>(
     sig: ty::PolyFnSig<'tcx>,
 ) {
     let (own_counts, span) = match tcx.hir_node_by_def_id(def_id) {
-        hir::Node::ForeignItem(hir::ForeignItem {
+        hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
+        | hir::Node::ForeignItem(hir::ForeignItem {
             kind: hir::ForeignItemKind::Fn(.., generics),
             ..
         }) => {
@@ -136,7 +137,13 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
 
 /// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`,
 /// and in `library/core/src/intrinsics.rs`.
-pub fn check_intrinsic_type(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId, span: Span) {
+pub fn check_intrinsic_type(
+    tcx: TyCtxt<'_>,
+    intrinsic_id: LocalDefId,
+    span: Span,
+    intrinsic_name: Symbol,
+    abi: Abi,
+) {
     let generics = tcx.generics_of(intrinsic_id);
     let param = |n| {
         if let Some(&ty::GenericParamDef {
@@ -148,7 +155,6 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId, span: Spa
             Ty::new_error_with_message(tcx, span, "expected param")
         }
     };
-    let intrinsic_name = tcx.item_name(intrinsic_id.into());
     let name_str = intrinsic_name.as_str();
 
     let bound_vars = tcx.mk_bound_variable_kinds(&[
@@ -479,7 +485,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId, span: Spa
 
             sym::black_box => (1, 0, vec![param(0)], param(0)),
 
-            sym::is_val_statically_known => (1, 0, vec![param(0)], tcx.types.bool),
+            sym::is_val_statically_known => (1, 1, vec![param(0)], tcx.types.bool),
 
             sym::const_eval_select => (4, 0, vec![param(0), param(1), param(2)], param(3)),
 
@@ -487,7 +493,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId, span: Spa
                 (0, 0, vec![Ty::new_imm_ptr(tcx, Ty::new_unit(tcx))], tcx.types.usize)
             }
 
-            sym::debug_assertions => (0, 0, Vec::new(), tcx.types.bool),
+            sym::debug_assertions => (0, 1, Vec::new(), tcx.types.bool),
 
             other => {
                 tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span, name: other });
@@ -496,7 +502,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId, span: Spa
         };
         (n_tps, 0, n_cts, inputs, output, unsafety)
     };
-    let sig = tcx.mk_fn_sig(inputs, output, false, unsafety, Abi::RustIntrinsic);
+    let sig = tcx.mk_fn_sig(inputs, output, false, unsafety, abi);
     let sig = ty::Binder::bind_with_vars(sig, bound_vars);
     equate_intrinsic_type(tcx, span, intrinsic_id, n_tps, n_lts, n_cts, sig)
 }
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 375fa1350b5..d56c3d3b6c1 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -2590,7 +2590,7 @@ pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
 #[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")]
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[cfg_attr(not(bootstrap), rustc_intrinsic)]
-pub(crate) const fn debug_assertions() -> bool {
+pub(crate) const unsafe fn debug_assertions() -> bool {
     cfg!(debug_assertions)
 }
 
diff --git a/tests/ui/feature-gates/feature-gate-abi.rs b/tests/ui/feature-gates/feature-gate-abi.rs
index 712655f9775..39f98ac908b 100644
--- a/tests/ui/feature-gates/feature-gate-abi.rs
+++ b/tests/ui/feature-gates/feature-gate-abi.rs
@@ -14,8 +14,10 @@ trait Tuple { }
 // Functions
 extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
                                    //~^ ERROR intrinsic must be in
+                                   //~| ERROR unrecognized intrinsic function: `f1`
 extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental
                                        //~^ ERROR intrinsic must be in
+                                       //~| ERROR unrecognized intrinsic function: `f2`
 extern "rust-call" fn f4(_: ()) {} //~ ERROR rust-call ABI is subject to change
 
 // Methods in trait definition
diff --git a/tests/ui/feature-gates/feature-gate-abi.stderr b/tests/ui/feature-gates/feature-gate-abi.stderr
index d031c2adf50..aa60434d9fe 100644
--- a/tests/ui/feature-gates/feature-gate-abi.stderr
+++ b/tests/ui/feature-gates/feature-gate-abi.stderr
@@ -8,7 +8,7 @@ LL | extern "rust-intrinsic" fn f1() {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:17:8
+  --> $DIR/feature-gate-abi.rs:18:8
    |
 LL | extern "platform-intrinsic" fn f2() {}
    |        ^^^^^^^^^^^^^^^^^^^^
@@ -18,7 +18,7 @@ LL | extern "platform-intrinsic" fn f2() {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:19:8
+  --> $DIR/feature-gate-abi.rs:21:8
    |
 LL | extern "rust-call" fn f4(_: ()) {}
    |        ^^^^^^^^^^^
@@ -28,7 +28,7 @@ LL | extern "rust-call" fn f4(_: ()) {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:23:12
+  --> $DIR/feature-gate-abi.rs:25:12
    |
 LL |     extern "rust-intrinsic" fn m1();
    |            ^^^^^^^^^^^^^^^^
@@ -37,7 +37,7 @@ LL |     extern "rust-intrinsic" fn m1();
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:25:12
+  --> $DIR/feature-gate-abi.rs:27:12
    |
 LL |     extern "platform-intrinsic" fn m2();
    |            ^^^^^^^^^^^^^^^^^^^^
@@ -47,7 +47,7 @@ LL |     extern "platform-intrinsic" fn m2();
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:27:12
+  --> $DIR/feature-gate-abi.rs:29:12
    |
 LL |     extern "rust-call" fn m4(_: ());
    |            ^^^^^^^^^^^
@@ -57,7 +57,7 @@ LL |     extern "rust-call" fn m4(_: ());
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:29:12
+  --> $DIR/feature-gate-abi.rs:31:12
    |
 LL |     extern "rust-call" fn dm4(_: ()) {}
    |            ^^^^^^^^^^^
@@ -67,7 +67,7 @@ LL |     extern "rust-call" fn dm4(_: ()) {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:36:12
+  --> $DIR/feature-gate-abi.rs:38:12
    |
 LL |     extern "rust-intrinsic" fn m1() {}
    |            ^^^^^^^^^^^^^^^^
@@ -76,7 +76,7 @@ LL |     extern "rust-intrinsic" fn m1() {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:38:12
+  --> $DIR/feature-gate-abi.rs:40:12
    |
 LL |     extern "platform-intrinsic" fn m2() {}
    |            ^^^^^^^^^^^^^^^^^^^^
@@ -86,7 +86,7 @@ LL |     extern "platform-intrinsic" fn m2() {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:40:12
+  --> $DIR/feature-gate-abi.rs:42:12
    |
 LL |     extern "rust-call" fn m4(_: ()) {}
    |            ^^^^^^^^^^^
@@ -96,7 +96,7 @@ LL |     extern "rust-call" fn m4(_: ()) {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:45:12
+  --> $DIR/feature-gate-abi.rs:47:12
    |
 LL |     extern "rust-intrinsic" fn im1() {}
    |            ^^^^^^^^^^^^^^^^
@@ -105,7 +105,7 @@ LL |     extern "rust-intrinsic" fn im1() {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:47:12
+  --> $DIR/feature-gate-abi.rs:49:12
    |
 LL |     extern "platform-intrinsic" fn im2() {}
    |            ^^^^^^^^^^^^^^^^^^^^
@@ -115,7 +115,7 @@ LL |     extern "platform-intrinsic" fn im2() {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:49:12
+  --> $DIR/feature-gate-abi.rs:51:12
    |
 LL |     extern "rust-call" fn im4(_: ()) {}
    |            ^^^^^^^^^^^
@@ -125,7 +125,7 @@ LL |     extern "rust-call" fn im4(_: ()) {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:53:18
+  --> $DIR/feature-gate-abi.rs:55:18
    |
 LL | type A1 = extern "rust-intrinsic" fn();
    |                  ^^^^^^^^^^^^^^^^
@@ -134,7 +134,7 @@ LL | type A1 = extern "rust-intrinsic" fn();
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:54:18
+  --> $DIR/feature-gate-abi.rs:56:18
    |
 LL | type A2 = extern "platform-intrinsic" fn();
    |                  ^^^^^^^^^^^^^^^^^^^^
@@ -144,7 +144,7 @@ LL | type A2 = extern "platform-intrinsic" fn();
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:55:18
+  --> $DIR/feature-gate-abi.rs:57:18
    |
 LL | type A4 = extern "rust-call" fn(_: ());
    |                  ^^^^^^^^^^^
@@ -154,7 +154,7 @@ LL | type A4 = extern "rust-call" fn(_: ());
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:58:8
+  --> $DIR/feature-gate-abi.rs:60:8
    |
 LL | extern "rust-intrinsic" {}
    |        ^^^^^^^^^^^^^^^^
@@ -163,7 +163,7 @@ LL | extern "rust-intrinsic" {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:59:8
+  --> $DIR/feature-gate-abi.rs:61:8
    |
 LL | extern "platform-intrinsic" {}
    |        ^^^^^^^^^^^^^^^^^^^^
@@ -173,7 +173,7 @@ LL | extern "platform-intrinsic" {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:60:8
+  --> $DIR/feature-gate-abi.rs:62:8
    |
 LL | extern "rust-call" {}
    |        ^^^^^^^^^^^
@@ -182,14 +182,26 @@ LL | extern "rust-call" {}
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
+error[E0093]: unrecognized intrinsic function: `f1`
+  --> $DIR/feature-gate-abi.rs:15:28
+   |
+LL | extern "rust-intrinsic" fn f1() {}
+   |                            ^^ unrecognized intrinsic
+
+error[E0093]: unrecognized intrinsic function: `f2`
+  --> $DIR/feature-gate-abi.rs:18:32
+   |
+LL | extern "platform-intrinsic" fn f2() {}
+   |                                ^^ unrecognized intrinsic
+
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:23:32
+  --> $DIR/feature-gate-abi.rs:25:32
    |
 LL |     extern "rust-intrinsic" fn m1();
    |                                ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:25:36
+  --> $DIR/feature-gate-abi.rs:27:36
    |
 LL |     extern "platform-intrinsic" fn m2();
    |                                    ^^
@@ -201,35 +213,36 @@ LL | extern "rust-intrinsic" fn f1() {}
    |                                 ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:17:37
+  --> $DIR/feature-gate-abi.rs:18:37
    |
 LL | extern "platform-intrinsic" fn f2() {}
    |                                     ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:36:37
+  --> $DIR/feature-gate-abi.rs:38:37
    |
 LL |     extern "rust-intrinsic" fn m1() {}
    |                                     ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:38:41
+  --> $DIR/feature-gate-abi.rs:40:41
    |
 LL |     extern "platform-intrinsic" fn m2() {}
    |                                         ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:45:38
+  --> $DIR/feature-gate-abi.rs:47:38
    |
 LL |     extern "rust-intrinsic" fn im1() {}
    |                                      ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:47:42
+  --> $DIR/feature-gate-abi.rs:49:42
    |
 LL |     extern "platform-intrinsic" fn im2() {}
    |                                          ^^
 
-error: aborting due to 27 previous errors
+error: aborting due to 29 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
+Some errors have detailed explanations: E0093, E0658.
+For more information about an error, try `rustc --explain E0093`.
diff --git a/tests/ui/feature-gates/feature-gate-intrinsics.rs b/tests/ui/feature-gates/feature-gate-intrinsics.rs
index e0dc3cc579d..725d968d24c 100644
--- a/tests/ui/feature-gates/feature-gate-intrinsics.rs
+++ b/tests/ui/feature-gates/feature-gate-intrinsics.rs
@@ -4,5 +4,6 @@ extern "rust-intrinsic" {   //~ ERROR intrinsics are subject to change
 
 extern "rust-intrinsic" fn baz() {} //~ ERROR intrinsics are subject to change
 //~^ ERROR intrinsic must be in
+//~| ERROR unrecognized intrinsic function: `baz`
 
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-intrinsics.stderr b/tests/ui/feature-gates/feature-gate-intrinsics.stderr
index ebd0f41715e..78c21843adb 100644
--- a/tests/ui/feature-gates/feature-gate-intrinsics.stderr
+++ b/tests/ui/feature-gates/feature-gate-intrinsics.stderr
@@ -22,13 +22,19 @@ error[E0093]: unrecognized intrinsic function: `bar`
 LL |     fn bar();
    |     ^^^^^^^^^ unrecognized intrinsic
 
+error[E0093]: unrecognized intrinsic function: `baz`
+  --> $DIR/feature-gate-intrinsics.rs:5:28
+   |
+LL | extern "rust-intrinsic" fn baz() {}
+   |                            ^^^ unrecognized intrinsic
+
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
   --> $DIR/feature-gate-intrinsics.rs:5:34
    |
 LL | extern "rust-intrinsic" fn baz() {}
    |                                  ^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0093, E0658.
 For more information about an error, try `rustc --explain E0093`.
diff --git a/tests/ui/intrinsics-always-extern.rs b/tests/ui/intrinsics-always-extern.rs
index 22951147d7d..0afd8353455 100644
--- a/tests/ui/intrinsics-always-extern.rs
+++ b/tests/ui/intrinsics-always-extern.rs
@@ -10,6 +10,7 @@ impl Foo for () {
 }
 
 extern "rust-intrinsic" fn hello() {//~ ERROR intrinsic must
+    //~^ ERROR unrecognized intrinsic function: `hello`
 }
 
 fn main() {
diff --git a/tests/ui/intrinsics-always-extern.stderr b/tests/ui/intrinsics-always-extern.stderr
index 24b6da16096..32468f99197 100644
--- a/tests/ui/intrinsics-always-extern.stderr
+++ b/tests/ui/intrinsics-always-extern.stderr
@@ -4,6 +4,12 @@ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
 LL |     extern "rust-intrinsic" fn foo(&self);
    |                                ^^^
 
+error[E0093]: unrecognized intrinsic function: `hello`
+  --> $DIR/intrinsics-always-extern.rs:12:28
+   |
+LL | extern "rust-intrinsic" fn hello() {
+   |                            ^^^^^ unrecognized intrinsic
+
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
   --> $DIR/intrinsics-always-extern.rs:8:43
    |
@@ -17,8 +23,10 @@ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
    |
 LL |   extern "rust-intrinsic" fn hello() {
    |  ____________________________________^
+LL | |
 LL | | }
    | |_^
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0093`.