about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs58
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/call.rs3
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs12
-rw-r--r--compiler/rustc_middle/src/ty/util.rs9
-rw-r--r--compiler/rustc_mir_build/src/builder/mod.rs14
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs3
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs18
-rw-r--r--src/tools/miri/src/bin/miri.rs2
-rw-r--r--tests/ui/consts/auxiliary/unstable_intrinsic.rs6
-rw-r--r--tests/ui/consts/const-unstable-intrinsic.rs13
-rw-r--r--tests/ui/consts/const-unstable-intrinsic.stderr4
-rw-r--r--tests/ui/intrinsics/not-overridden.rs3
-rw-r--r--tests/ui/intrinsics/not-overridden.stderr2
-rw-r--r--tests/ui/parser/fn-body-optional-semantic-fail.rs4
-rw-r--r--tests/ui/parser/fn-body-optional-semantic-fail.stderr18
-rw-r--r--tests/ui/target-feature/no-llvm-leaks.rs5
-rw-r--r--tests/ui/traits/const-traits/auxiliary/minicore.rs6
19 files changed, 118 insertions, 68 deletions
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 74a02eebd02..6fce9116938 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -222,6 +222,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         decl,
                         coroutine_kind,
                         body.as_deref(),
+                        attrs,
                     );
 
                     let itctx = ImplTraitContext::Universal;
@@ -233,7 +234,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         header: this.lower_fn_header(*header, hir::Safety::Safe),
                         span: this.lower_span(*fn_sig_span),
                     };
-                    hir::ItemKind::Fn { sig, generics, body: body_id }
+                    hir::ItemKind::Fn { sig, generics, body: body_id, has_body: body.is_some() }
                 })
             }
             ItemKind::Mod(_, mod_kind) => match mod_kind {
@@ -439,6 +440,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     sig: delegation_results.sig,
                     generics: delegation_results.generics,
                     body: delegation_results.body_id,
+                    has_body: true,
                 }
             }
             ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => {
@@ -747,7 +749,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
         let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
-        self.lower_attrs(hir_id, &i.attrs);
+        let attrs = self.lower_attrs(hir_id, &i.attrs);
         let trait_item_def_id = hir_id.expect_owner();
 
         let (generics, kind, has_default) = match &i.kind {
@@ -785,6 +787,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     &sig.decl,
                     sig.header.coroutine_kind,
                     Some(body),
+                    attrs,
                 );
                 let (generics, sig) = self.lower_method_sig(
                     generics,
@@ -877,7 +880,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let has_value = true;
         let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
         let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
-        self.lower_attrs(hir_id, &i.attrs);
+        let attrs = self.lower_attrs(hir_id, &i.attrs);
 
         let (generics, kind) = match &i.kind {
             AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
@@ -900,6 +903,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     &sig.decl,
                     sig.header.coroutine_kind,
                     body.as_deref(),
+                    attrs,
                 );
                 let (generics, sig) = self.lower_method_sig(
                     generics,
@@ -1054,20 +1058,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         })
     }
 
