1
Fork 0

rustc_intrinsic: support functions without body; they are implicitly marked as must-be-overridden

This commit is contained in:
Ralf Jung 2025-01-04 11:41:51 +01:00
parent be65012aa3
commit 3cd3649c6c
19 changed files with 118 additions and 68 deletions

View file

@ -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(