1
Fork 0

Auto merge of #135031 - RalfJung:intrinsics-without-body, r=oli-obk

rustc_intrinsic: support functions without body

We synthesize a HIR body `loop {}` but such bodyless intrinsics.

Most of the diff is due to turning `ItemKind::Fn` into a brace (named-field) enum variant, because it carries a `bool`-typed field now. This is to remember whether the function has a body. MIR building panics to avoid ever translating the fake `loop {}` body, and the intrinsic logic uses the lack of a body to implicitly mark that intrinsic as must-be-overridden.

I first tried actually having no body rather than generating the fake body, but there's a *lot* of code that assumes that all function items have HIR and MIR, so this didn't work very well. Then I noticed that even `rustc_intrinsic_must_be_overridden` intrinsics have MIR generated (they are filled with an `Unreachable` terminator) so I guess I am not the first to discover this. ;)

r? `@oli-obk`
This commit is contained in:
bors 2025-01-04 12:50:38 +00:00
commit fd127a3a84
81 changed files with 272 additions and 175 deletions

View file

@ -44,7 +44,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
return None;
}
match tcx.hir_node_by_def_id(def_id.expect_local()) {
Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) => {
Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. }) => {
generics.params.is_empty().not().then_some(generics.span)
}
_ => {
@ -58,7 +58,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
return None;
}
match tcx.hir_node_by_def_id(def_id.expect_local()) {
Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) => {
Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. }) => {
Some(generics.where_clause_span)
}
_ => {
@ -79,7 +79,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
return None;
}
match tcx.hir_node_by_def_id(def_id.expect_local()) {
Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. }) => {
Node::Item(hir::Item { kind: hir::ItemKind::Fn { sig: fn_sig, .. }, .. }) => {
Some(fn_sig.decl.output.span())
}
_ => {
@ -201,7 +201,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
match start_t.kind() {
ty::FnDef(..) => {
if let Node::Item(it) = tcx.hir_node(start_id) {
if let hir::ItemKind::Fn(sig, generics, _) = &it.kind {
if let hir::ItemKind::Fn { sig, generics, .. } = &it.kind {
let mut error = false;
if !generics.params.is_empty() {
tcx.dcx().emit_err(errors::StartFunctionParameters { span: generics.span });

View file

@ -26,7 +26,7 @@ fn equate_intrinsic_type<'tcx>(
sig: ty::PolyFnSig<'tcx>,
) {
let (generics, span) = match tcx.hir_node_by_def_id(def_id) {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. })
| hir::Node::ForeignItem(hir::ForeignItem {
kind: hir::ForeignItemKind::Fn(_, _, generics),
..

View file

@ -293,7 +293,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
}
res
}
hir::ItemKind::Fn(ref sig, ..) => {
hir::ItemKind::Fn { sig, .. } => {
check_item_fn(tcx, def_id, item.ident, item.span, sig.decl)
}
hir::ItemKind::Static(ty, ..) => {

View file

@ -795,7 +795,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
}
}
hir::ItemKind::Fn(..) => {
hir::ItemKind::Fn { .. } => {
tcx.ensure().generics_of(def_id);
tcx.ensure().type_of(def_id);
tcx.ensure().predicates_of(def_id);
@ -1325,7 +1325,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
generics,
..
})
| Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), .. }) => {
| Item(hir::Item { kind: ItemKind::Fn { sig, generics, .. }, .. }) => {
lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
}

View file

@ -969,7 +969,7 @@ pub(super) fn const_conditions<'tcx>(
{
Node::Item(item) => match item.kind {
hir::ItemKind::Impl(impl_) => (impl_.generics, None, false),
hir::ItemKind::Fn(_, generics, _) => (generics, None, false),
hir::ItemKind::Fn { generics, .. } => (generics, None, false),
hir::ItemKind::Trait(_, _, generics, supertraits, _) => {
(generics, Some((item.owner_id.def_id, supertraits)), false)
}

View file

@ -660,7 +660,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
_ => {}
}
match item.kind {
hir::ItemKind::Fn(_, generics, _) => {
hir::ItemKind::Fn { generics, .. } => {
self.visit_early_late(item.hir_id(), generics, |this| {
intravisit::walk_item(this, item);
});
@ -1379,7 +1379,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
} else if let Some(body_id) = outermost_body {
let fn_id = self.tcx.hir().body_owner(body_id);
match self.tcx.hir_node(fn_id) {
Node::Item(hir::Item { owner_id, kind: hir::ItemKind::Fn(..), .. })
Node::Item(hir::Item { owner_id, kind: hir::ItemKind::Fn { .. }, .. })
| Node::TraitItem(hir::TraitItem {
owner_id,
kind: hir::TraitItemKind::Fn(..),

View file

@ -294,7 +294,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
}
_ => icx.lower_ty(*self_ty),
},
ItemKind::Fn(..) => {
ItemKind::Fn { .. } => {
let args = ty::GenericArgs::identity_for_item(tcx, def_id);
Ty::new_fn_def(tcx, def_id.to_def_id(), args)
}

View file

@ -189,9 +189,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// 2. Functions inside trait blocks
// 3. Functions inside impl blocks
let (sig, generics) = match tcx.hir_node_by_def_id(parent_id) {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => {
(sig, generics)
}
hir::Node::Item(hir::Item {
kind: hir::ItemKind::Fn { sig, generics, .. }, ..
}) => (sig, generics),
hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(sig, _),
generics,