-    fn lower_fn_body_block(
-        &mut self,
-        span: Span,
-        decl: &FnDecl,
-        body: Option<&Block>,
-    ) -> hir::BodyId {
-        self.lower_fn_body(decl, |this| this.lower_block_expr_opt(span, body))
-    }
-
-    fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr<'hir> {
-        match block {
-            Some(block) => self.lower_block_expr(block),
-            None => self.expr_err(span, self.dcx().has_errors().unwrap()),
-        }
+    fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId {
+        self.lower_fn_body(decl, |this| this.lower_block_expr(body))
     }
 
     pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId {
@@ -1089,9 +1081,37 @@ impl<'hir> LoweringContext<'_, 'hir> {
         decl: &FnDecl,
         coroutine_kind: Option<CoroutineKind>,
         body: Option<&Block>,
+        attrs: &'hir [hir::Attribute],
     ) -> hir::BodyId {
-        let (Some(coroutine_kind), Some(body)) = (coroutine_kind, body) else {
-            return self.lower_fn_body_block(span, decl, body);
+        let Some(body) = body else {
+            // Functions without a body are an error, except if this is an intrinsic. For those we
+            // create a fake body so that the entire rest of the compiler doesn't have to deal with
+            // this as a special case.
+            return self.lower_fn_body(decl, |this| {
+                if attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic) {
+                    let empty_block = hir::Block {
+                        hir_id: this.next_id(),
+                        stmts: &[],
+                        expr: None,
+                        rules: hir::BlockCheckMode::DefaultBlock,
+                        span,
+                        targeted_by_break: false,
+                    };
+                    let loop_ = hir::ExprKind::Loop(
+                        this.arena.alloc(empty_block),
+                        None,
+                        hir::LoopSource::Loop,
+                        span,
+                    );
+                    hir::Expr { hir_id: this.next_id(), kind: loop_, span }
+                } else {
+                    this.expr_err(span, this.dcx().has_errors().unwrap())
+                }
+            });
+        };
+        let Some(coroutine_kind) = coroutine_kind else {
+            // Typical case: not a coroutine.
+            return self.lower_fn_body_block(decl, body);
         };
         self.lower_body(|this| {
             let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index d1cf9c53d66..236ca7ba703 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -920,7 +920,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             ItemKind::Fn(box Fn { defaultness, sig, generics, body }) => {
                 self.check_defaultness(item.span, *defaultness);
 
-                if body.is_none() {
+                let is_intrinsic =
+                    item.attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic);
+                if body.is_none() && !is_intrinsic {
                     self.dcx().emit_err(errors::FnWithoutBody {
                         span: item.span,
                         replace_span: self.ending_semi_or_hi(item.span),
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index 99f0ac702c5..e6a34193c9d 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -566,7 +566,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             | ty::InstanceKind::ThreadLocalShim(..)
             | ty::InstanceKind::AsyncDropGlueCtorShim(..)
             | ty::InstanceKind::Item(_) => {
-                // We need MIR for this fn
+                // We need MIR for this fn.
+                // Note that this can be an intrinsic, if we are executing its fallback body.
                 let Some((body, instance)) = M::find_mir_or_eval_fn(
                     self,
                     instance,
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 4112ae80980..489ef5e8fe7 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -1013,7 +1013,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
     gated!(
         rustc_intrinsic, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics,
-        "the `#[rustc_intrinsic]` attribute is used to declare intrinsics with function bodies",
+        "the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items",
     ),
     gated!(
         rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics,
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index c09f4e9fadc..114fc072c9e 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -3640,7 +3640,7 @@ impl<'hir> Item<'hir> {
             ItemKind::Const(ty, generics, body), (ty, generics, *body);
 
         expect_fn, (&FnSig<'hir>, &'hir Generics<'hir>, BodyId),
-            ItemKind::Fn { sig, generics, body }, (sig, generics, *body);
+            ItemKind::Fn { sig, generics, body, .. }, (sig, generics, *body);
 
         expect_macro, (&ast::MacroDef, MacroKind), ItemKind::Macro(def, mk), (def, *mk);
 
@@ -3768,7 +3768,15 @@ pub enum ItemKind<'hir> {
     /// A `const` item.
     Const(&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId),
     /// A function declaration.
-    Fn { sig: FnSig<'hir>, generics: &'hir Generics<'hir>, body: BodyId },
+    Fn {
+        sig: FnSig<'hir>,
+        generics: &'hir Generics<'hir>,
+        body: BodyId,
+        /// Whether this function actually has a body.
+        /// For functions without a body, `body` is synthesized (to avoid ICEs all over the
+        /// compiler), but that code should never be translated.
+        has_body: bool,
+    },
     /// A MBE macro definition (`macro_rules!` or `macro`).
     Macro(&'hir ast::MacroDef, MacroKind),
     /// A module.
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index ab8285f87d6..4272893df30 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1778,9 +1778,16 @@ pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Intrinsi
         && (matches!(tcx.fn_sig(def_id).skip_binder().abi(), ExternAbi::RustIntrinsic)
             || tcx.has_attr(def_id, sym::rustc_intrinsic))
     {
+        let must_be_overridden = tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden)
+            || match tcx.hir_node_by_def_id(def_id) {
+                hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { has_body, .. }, .. }) => {
+                    !has_body
+                }
+                _ => true,
+            };
         Some(ty::IntrinsicDef {
             name: tcx.item_name(def_id.into()),
-            must_be_overridden: tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden),
+            must_be_overridden,
             const_stable: tcx.has_attr(def_id, sym::rustc_intrinsic_const_stable_indirect),
         })
     } else {
diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs
index 0a60899248a..932b6fbe026 100644
--- a/compiler/rustc_mir_build/src/builder/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/mod.rs
@@ -1005,11 +1005,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         if let Some(source_scope) = scope {
             self.source_scope = source_scope;
         }
+
         if self.tcx.intrinsic(self.def_id).is_some_and(|i| i.must_be_overridden) {
             let source_info = self.source_info(rustc_span::DUMMY_SP);
             self.cfg.terminate(block, source_info, TerminatorKind::Unreachable);
             self.cfg.start_new_block().unit()
         } else {
+            // Ensure we don't silently codegen functions with fake bodies.
+            match self.tcx.hir_node(self.hir_id) {
+                hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Fn { has_body: false, .. },
+                    ..
+                }) => {
+                    self.tcx.dcx().span_delayed_bug(
+                        expr_span,
+                        format!("fn item without body has reached MIR building: {:?}", self.def_id),
+                    );
+                }
+                _ => {}
+            }
             self.expr_into_dest(Place::return_place(), block, expr_id)
         }
     }
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 35699acb318..339acbad6b9 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -190,7 +190,8 @@ impl<'tcx> Inliner<'tcx> {
 
         // Intrinsic fallback bodies are automatically made cross-crate inlineable,
         // but at this stage we don't know whether codegen knows the intrinsic,
-        // so just conservatively don't inline it.
+        // so just conservatively don't inline it. This also ensures that we do not
+        // accidentally inline the body of an intrinsic that *must* be overridden.
         if self.tcx.has_attr(callsite.callee.def_id(), sym::rustc_intrinsic) {
             return Err("Callee is an intrinsic, do not inline fallback bodies");
         }
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 05d34715314..00aae03704f 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -232,7 +232,7 @@ use rustc_middle::{bug, span_bug};
 use rustc_session::Limit;
 use rustc_session::config::EntryFnType;
 use rustc_span::source_map::{Spanned, dummy_spanned, respan};
-use rustc_span::{DUMMY_SP, Span, sym};
+use rustc_span::{DUMMY_SP, Span};
 use tracing::{debug, instrument, trace};
 
 use crate::errors::{self, EncounteredErrorWhileInstantiating, NoOptimizedMir, RecursionLimit};
@@ -894,9 +894,8 @@ fn visit_instance_use<'tcx>(
     if !tcx.should_codegen_locally(instance) {
         return;
     }
-    if let ty::InstanceKind::Intrinsic(def_id) = instance.def {
-        let name = tcx.item_name(def_id);
-        if let Some(_requirement) = ValidityRequirement::from_intrinsic(name) {
+    if let Some(intrinsic) = tcx.intrinsic(instance.def_id()) {
+        if let Some(_requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) {
             // The intrinsics assert_inhabited, assert_zero_valid, and assert_mem_uninitialized_valid will
             // be lowered in codegen to nothing or a call to panic_nounwind. So if we encounter any
             // of those intrinsics, we need to include a mono item for panic_nounwind, else we may try to
@@ -906,11 +905,12 @@ fn visit_instance_use<'tcx>(
             if tcx.should_codegen_locally(panic_instance) {
                 output.push(create_fn_mono_item(tcx, panic_instance, source));
             }
-        } else if tcx.has_attr(def_id, sym::rustc_intrinsic)
-            && !tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden)
-        {
-            // Codegen the fallback body of intrinsics with fallback bodies
-            let instance = ty::Instance::new(def_id, instance.args);
+        } else if !intrinsic.must_be_overridden {
+            // Codegen the fallback body of intrinsics with fallback bodies.
+            // We explicitly skip this otherwise to ensure we get a linker error
+            // if anyone tries to call this intrinsic and the codegen backend did not
+            // override the implementation.
+            let instance = ty::Instance::new(instance.def_id(), instance.args);
             if tcx.should_codegen_locally(instance) {
                 output.push(create_fn_mono_item(tcx, instance, source));
             }
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index 962e313ce33..9055aa30271 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -242,7 +242,7 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
                             let is_reachable_non_generic = matches!(
                                 tcx.hir_node_by_def_id(local_def_id),
                                 Node::Item(&hir::Item {
-                                    kind: hir::ItemKind::Static(..) | hir::ItemKind::Fn { .. },
+                                    kind: hir::ItemKind::Static(..) | hir::ItemKind::Fn{ .. },
                                     ..
                                 }) | Node::ImplItem(&hir::ImplItem {
                                     kind: hir::ImplItemKind::Fn(..),
diff --git a/tests/ui/consts/auxiliary/unstable_intrinsic.rs b/tests/ui/consts/auxiliary/unstable_intrinsic.rs
index 9e53a8feb5d..45631df7859 100644
--- a/tests/ui/consts/auxiliary/unstable_intrinsic.rs
+++ b/tests/ui/consts/auxiliary/unstable_intrinsic.rs
@@ -3,11 +3,9 @@
 
 #[unstable(feature = "unstable", issue = "42")]
 #[rustc_intrinsic]
-#[rustc_intrinsic_must_be_overridden]
-pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
+pub const unsafe fn size_of_val<T>(x: *const T) -> usize;
 
 #[unstable(feature = "unstable", issue = "42")]
 #[rustc_const_unstable(feature = "unstable", issue = "42")]
 #[rustc_intrinsic]
-#[rustc_intrinsic_must_be_overridden]
-pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
+pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize;
diff --git a/tests/ui/consts/const-unstable-intrinsic.rs b/tests/ui/consts/const-unstable-intrinsic.rs
index 8b38067e46e..890a30c73c8 100644
--- a/tests/ui/consts/const-unstable-intrinsic.rs
+++ b/tests/ui/consts/const-unstable-intrinsic.rs
@@ -2,7 +2,7 @@
 //! neither within a crate nor cross-crate.
 //@ aux-build:unstable_intrinsic.rs
 #![feature(staged_api, rustc_attrs, intrinsics)]
-#![stable(since="1.0.0", feature = "stable")]
+#![stable(since = "1.0.0", feature = "stable")]
 #![feature(local)]
 
 extern crate unstable_intrinsic;
@@ -30,14 +30,12 @@ const fn const_main() {
 
 #[unstable(feature = "local", issue = "42")]
 #[rustc_intrinsic]
-#[rustc_intrinsic_must_be_overridden]
-pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
+pub const unsafe fn size_of_val<T>(x: *const T) -> usize;
 
 #[unstable(feature = "local", issue = "42")]
 #[rustc_const_unstable(feature = "local", issue = "42")]
 #[rustc_intrinsic]
-#[rustc_intrinsic_must_be_overridden]
-pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
+pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
@@ -45,10 +43,7 @@ pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
 pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
     // Const stability attributes are not inherited from parent items.
     #[rustc_intrinsic]
-    #[rustc_intrinsic_must_be_overridden]
-    const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
-        unimplemented!()
-    }
+    const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize);
 
     unsafe { copy(src, dst, count) }
     //~^ ERROR cannot be (indirectly) exposed to stable
diff --git a/tests/ui/consts/const-unstable-intrinsic.stderr b/tests/ui/consts/const-unstable-intrinsic.stderr
index dfca04bef07..601c8647eee 100644
--- a/tests/ui/consts/const-unstable-intrinsic.stderr
+++ b/tests/ui/consts/const-unstable-intrinsic.stderr
@@ -69,7 +69,7 @@ LL | const fn const_main() {
    |
 
 error: intrinsic `copy::copy` cannot be (indirectly) exposed to stable
-  --> $DIR/const-unstable-intrinsic.rs:53:14
+  --> $DIR/const-unstable-intrinsic.rs:48:14
    |
 LL |     unsafe { copy(src, dst, count) }
    |              ^^^^^^^^^^^^^^^^^^^^^
@@ -77,7 +77,7 @@ LL |     unsafe { copy(src, dst, count) }
    = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_intrinsic_const_stable_indirect]` (but this requires team approval)
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
-  --> $DIR/const-unstable-intrinsic.rs:61:9
+  --> $DIR/const-unstable-intrinsic.rs:56:9
    |
 LL |         super::size_of_val(src);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/intrinsics/not-overridden.rs b/tests/ui/intrinsics/not-overridden.rs
index b57b4e5bc06..2359eee8b26 100644
--- a/tests/ui/intrinsics/not-overridden.rs
+++ b/tests/ui/intrinsics/not-overridden.rs
@@ -9,8 +9,7 @@
 //@ rustc-env:RUST_BACKTRACE=0
 
 #[rustc_intrinsic]
-#[rustc_intrinsic_must_be_overridden]
-pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {}
+pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize);
 
 fn main() {
     unsafe { const_deallocate(std::ptr::null_mut(), 0, 0) }
diff --git a/tests/ui/intrinsics/not-overridden.stderr b/tests/ui/intrinsics/not-overridden.stderr
index 9b8849cea1c..025a18fa4de 100644
--- a/tests/ui/intrinsics/not-overridden.stderr
+++ b/tests/ui/intrinsics/not-overridden.stderr
@@ -1,5 +1,5 @@
 error: must be overridden by codegen backend, but isn't
-  --> $DIR/not-overridden.rs:16:14
+  --> $DIR/not-overridden.rs:15:14
    |
 LL |     unsafe { const_deallocate(std::ptr::null_mut(), 0, 0) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/parser/fn-body-optional-semantic-fail.rs b/tests/ui/parser/fn-body-optional-semantic-fail.rs
index 12df488802e..46f5d7e96d1 100644
--- a/tests/ui/parser/fn-body-optional-semantic-fail.rs
+++ b/tests/ui/parser/fn-body-optional-semantic-fail.rs
@@ -1,7 +1,11 @@
 // Tests the different rules for `fn` forms requiring the presence or lack of a body.
+// Also ensures that functions without a body don't show other odd errors.
+
+trait Trait {}
 
 fn main() {
     fn f1(); //~ ERROR free function without a body
+    fn f1_rpit() -> impl Trait; //~ ERROR free function without a body
     fn f2() {} // OK.
 
     trait X {
diff --git a/tests/ui/parser/fn-body-optional-semantic-fail.stderr b/tests/ui/parser/fn-body-optional-semantic-fail.stderr
index 14bcd7c16fa..525a0a0f681 100644
--- a/tests/ui/parser/fn-body-optional-semantic-fail.stderr
+++ b/tests/ui/parser/fn-body-optional-semantic-fail.stderr
@@ -1,13 +1,21 @@
 error: free function without a body
-  --> $DIR/fn-body-optional-semantic-fail.rs:4:5
+  --> $DIR/fn-body-optional-semantic-fail.rs:7:5
    |
 LL |     fn f1();
    |     ^^^^^^^-
    |            |
    |            help: provide a definition for the function: `{ <body> }`
 
+error: free function without a body
+  --> $DIR/fn-body-optional-semantic-fail.rs:8:5
+   |
+LL |     fn f1_rpit() -> impl Trait;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                               |
+   |                               help: provide a definition for the function: `{ <body> }`
+
 error: associated function in `impl` without body
-  --> $DIR/fn-body-optional-semantic-fail.rs:14:9
+  --> $DIR/fn-body-optional-semantic-fail.rs:18:9
    |
 LL |         fn f1();
    |         ^^^^^^^-
@@ -15,7 +23,7 @@ LL |         fn f1();
    |                help: provide a definition for the function: `{ <body> }`
 
 error: associated function in `impl` without body
-  --> $DIR/fn-body-optional-semantic-fail.rs:19:9
+  --> $DIR/fn-body-optional-semantic-fail.rs:23:9
    |
 LL |         fn f3();
    |         ^^^^^^^-
@@ -23,7 +31,7 @@ LL |         fn f3();
    |                help: provide a definition for the function: `{ <body> }`
 
 error: incorrect function inside `extern` block
-  --> $DIR/fn-body-optional-semantic-fail.rs:25:12
+  --> $DIR/fn-body-optional-semantic-fail.rs:29:12
    |
 LL |     extern "C" {
    |     ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body
@@ -36,5 +44,5 @@ LL |         fn f6() {}
    = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
    = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
diff --git a/tests/ui/target-feature/no-llvm-leaks.rs b/tests/ui/target-feature/no-llvm-leaks.rs
index 10268686405..d4f70fe7069 100644
--- a/tests/ui/target-feature/no-llvm-leaks.rs
+++ b/tests/ui/target-feature/no-llvm-leaks.rs
@@ -19,10 +19,7 @@ impl Copy for bool {}
 #[stable(feature = "test", since = "1.0.0")]
 #[rustc_const_stable(feature = "test", since = "1.0.0")]
 #[rustc_intrinsic]
-#[rustc_intrinsic_must_be_overridden]
-const unsafe fn unreachable() -> ! {
-    loop {}
-}
+const unsafe fn unreachable() -> !;
 
 #[rustc_builtin_macro]
 macro_rules! cfg {
diff --git a/tests/ui/traits/const-traits/auxiliary/minicore.rs b/tests/ui/traits/const-traits/auxiliary/minicore.rs
index e606d896e93..08d7817548d 100644
--- a/tests/ui/traits/const-traits/auxiliary/minicore.rs
+++ b/tests/ui/traits/const-traits/auxiliary/minicore.rs
@@ -471,7 +471,6 @@ pub trait StructuralPartialEq {}
 
 pub const fn drop<T: ~const Destruct>(_: T) {}
 
-#[rustc_intrinsic_must_be_overridden]
 #[rustc_intrinsic]
 const fn const_eval_select<ARG: Tuple, F, G, RET>(
     arg: ARG,
@@ -480,7 +479,4 @@ const fn const_eval_select<ARG: Tuple, F, G, RET>(
 ) -> RET
 where
     F: const FnOnce<ARG, Output = RET>,
-    G: FnOnce<ARG, Output = RET>,
-{
-    loop {}
-}
+    G: FnOnce<ARG, Output = RET>;