Skip to content

rustc_intrinsic: support functions without body #135031

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 44 additions & 24 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
decl,
coroutine_kind,
body.as_deref(),
attrs,
);

let itctx = ImplTraitContext::Universal;
Expand All @@ -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_id)
hir::ItemKind::Fn { sig, generics, body: body_id, has_body: body.is_some() }
})
}
ItemKind::Mod(_, mod_kind) => match mod_kind {
Expand Down Expand Up @@ -435,11 +436,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
ItemKind::Delegation(box delegation) => {
let delegation_results = self.lower_delegation(delegation, id);
hir::ItemKind::Fn(
delegation_results.sig,
delegation_results.generics,
delegation_results.body_id,
)
hir::ItemKind::Fn {
sig: delegation_results.sig,
generics: delegation_results.generics,
body: delegation_results.body_id,
has_body: true,
}
}
ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => {
panic!("macros should have been expanded by now")
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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(
Expand All @@ -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,
Expand Down Expand Up @@ -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 {
Expand All @@ -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(
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {

let arg = match hir.get_if_local(callee_def_id) {
Some(
hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. })
hir::Node::Item(hir::Item {
ident, kind: hir::ItemKind::Fn { sig, .. }, ..
})
| hir::Node::TraitItem(hir::TraitItem {
ident,
kind: hir::TraitItemKind::Fn(sig, _),
Expand Down Expand Up @@ -1020,7 +1022,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
// ...otherwise we are probably in the tail expression of the function, point at the
// return type.
match self.infcx.tcx.hir_node_by_def_id(hir.get_parent_item(fn_call_id).def_id) {
hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. })
hir::Node::Item(hir::Item {
ident, kind: hir::ItemKind::Fn { sig, .. }, ..
})
| hir::Node::TraitItem(hir::TraitItem {
ident,
kind: hir::TraitItemKind::Fn(sig, _),
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_const_eval/src/interpret/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
30 changes: 19 additions & 11 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand All @@ -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",
Expand Down Expand Up @@ -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),
Expand All @@ -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),
Expand All @@ -4030,7 +4038,7 @@ impl<'hir> OwnerNode<'hir> {
kind:
ItemKind::Static(_, _, body)
| ItemKind::Const(_, _, body)
| ItemKind::Fn(_, _, body),
| ItemKind::Fn { body, .. },
..
})
| OwnerNode::TraitItem(TraitItem {
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_hir_analysis/src/check/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
_ => {
Expand All @@ -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)
}
_ => {
Expand All @@ -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())
}
_ => {
Expand Down Expand Up @@ -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 });
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
..
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, ..) => {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,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);
Expand Down Expand Up @@ -1297,7 +1297,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)
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Loading
Loading