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

@ -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(FnSig<'hir>, &'hir Generics<'hir>, 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.
@ -3819,7 +3827,7 @@ pub struct Impl<'hir> {
impl ItemKind<'_> {
pub fn generics(&self) -> Option<&Generics<'_>> {
Some(match *self {
ItemKind::Fn(_, ref generics, _)
ItemKind::Fn { ref generics, .. }
| ItemKind::TyAlias(_, ref generics)
| ItemKind::Const(_, ref generics, _)
| ItemKind::Enum(_, ref generics)
@ -3838,7 +3846,7 @@ impl ItemKind<'_> {
ItemKind::Use(..) => "`use` import",
ItemKind::Static(..) => "static item",
ItemKind::Const(..) => "constant item",
ItemKind::Fn(..) => "function",
ItemKind::Fn { .. } => "function",
ItemKind::Macro(..) => "macro",
ItemKind::Mod(..) => "module",
ItemKind::ForeignMod { .. } => "extern block",
@ -4004,7 +4012,7 @@ impl<'hir> OwnerNode<'hir> {
match self {
OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
| OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
| OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. })
| OwnerNode::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. })
| OwnerNode::ForeignItem(ForeignItem {
kind: ForeignItemKind::Fn(fn_sig, _, _), ..
}) => Some(fn_sig),
@ -4016,7 +4024,7 @@ impl<'hir> OwnerNode<'hir> {
match self {
OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
| OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
| OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. })
| OwnerNode::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. })
| OwnerNode::ForeignItem(ForeignItem {
kind: ForeignItemKind::Fn(fn_sig, _, _), ..
}) => Some(fn_sig.decl),
@ -4030,7 +4038,7 @@ impl<'hir> OwnerNode<'hir> {
kind:
ItemKind::Static(_, _, body)
| ItemKind::Const(_, _, body)
| ItemKind::Fn(_, _, body),
| ItemKind::Fn { body, .. },
..
})
| OwnerNode::TraitItem(TraitItem {
@ -4206,7 +4214,7 @@ impl<'hir> Node<'hir> {
match self {
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
| Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. })
| Node::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. })
| Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => {
Some(fn_sig.decl)
}
@ -4236,7 +4244,7 @@ impl<'hir> Node<'hir> {
match self {
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
| Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. })
| Node::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. })
| Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => {
Some(fn_sig)
}
@ -4281,7 +4289,7 @@ impl<'hir> Node<'hir> {
Node::Item(Item {
owner_id,
kind:
ItemKind::Const(_, _, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body),
ItemKind::Const(_, _, body) | ItemKind::Static(.., body) | ItemKind::Fn { body, .. },
..
})
| Node::TraitItem(TraitItem {
@ -4338,7 +4346,7 @@ impl<'hir> Node<'hir> {
pub fn fn_kind(self) -> Option<FnKind<'hir>> {
match self {
Node::Item(i) => match i.kind {
ItemKind::Fn(ref sig, ref generics, _) => {
ItemKind::Fn { sig, generics, .. } => {
Some(FnKind::ItemFn(i.ident, generics, sig.header))
}
_ => None,

View file

@ -509,7 +509,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
try_visit!(visitor.visit_generics(generics));
try_visit!(visitor.visit_nested_body(body));
}
ItemKind::Fn(ref sig, ref generics, body_id) => {
ItemKind::Fn { sig, generics, body: body_id, .. } => {
try_visit!(visitor.visit_id(item.hir_id()));
try_visit!(visitor.visit_fn(
FnKind::ItemFn(item.ident, generics, sig.header),

View file

@ -106,7 +106,7 @@ impl Target {
ItemKind::Use(..) => Target::Use,
ItemKind::Static { .. } => Target::Static,
ItemKind::Const(..) => Target::Const,
ItemKind::Fn(..) => Target::Fn,
ItemKind::Fn { .. } => Target::Fn,
ItemKind::Macro(..) => Target::MacroDef,
ItemKind::Mod(..) => Target::Mod,
ItemKind::ForeignMod { .. } => Target::ForeignMod,