diff options
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>; |
