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

@ -222,6 +222,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
decl, decl,
coroutine_kind, coroutine_kind,
body.as_deref(), body.as_deref(),
attrs,
); );
let itctx = ImplTraitContext::Universal; let itctx = ImplTraitContext::Universal;
@ -233,7 +234,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
header: this.lower_fn_header(*header, hir::Safety::Safe), header: this.lower_fn_header(*header, hir::Safety::Safe),
span: this.lower_span(*fn_sig_span), 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 { ItemKind::Mod(_, mod_kind) => match mod_kind {
@ -435,11 +436,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
ItemKind::Delegation(box delegation) => { ItemKind::Delegation(box delegation) => {
let delegation_results = self.lower_delegation(delegation, id); let delegation_results = self.lower_delegation(delegation, id);
hir::ItemKind::Fn( hir::ItemKind::Fn {
delegation_results.sig, sig: delegation_results.sig,
delegation_results.generics, generics: delegation_results.generics,
delegation_results.body_id, body: delegation_results.body_id,
) has_body: true,
}
} }
ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => { ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => {
panic!("macros should have been expanded by now") panic!("macros should have been expanded by now")
@ -747,7 +749,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'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); 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 trait_item_def_id = hir_id.expect_owner();
let (generics, kind, has_default) = match &i.kind { let (generics, kind, has_default) = match &i.kind {
@ -785,6 +787,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&sig.decl, &sig.decl,
sig.header.coroutine_kind, sig.header.coroutine_kind,
Some(body), Some(body),
attrs,
); );
let (generics, sig) = self.lower_method_sig( let (generics, sig) = self.lower_method_sig(
generics, generics,
@ -877,7 +880,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let has_value = true; let has_value = true;
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); 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 { let (generics, kind) = match &i.kind {
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics( AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
@ -900,6 +903,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&sig.decl, &sig.decl,
sig.header.coroutine_kind, sig.header.coroutine_kind,
body.as_deref(), body.as_deref(),
attrs,
); );
let (generics, sig) = self.lower_method_sig( let (generics, sig) = self.lower_method_sig(
generics, generics,
@ -1054,20 +1058,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
}) })
} }
fn lower_fn_body_block( fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId {
&mut self, self.lower_fn_body(decl, |this| this.lower_block_expr(body))
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()),
}
} }
pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId { 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, decl: &FnDecl,
coroutine_kind: Option<CoroutineKind>, coroutine_kind: Option<CoroutineKind>,
body: Option<&Block>, body: Option<&Block>,
attrs: &'hir [hir::Attribute],
) -> hir::BodyId { ) -> hir::BodyId {
let (Some(coroutine_kind), Some(body)) = (coroutine_kind, body) else { let Some(body) = body else {
return self.lower_fn_body_block(span, decl, body); // 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| { self.lower_body(|this| {
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(

View File

@ -920,7 +920,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
ItemKind::Fn(box Fn { defaultness, sig, generics, body }) => { ItemKind::Fn(box Fn { defaultness, sig, generics, body }) => {
self.check_defaultness(item.span, *defaultness); 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 { self.dcx().emit_err(errors::FnWithoutBody {
span: item.span, span: item.span,
replace_span: self.ending_semi_or_hi(item.span), replace_span: self.ending_semi_or_hi(item.span),

View File

@ -981,7 +981,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let arg = match hir.get_if_local(callee_def_id) { let arg = match hir.get_if_local(callee_def_id) {
Some( 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 { | hir::Node::TraitItem(hir::TraitItem {
ident, ident,
kind: hir::TraitItemKind::Fn(sig, _), kind: hir::TraitItemKind::Fn(sig, _),
@ -1020,7 +1022,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
// ...otherwise we are probably in the tail expression of the function, point at the // ...otherwise we are probably in the tail expression of the function, point at the
// return type. // return type.
match self.infcx.tcx.hir_node_by_def_id(hir.get_parent_item(fn_call_id).def_id) { 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 { | hir::Node::TraitItem(hir::TraitItem {
ident, ident,
kind: hir::TraitItemKind::Fn(sig, _), kind: hir::TraitItemKind::Fn(sig, _),

View File

@ -566,7 +566,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
| ty::InstanceKind::ThreadLocalShim(..) | ty::InstanceKind::ThreadLocalShim(..)
| ty::InstanceKind::AsyncDropGlueCtorShim(..) | ty::InstanceKind::AsyncDropGlueCtorShim(..)
| ty::InstanceKind::Item(_) => { | 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( let Some((body, instance)) = M::find_mir_or_eval_fn(
self, self,
instance, instance,

View File

@ -1013,7 +1013,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
), ),
gated!( gated!(
rustc_intrinsic, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics, 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!( gated!(
rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics, rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics,

View File

@ -3640,7 +3640,7 @@ impl<'hir> Item<'hir> {
ItemKind::Const(ty, generics, body), (ty, generics, *body); ItemKind::Const(ty, generics, body), (ty, generics, *body);
expect_fn, (&FnSig<'hir>, &'hir Generics<'hir>, BodyId), 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); expect_macro, (&ast::MacroDef, MacroKind), ItemKind::Macro(def, mk), (def, *mk);
@ -3768,7 +3768,15 @@ pub enum ItemKind<'hir> {
/// A `const` item. /// A `const` item.
Const(&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId), Const(&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId),
/// A function declaration. /// 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`). /// A MBE macro definition (`macro_rules!` or `macro`).
Macro(&'hir ast::MacroDef, MacroKind), Macro(&'hir ast::MacroDef, MacroKind),
/// A module. /// A module.
@ -3819,7 +3827,7 @@ pub struct Impl<'hir> {
impl ItemKind<'_> { impl ItemKind<'_> {
pub fn generics(&self) -> Option<&Generics<'_>> { pub fn generics(&self) -> Option<&Generics<'_>> {
Some(match *self { Some(match *self {
ItemKind::Fn(_, ref generics, _) ItemKind::Fn { ref generics, .. }
| ItemKind::TyAlias(_, ref generics) | ItemKind::TyAlias(_, ref generics)
| ItemKind::Const(_, ref generics, _) | ItemKind::Const(_, ref generics, _)
| ItemKind::Enum(_, ref generics) | ItemKind::Enum(_, ref generics)
@ -3838,7 +3846,7 @@ impl ItemKind<'_> {
ItemKind::Use(..) => "`use` import", ItemKind::Use(..) => "`use` import",
ItemKind::Static(..) => "static item", ItemKind::Static(..) => "static item",
ItemKind::Const(..) => "constant item", ItemKind::Const(..) => "constant item",
ItemKind::Fn(..) => "function", ItemKind::Fn { .. } => "function",
ItemKind::Macro(..) => "macro", ItemKind::Macro(..) => "macro",
ItemKind::Mod(..) => "module", ItemKind::Mod(..) => "module",
ItemKind::ForeignMod { .. } => "extern block", ItemKind::ForeignMod { .. } => "extern block",
@ -4004,7 +4012,7 @@ impl<'hir> OwnerNode<'hir> {
match self { match self {
OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
| OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::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 { | OwnerNode::ForeignItem(ForeignItem {
kind: ForeignItemKind::Fn(fn_sig, _, _), .. kind: ForeignItemKind::Fn(fn_sig, _, _), ..
}) => Some(fn_sig), }) => Some(fn_sig),
@ -4016,7 +4024,7 @@ impl<'hir> OwnerNode<'hir> {
match self { match self {
OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
| OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::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 { | OwnerNode::ForeignItem(ForeignItem {
kind: ForeignItemKind::Fn(fn_sig, _, _), .. kind: ForeignItemKind::Fn(fn_sig, _, _), ..
}) => Some(fn_sig.decl), }) => Some(fn_sig.decl),
@ -4030,7 +4038,7 @@ impl<'hir> OwnerNode<'hir> {
kind: kind:
ItemKind::Static(_, _, body) ItemKind::Static(_, _, body)
| ItemKind::Const(_, _, body) | ItemKind::Const(_, _, body)
| ItemKind::Fn(_, _, body), | ItemKind::Fn { body, .. },
.. ..
}) })
| OwnerNode::TraitItem(TraitItem { | OwnerNode::TraitItem(TraitItem {
@ -4206,7 +4214,7 @@ impl<'hir> Node<'hir> {
match self { match self {
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
| Node::ImplItem(ImplItem { kind: ImplItemKind::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, _, _), .. }) => { | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => {
Some(fn_sig.decl) Some(fn_sig.decl)
} }
@ -4236,7 +4244,7 @@ impl<'hir> Node<'hir> {
match self { match self {
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
| Node::ImplItem(ImplItem { kind: ImplItemKind::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, _, _), .. }) => { | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => {
Some(fn_sig) Some(fn_sig)
} }
@ -4281,7 +4289,7 @@ impl<'hir> Node<'hir> {
Node::Item(Item { Node::Item(Item {
owner_id, owner_id,
kind: kind:
ItemKind::Const(_, _, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body), ItemKind::Const(_, _, body) | ItemKind::Static(.., body) | ItemKind::Fn { body, .. },
.. ..
}) })
| Node::TraitItem(TraitItem { | Node::TraitItem(TraitItem {
@ -4338,7 +4346,7 @@ impl<'hir> Node<'hir> {
pub fn fn_kind(self) -> Option<FnKind<'hir>> { pub fn fn_kind(self) -> Option<FnKind<'hir>> {
match self { match self {
Node::Item(i) => match i.kind { Node::Item(i) => match i.kind {
ItemKind::Fn(ref sig, ref generics, _) => { ItemKind::Fn { sig, generics, .. } => {
Some(FnKind::ItemFn(i.ident, generics, sig.header)) Some(FnKind::ItemFn(i.ident, generics, sig.header))
} }
_ => None, _ => 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_generics(generics));
try_visit!(visitor.visit_nested_body(body)); 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_id(item.hir_id()));
try_visit!(visitor.visit_fn( try_visit!(visitor.visit_fn(
FnKind::ItemFn(item.ident, generics, sig.header), FnKind::ItemFn(item.ident, generics, sig.header),

View File

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

View File

@ -44,7 +44,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
return None; return None;
} }
match tcx.hir_node_by_def_id(def_id.expect_local()) { 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) 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; return None;
} }
match tcx.hir_node_by_def_id(def_id.expect_local()) { 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) Some(generics.where_clause_span)
} }
_ => { _ => {
@ -79,7 +79,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
return None; return None;
} }
match tcx.hir_node_by_def_id(def_id.expect_local()) { 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()) 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() { match start_t.kind() {
ty::FnDef(..) => { ty::FnDef(..) => {
if let Node::Item(it) = tcx.hir_node(start_id) { 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; let mut error = false;
if !generics.params.is_empty() { if !generics.params.is_empty() {
tcx.dcx().emit_err(errors::StartFunctionParameters { span: generics.span }); tcx.dcx().emit_err(errors::StartFunctionParameters { span: generics.span });

View File

@ -26,7 +26,7 @@ fn equate_intrinsic_type<'tcx>(
sig: ty::PolyFnSig<'tcx>, sig: ty::PolyFnSig<'tcx>,
) { ) {
let (generics, span) = match tcx.hir_node_by_def_id(def_id) { 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 { | hir::Node::ForeignItem(hir::ForeignItem {
kind: hir::ForeignItemKind::Fn(_, _, generics), 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 res
} }
hir::ItemKind::Fn(ref sig, ..) => { hir::ItemKind::Fn { sig, .. } => {
check_item_fn(tcx, def_id, item.ident, item.span, sig.decl) check_item_fn(tcx, def_id, item.ident, item.span, sig.decl)
} }
hir::ItemKind::Static(ty, ..) => { 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().generics_of(def_id);
tcx.ensure().type_of(def_id); tcx.ensure().type_of(def_id);
tcx.ensure().predicates_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, 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) 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 { Node::Item(item) => match item.kind {
hir::ItemKind::Impl(impl_) => (impl_.generics, None, false), 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, _) => { hir::ItemKind::Trait(_, _, generics, supertraits, _) => {
(generics, Some((item.owner_id.def_id, supertraits)), false) (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 { match item.kind {
hir::ItemKind::Fn(_, generics, _) => { hir::ItemKind::Fn { generics, .. } => {
self.visit_early_late(item.hir_id(), generics, |this| { self.visit_early_late(item.hir_id(), generics, |this| {
intravisit::walk_item(this, item); intravisit::walk_item(this, item);
}); });
@ -1379,7 +1379,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
} else if let Some(body_id) = outermost_body { } else if let Some(body_id) = outermost_body {
let fn_id = self.tcx.hir().body_owner(body_id); let fn_id = self.tcx.hir().body_owner(body_id);
match self.tcx.hir_node(fn_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 { | Node::TraitItem(hir::TraitItem {
owner_id, owner_id,
kind: hir::TraitItemKind::Fn(..), 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), _ => icx.lower_ty(*self_ty),
}, },
ItemKind::Fn(..) => { ItemKind::Fn { .. } => {
let args = ty::GenericArgs::identity_for_item(tcx, def_id); let args = ty::GenericArgs::identity_for_item(tcx, def_id);
Ty::new_fn_def(tcx, def_id.to_def_id(), args) 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 // 2. Functions inside trait blocks
// 3. Functions inside impl blocks // 3. Functions inside impl blocks
let (sig, generics) = match tcx.hir_node_by_def_id(parent_id) { let (sig, generics) = match tcx.hir_node_by_def_id(parent_id) {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => { hir::Node::Item(hir::Item {
(sig, generics) kind: hir::ItemKind::Fn { sig, generics, .. }, ..
} }) => (sig, generics),
hir::Node::TraitItem(hir::TraitItem { hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(sig, _), kind: hir::TraitItemKind::Fn(sig, _),
generics, generics,

View File

@ -634,7 +634,7 @@ impl<'a> State<'a> {
self.word(";"); self.word(";");
self.end(); // end the outer cbox self.end(); // end the outer cbox
} }
hir::ItemKind::Fn(ref sig, generics, body) => { hir::ItemKind::Fn { sig, generics, body, .. } => {
self.head(""); self.head("");
self.print_fn( self.print_fn(
sig.decl, sig.decl,

View File

@ -391,7 +391,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let hir::Node::Block(block) = node { if let hir::Node::Block(block) = node {
// check that the body's parent is an fn // check that the body's parent is an fn
let parent = self.tcx.parent_hir_node(self.tcx.parent_hir_id(block.hir_id)); let parent = self.tcx.parent_hir_node(self.tcx.parent_hir_id(block.hir_id));
if let (Some(expr), hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. })) = if let (Some(expr), hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { .. }, .. })) =
(&block.expr, parent) (&block.expr, parent)
{ {
// check that the `if` expr without `else` is the fn body's expr // check that the `if` expr without `else` is the fn body's expr

View File

@ -705,7 +705,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for id in self.tcx.hir().items() { for id in self.tcx.hir().items() {
if let Some(node) = self.tcx.hir().get_if_local(id.owner_id.into()) if let Some(node) = self.tcx.hir().get_if_local(id.owner_id.into())
&& let hir::Node::Item(item) = node && let hir::Node::Item(item) = node
&& let hir::ItemKind::Fn(..) = item.kind && let hir::ItemKind::Fn { .. } = item.kind
&& item.ident.name == segment.ident.name && item.ident.name == segment.ident.name
{ {
err.span_label( err.span_label(

View File

@ -1127,7 +1127,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let encl_item_id = self.tcx.hir().get_parent_item(expr.hir_id); let encl_item_id = self.tcx.hir().get_parent_item(expr.hir_id);
if let hir::Node::Item(hir::Item { if let hir::Node::Item(hir::Item {
kind: hir::ItemKind::Fn(..), span: encl_fn_span, .. kind: hir::ItemKind::Fn { .. },
span: encl_fn_span,
..
}) })
| hir::Node::TraitItem(hir::TraitItem { | hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)), kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),

View File

@ -891,7 +891,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.hir().get_fn_id_for_return_block(blk_id).and_then(|item_id| { self.tcx.hir().get_fn_id_for_return_block(blk_id).and_then(|item_id| {
match self.tcx.hir_node(item_id) { match self.tcx.hir_node(item_id) {
Node::Item(&hir::Item { Node::Item(&hir::Item {
kind: hir::ItemKind::Fn(ref sig, ..), owner_id, .. kind: hir::ItemKind::Fn { sig, .. }, owner_id, ..
}) => Some((owner_id.def_id, sig.decl)), }) => Some((owner_id.def_id, sig.decl)),
Node::TraitItem(&hir::TraitItem { Node::TraitItem(&hir::TraitItem {
kind: hir::TraitItemKind::Fn(ref sig, ..), kind: hir::TraitItemKind::Fn(ref sig, ..),
@ -920,7 +920,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
)) => { )) => {
let (sig, owner_id) = match self.tcx.parent_hir_node(hir_id) { let (sig, owner_id) = match self.tcx.parent_hir_node(hir_id) {
Node::Item(&hir::Item { Node::Item(&hir::Item {
kind: hir::ItemKind::Fn(ref sig, ..), kind: hir::ItemKind::Fn { ref sig, .. },
owner_id, owner_id,
.. ..
}) => (sig, owner_id), }) => (sig, owner_id),

View File

@ -2041,7 +2041,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn parent_item_span(&self, id: HirId) -> Option<Span> { fn parent_item_span(&self, id: HirId) -> Option<Span> {
let node = self.tcx.hir_node_by_def_id(self.tcx.hir().get_parent_item(id).def_id); let node = self.tcx.hir_node_by_def_id(self.tcx.hir().get_parent_item(id).def_id);
match node { match node {
Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) Node::Item(&hir::Item { kind: hir::ItemKind::Fn { body: body_id, .. }, .. })
| Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => { | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
let body = self.tcx.hir().body(body_id); let body = self.tcx.hir().body(body_id);
if let ExprKind::Block(block, _) = &body.value.kind { if let ExprKind::Block(block, _) = &body.value.kind {
@ -2189,7 +2189,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
} }
hir::Node::Item(item) => { hir::Node::Item(item) => {
if let hir::ItemKind::Fn(..) = item.kind { if let hir::ItemKind::Fn { .. } = item.kind {
break; break;
} }
} }

View File

@ -981,14 +981,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let hir::Node::Item(hir::Item { let hir::Node::Item(hir::Item {
kind: kind:
hir::ItemKind::Fn( hir::ItemKind::Fn {
hir::FnSig { sig:
decl: hir::FnDecl { inputs: fn_parameters, output: fn_return, .. }, hir::FnSig {
.. decl: hir::FnDecl { inputs: fn_parameters, output: fn_return, .. },
}, ..
hir::Generics { params, predicates, .. }, },
_body_id, generics: hir::Generics { params, predicates, .. },
), ..
},
.. ..
}) = fn_node }) = fn_node
else { else {

View File

@ -1935,7 +1935,7 @@ fn drop_location_span(tcx: TyCtxt<'_>, hir_id: HirId) -> Span {
let owner_node = tcx.hir_node(owner_id); let owner_node = tcx.hir_node(owner_id);
let owner_span = match owner_node { let owner_span = match owner_node {
hir::Node::Item(item) => match item.kind { hir::Node::Item(item) => match item.kind {
hir::ItemKind::Fn(_, _, owner_id) => tcx.hir().span(owner_id.hir_id), hir::ItemKind::Fn { body: owner_id, .. } => tcx.hir().span(owner_id.hir_id),
_ => { _ => {
bug!("Drop location span error: need to handle more ItemKind '{:?}'", item.kind); bug!("Drop location span error: need to handle more ItemKind '{:?}'", item.kind);
} }

View File

@ -253,7 +253,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
HirItem::Const(..) => ("ItemConst", LABELS_CONST), HirItem::Const(..) => ("ItemConst", LABELS_CONST),
// A function declaration // A function declaration
HirItem::Fn(..) => ("ItemFn", LABELS_FN), HirItem::Fn { .. } => ("ItemFn", LABELS_FN),
// // A module // // A module
HirItem::Mod(..) => ("ItemMod", LABELS_HIR_ONLY), HirItem::Mod(..) => ("ItemMod", LABELS_HIR_ONLY),

View File

@ -1030,7 +1030,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
} }
}; };
match it.kind { match it.kind {
hir::ItemKind::Fn(.., generics, _) => { hir::ItemKind::Fn { generics, .. } => {
if let Some(no_mangle_attr) = attr::find_by_name(attrs, sym::no_mangle) { if let Some(no_mangle_attr) = attr::find_by_name(attrs, sym::no_mangle) {
check_no_mangle_on_generic_fn(no_mangle_attr, None, generics, it.span); check_no_mangle_on_generic_fn(no_mangle_attr, None, generics, it.span);
} }

View File

@ -112,7 +112,7 @@ declare_lint_pass!(
impl<'tcx> LateLintPass<'tcx> for ImplTraitOvercaptures { impl<'tcx> LateLintPass<'tcx> for ImplTraitOvercaptures {
fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'tcx>) { fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'tcx>) {
match &it.kind { match &it.kind {
hir::ItemKind::Fn(..) => check_fn(cx.tcx, it.owner_id.def_id), hir::ItemKind::Fn { .. } => check_fn(cx.tcx, it.owner_id.def_id),
_ => {} _ => {}
} }
} }

View File

@ -1561,7 +1561,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions {
); );
} }
// See `check_fn`.. // See `check_fn`..
hir::ItemKind::Fn(..) => {} hir::ItemKind::Fn { .. } => {}
// See `check_field_def`.. // See `check_field_def`..
hir::ItemKind::Union(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) => {} hir::ItemKind::Union(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) => {}
// Doesn't define something that can contain a external type to be checked. // Doesn't define something that can contain a external type to be checked.

View File

@ -634,7 +634,7 @@ impl<'hir> Map<'hir> {
for (hir_id, node) in self.parent_iter(hir_id) { for (hir_id, node) in self.parent_iter(hir_id) {
if let Node::Item(Item { if let Node::Item(Item {
kind: kind:
ItemKind::Fn(..) ItemKind::Fn { .. }
| ItemKind::Const(..) | ItemKind::Const(..)
| ItemKind::Static(..) | ItemKind::Static(..)
| ItemKind::Mod(..) | ItemKind::Mod(..)
@ -823,7 +823,7 @@ impl<'hir> Map<'hir> {
let span = match self.tcx.hir_node(hir_id) { let span = match self.tcx.hir_node(hir_id) {
// Function-like. // Function-like.
Node::Item(Item { kind: ItemKind::Fn(sig, ..), span: outer_span, .. }) Node::Item(Item { kind: ItemKind::Fn { sig, .. }, span: outer_span, .. })
| Node::TraitItem(TraitItem { | Node::TraitItem(TraitItem {
kind: TraitItemKind::Fn(sig, ..), kind: TraitItemKind::Fn(sig, ..),
span: outer_span, span: outer_span,
@ -1149,7 +1149,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
ItemKind::Use(..) => "use", ItemKind::Use(..) => "use",
ItemKind::Static(..) => "static", ItemKind::Static(..) => "static",
ItemKind::Const(..) => "const", ItemKind::Const(..) => "const",
ItemKind::Fn(..) => "fn", ItemKind::Fn { .. } => "fn",
ItemKind::Macro(..) => "macro", ItemKind::Macro(..) => "macro",
ItemKind::Mod(..) => "mod", ItemKind::Mod(..) => "mod",
ItemKind::ForeignMod { .. } => "foreign mod", ItemKind::ForeignMod { .. } => "foreign mod",

View File

@ -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) && (matches!(tcx.fn_sig(def_id).skip_binder().abi(), ExternAbi::RustIntrinsic)
|| tcx.has_attr(def_id, sym::rustc_intrinsic)) || 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 { Some(ty::IntrinsicDef {
name: tcx.item_name(def_id.into()), 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), const_stable: tcx.has_attr(def_id, sym::rustc_intrinsic_const_stable_indirect),
}) })
} else { } else {

View File

@ -1005,11 +1005,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
if let Some(source_scope) = scope { if let Some(source_scope) = scope {
self.source_scope = source_scope; self.source_scope = source_scope;
} }
if self.tcx.intrinsic(self.def_id).is_some_and(|i| i.must_be_overridden) { 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); let source_info = self.source_info(rustc_span::DUMMY_SP);
self.cfg.terminate(block, source_info, TerminatorKind::Unreachable); self.cfg.terminate(block, source_info, TerminatorKind::Unreachable);
self.cfg.start_new_block().unit() self.cfg.start_new_block().unit()
} else { } 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) self.expr_into_dest(Place::return_place(), block, expr_id)
} }
} }

View File

@ -190,7 +190,8 @@ impl<'tcx> Inliner<'tcx> {
// Intrinsic fallback bodies are automatically made cross-crate inlineable, // Intrinsic fallback bodies are automatically made cross-crate inlineable,
// but at this stage we don't know whether codegen knows the intrinsic, // 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) { if self.tcx.has_attr(callsite.callee.def_id(), sym::rustc_intrinsic) {
return Err("Callee is an intrinsic, do not inline fallback bodies"); return Err("Callee is an intrinsic, do not inline fallback bodies");
} }

View File

@ -232,7 +232,7 @@ use rustc_middle::{bug, span_bug};
use rustc_session::Limit; use rustc_session::Limit;
use rustc_session::config::EntryFnType; use rustc_session::config::EntryFnType;
use rustc_span::source_map::{Spanned, dummy_spanned, respan}; 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 tracing::{debug, instrument, trace};
use crate::errors::{self, EncounteredErrorWhileInstantiating, NoOptimizedMir, RecursionLimit}; use crate::errors::{self, EncounteredErrorWhileInstantiating, NoOptimizedMir, RecursionLimit};
@ -894,9 +894,8 @@ fn visit_instance_use<'tcx>(
if !tcx.should_codegen_locally(instance) { if !tcx.should_codegen_locally(instance) {
return; return;
} }
if let ty::InstanceKind::Intrinsic(def_id) = instance.def { if let Some(intrinsic) = tcx.intrinsic(instance.def_id()) {
let name = tcx.item_name(def_id); if let Some(_requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) {
if let Some(_requirement) = ValidityRequirement::from_intrinsic(name) {
// The intrinsics assert_inhabited, assert_zero_valid, and assert_mem_uninitialized_valid will // 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 // 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 // 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) { if tcx.should_codegen_locally(panic_instance) {
output.push(create_fn_mono_item(tcx, panic_instance, source)); output.push(create_fn_mono_item(tcx, panic_instance, source));
} }
} else if tcx.has_attr(def_id, sym::rustc_intrinsic) } else if !intrinsic.must_be_overridden {
&& !tcx.has_attr(def_id, sym::rustc_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
// Codegen the fallback body of intrinsics with fallback bodies // if anyone tries to call this intrinsic and the codegen backend did not
let instance = ty::Instance::new(def_id, instance.args); // override the implementation.
let instance = ty::Instance::new(instance.def_id(), instance.args);
if tcx.should_codegen_locally(instance) { if tcx.should_codegen_locally(instance) {
output.push(create_fn_mono_item(tcx, instance, source)); output.push(create_fn_mono_item(tcx, instance, source));
} }

View File

@ -1646,7 +1646,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}; };
let Some(ItemLike::Item(Item { let Some(ItemLike::Item(Item {
kind: ItemKind::Fn(FnSig { decl, .. }, generics, _), .. kind: ItemKind::Fn { sig: FnSig { decl, .. }, generics, .. },
..
})) = item })) = item
else { else {
bug!("should be a function item"); bug!("should be a function item");

View File

@ -30,7 +30,10 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
} }
let (fn_header, body_id) = match tcx.hir_node_by_def_id(def_id) { let (fn_header, body_id) = match tcx.hir_node_by_def_id(def_id) {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) hir::Node::Item(hir::Item {
kind: hir::ItemKind::Fn { sig, body: body_id, .. },
..
})
| hir::Node::TraitItem(hir::TraitItem { | hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), kind: hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)),
.. ..

View File

@ -141,7 +141,7 @@ impl<'tcx> ReachableContext<'tcx> {
match self.tcx.hir_node_by_def_id(def_id) { match self.tcx.hir_node_by_def_id(def_id) {
Node::Item(item) => match item.kind { Node::Item(item) => match item.kind {
hir::ItemKind::Fn(..) => recursively_reachable(self.tcx, def_id.into()), hir::ItemKind::Fn { .. } => recursively_reachable(self.tcx, def_id.into()),
_ => false, _ => false,
}, },
Node::TraitItem(trait_method) => match trait_method.kind { Node::TraitItem(trait_method) => match trait_method.kind {
@ -200,7 +200,7 @@ impl<'tcx> ReachableContext<'tcx> {
match *node { match *node {
Node::Item(item) => { Node::Item(item) => {
match item.kind { match item.kind {
hir::ItemKind::Fn(.., body) => { hir::ItemKind::Fn { body, .. } => {
if recursively_reachable(self.tcx, item.owner_id.into()) { if recursively_reachable(self.tcx, item.owner_id.into()) {
self.visit_nested_body(body); self.visit_nested_body(body);
} }

View File

@ -428,7 +428,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
) )
} }
} }
hir::ItemKind::Fn(ref item_fn_sig, _, _) => { hir::ItemKind::Fn { sig: ref item_fn_sig, .. } => {
fn_sig = Some(item_fn_sig); fn_sig = Some(item_fn_sig);
} }
_ => {} _ => {}

View File

@ -654,7 +654,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
} }
hir::ItemKind::Const(..) hir::ItemKind::Const(..)
| hir::ItemKind::Static(..) | hir::ItemKind::Static(..)
| hir::ItemKind::Fn(..) | hir::ItemKind::Fn { .. }
| hir::ItemKind::TyAlias(..) => { | hir::ItemKind::TyAlias(..) => {
if let Some(item_ev) = item_ev { if let Some(item_ev) = item_ev {
self.reach(item.owner_id.def_id, item_ev).generics().predicates().ty(); self.reach(item.owner_id.def_id, item_ev).generics().predicates().ty();

View File

@ -1977,7 +1977,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
return None; return None;
}; };
let tykind = match self.tcx.hir_node_by_def_id(trace.cause.body_id) { let tykind = match self.tcx.hir_node_by_def_id(trace.cause.body_id) {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) => { hir::Node::Item(hir::Item {
kind: hir::ItemKind::Fn { body: body_id, .. }, ..
}) => {
let body = hir.body(*body_id); let body = hir.body(*body_id);
struct LetVisitor { struct LetVisitor {
span: Span, span: Span,

View File

@ -630,7 +630,7 @@ impl<T> Trait<T> for X {
let callable_scope = matches!( let callable_scope = matches!(
body_owner, body_owner,
Some( Some(
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }) hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { .. }, .. })
| hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. })
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }), | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }),
) )

View File

@ -817,7 +817,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
pat.walk(&mut find_compatible_candidates); pat.walk(&mut find_compatible_candidates);
} }
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. }) hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { body, .. }, .. })
| hir::Node::ImplItem(hir::ImplItem { | hir::Node::ImplItem(hir::ImplItem {
kind: hir::ImplItemKind::Fn(_, body), .. kind: hir::ImplItemKind::Fn(_, body), ..
}) })

View File

@ -913,7 +913,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
} }
let hir_id = self.tcx.local_def_id_to_hir_id(obligation.cause.body_id); let hir_id = self.tcx.local_def_id_to_hir_id(obligation.cause.body_id);
let body_id = match self.tcx.hir_node(hir_id) { let body_id = match self.tcx.hir_node(hir_id) {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) => body_id, hir::Node::Item(hir::Item {
kind: hir::ItemKind::Fn { body: body_id, .. }, ..
}) => body_id,
_ => return false, _ => return false,
}; };
let ControlFlow::Break(expr) = (FindMethodSubexprOfTry { search_span: span }) let ControlFlow::Break(expr) = (FindMethodSubexprOfTry { search_span: span })
@ -2910,7 +2912,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}) })
.collect::<Option<Vec<ArgKind>>>()?, .collect::<Option<Vec<ArgKind>>>()?,
), ),
Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref sig, ..), .. }) Node::Item(&hir::Item { kind: hir::ItemKind::Fn { ref sig, .. }, .. })
| Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, _), .. }) | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, _), .. })
| Node::TraitItem(&hir::TraitItem { | Node::TraitItem(&hir::TraitItem {
kind: hir::TraitItemKind::Fn(ref sig, _), .. kind: hir::TraitItemKind::Fn(ref sig, _), ..

View File

@ -91,7 +91,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
/// to be the enclosing (async) block/function/closure /// to be the enclosing (async) block/function/closure
fn describe_enclosure(&self, def_id: LocalDefId) -> Option<&'static str> { fn describe_enclosure(&self, def_id: LocalDefId) -> Option<&'static str> {
match self.tcx.hir_node_by_def_id(def_id) { match self.tcx.hir_node_by_def_id(def_id) {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }) => Some("a function"), hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { .. }, .. }) => Some("a function"),
hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) => { hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) => {
Some("a trait method") Some("a trait method")
} }

View File

@ -311,7 +311,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
.. ..
}) })
| hir::Node::Item(hir::Item { | hir::Node::Item(hir::Item {
kind: hir::ItemKind::Fn(fn_sig, generics, _), .. kind: hir::ItemKind::Fn { sig: fn_sig, generics, .. },
..
}) if projection.is_some() => { }) if projection.is_some() => {
// Missing restriction on associated type of type parameter (unmet projection). // Missing restriction on associated type of type parameter (unmet projection).
suggest_restriction( suggest_restriction(
@ -355,7 +356,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
| hir::ItemKind::Union(_, generics) | hir::ItemKind::Union(_, generics)
| hir::ItemKind::Trait(_, _, generics, ..) | hir::ItemKind::Trait(_, _, generics, ..)
| hir::ItemKind::Impl(hir::Impl { generics, .. }) | hir::ItemKind::Impl(hir::Impl { generics, .. })
| hir::ItemKind::Fn(_, generics, _) | hir::ItemKind::Fn { generics, .. }
| hir::ItemKind::TyAlias(_, generics) | hir::ItemKind::TyAlias(_, generics)
| hir::ItemKind::Const(_, generics, _) | hir::ItemKind::Const(_, generics, _)
| hir::ItemKind::TraitAlias(generics, _), | hir::ItemKind::TraitAlias(generics, _),
@ -420,7 +421,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
| hir::ItemKind::Union(_, generics) | hir::ItemKind::Union(_, generics)
| hir::ItemKind::Trait(_, _, generics, ..) | hir::ItemKind::Trait(_, _, generics, ..)
| hir::ItemKind::Impl(hir::Impl { generics, .. }) | hir::ItemKind::Impl(hir::Impl { generics, .. })
| hir::ItemKind::Fn(_, generics, _) | hir::ItemKind::Fn { generics, .. }
| hir::ItemKind::TyAlias(_, generics) | hir::ItemKind::TyAlias(_, generics)
| hir::ItemKind::Const(_, generics, _) | hir::ItemKind::Const(_, generics, _)
| hir::ItemKind::TraitAlias(generics, _), | hir::ItemKind::TraitAlias(generics, _),
@ -846,7 +847,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}; };
name.to_string() name.to_string()
} }
Some(hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(..), .. })) => { Some(hir::Node::Item(hir::Item {
ident, kind: hir::ItemKind::Fn { .. }, ..
})) => {
err.span_label(ident.span, "consider calling this function"); err.span_label(ident.span, "consider calling this function");
ident.to_string() ident.to_string()
} }
@ -1711,7 +1714,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
) -> bool { ) -> bool {
let hir = self.tcx.hir(); let hir = self.tcx.hir();
let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id); let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id);
if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) = node if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn {sig, body: body_id, .. }, .. }) = node
&& let hir::ExprKind::Block(blk, _) = &hir.body(*body_id).value.kind && let hir::ExprKind::Block(blk, _) = &hir.body(*body_id).value.kind
&& sig.decl.output.span().overlaps(span) && sig.decl.output.span().overlaps(span)
&& blk.expr.is_none() && blk.expr.is_none()
@ -1745,7 +1748,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
} }
pub(super) fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> { pub(super) fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. }) = let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { sig, .. }, .. }) =
self.tcx.hir_node_by_def_id(obligation.cause.body_id) self.tcx.hir_node_by_def_id(obligation.cause.body_id)
else { else {
return None; return None;
@ -1859,7 +1862,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let hir = self.tcx.hir(); let hir = self.tcx.hir();
let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id); let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id);
if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) = node { if let hir::Node::Item(hir::Item {
kind: hir::ItemKind::Fn { body: body_id, .. }, ..
}) = node
{
let body = hir.body(*body_id); let body = hir.body(*body_id);
// Point at all the `return`s in the function as they have failed trait bounds. // Point at all the `return`s in the function as they have failed trait bounds.
let mut visitor = ReturnsVisitor::default(); let mut visitor = ReturnsVisitor::default();
@ -4732,7 +4738,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
node: hir::Node<'hir>, node: hir::Node<'hir>,
) -> Option<(&'hir hir::FnDecl<'hir>, hir::BodyId)> { ) -> Option<(&'hir hir::FnDecl<'hir>, hir::BodyId)> {
match node { match node {
hir::Node::Item(item) if let hir::ItemKind::Fn(sig, _, body_id) = item.kind => { hir::Node::Item(item)
if let hir::ItemKind::Fn { sig, body: body_id, .. } = item.kind =>
{
Some((sig.decl, body_id)) Some((sig.decl, body_id))
} }
hir::Node::ImplItem(item) hir::Node::ImplItem(item)

View File

@ -520,7 +520,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
let is_impl = matches!(&node, hir::Node::ImplItem(_)); let is_impl = matches!(&node, hir::Node::ImplItem(_));
let (generics, parent_generics) = match node { let (generics, parent_generics) = match node {
hir::Node::Item(&hir::Item { hir::Node::Item(&hir::Item {
kind: hir::ItemKind::Fn(_, ref generics, ..), kind: hir::ItemKind::Fn { ref generics, .. },
.. ..
}) })
| hir::Node::TraitItem(&hir::TraitItem { ref generics, .. }) | hir::Node::TraitItem(&hir::TraitItem { ref generics, .. })

View File

@ -2810,7 +2810,7 @@ fn clean_maybe_renamed_item<'tcx>(
}), }),
ItemKind::Macro(_, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx), ItemKind::Macro(_, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx),
// proc macros can have a name set by attributes // proc macros can have a name set by attributes
ItemKind::Fn(ref sig, generics, body_id) => { ItemKind::Fn { ref sig, generics, body: body_id, .. } => {
clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx) clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
} }
ItemKind::Trait(_, _, generics, bounds, item_ids) => { ItemKind::Trait(_, _, generics, bounds, item_ids) => {

View File

@ -245,7 +245,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
match item.kind { match item.kind {
ItemKind::Static(_, _, _) ItemKind::Static(_, _, _)
| ItemKind::Const(_, _, _) | ItemKind::Const(_, _, _)
| ItemKind::Fn(_, _, _) | ItemKind::Fn { .. }
| ItemKind::Macro(_, _) | ItemKind::Macro(_, _)
| ItemKind::TyAlias(_, _) | ItemKind::TyAlias(_, _)
| ItemKind::Enum(_, _) | ItemKind::Enum(_, _)

View File

@ -499,7 +499,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
hir::ItemKind::Mod(m) => { hir::ItemKind::Mod(m) => {
self.enter_mod(item.owner_id.def_id, m, name, renamed, import_id); self.enter_mod(item.owner_id.def_id, m, name, renamed, import_id);
} }
hir::ItemKind::Fn(..) hir::ItemKind::Fn { .. }
| hir::ItemKind::ExternCrate(..) | hir::ItemKind::ExternCrate(..)
| hir::ItemKind::Enum(..) | hir::ItemKind::Enum(..)
| hir::ItemKind::Struct(..) | hir::ItemKind::Struct(..)

View File

@ -464,7 +464,7 @@ fn convert_module_item_kind(value: &ItemKind<'_>) -> SourceItemOrderingModuleIte
ItemKind::Use(..) => Use, ItemKind::Use(..) => Use,
ItemKind::Static(..) => Static, ItemKind::Static(..) => Static,
ItemKind::Const(..) => Const, ItemKind::Const(..) => Const,
ItemKind::Fn(..) => Fn, ItemKind::Fn{ .. } => Fn,
ItemKind::Macro(..) => Macro, ItemKind::Macro(..) => Macro,
ItemKind::Mod(..) => Mod, ItemKind::Mod(..) => Mod,
ItemKind::ForeignMod { .. } => ForeignMod, ItemKind::ForeignMod { .. } => ForeignMod,

View File

@ -21,7 +21,7 @@ pub(super) fn is_lint_level(symbol: Symbol, attr_id: AttrId) -> bool {
} }
pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool { pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
if let ItemKind::Fn(_, _, eid) = item.kind { if let ItemKind::Fn { body: eid, .. } = item.kind {
is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value) is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value)
} else { } else {
true true

View File

@ -639,7 +639,7 @@ impl<'tcx> LateLintPass<'tcx> for Documentation {
self.check_private_items, self.check_private_items,
); );
match item.kind { match item.kind {
ItemKind::Fn(sig, _, body_id) => { ItemKind::Fn { sig, body: body_id, .. } => {
if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) if !(is_entrypoint_fn(cx, item.owner_id.to_def_id())
|| in_external_macro(cx.tcx.sess, item.span)) || in_external_macro(cx.tcx.sess, item.span))
{ {

View File

@ -25,7 +25,7 @@ pub(super) fn check(
// page. So associated items or impl blocks are not part of this list. // page. So associated items or impl blocks are not part of this list.
ItemKind::Static(..) ItemKind::Static(..)
| ItemKind::Const(..) | ItemKind::Const(..)
| ItemKind::Fn(..) | ItemKind::Fn{ .. }
| ItemKind::Macro(..) | ItemKind::Macro(..)
| ItemKind::Mod(..) | ItemKind::Mod(..)
| ItemKind::TyAlias(..) | ItemKind::TyAlias(..)

View File

@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for Exit {
&& let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id() && let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id()
&& cx.tcx.is_diagnostic_item(sym::process_exit, def_id) && cx.tcx.is_diagnostic_item(sym::process_exit, def_id)
&& let parent = cx.tcx.hir().get_parent_item(e.hir_id) && let parent = cx.tcx.hir().get_parent_item(e.hir_id)
&& let OwnerNode::Item(Item{kind: ItemKind::Fn(..), ..}) = cx.tcx.hir_owner_node(parent) && let OwnerNode::Item(Item{kind: ItemKind::Fn{ .. }, ..}) = cx.tcx.hir_owner_node(parent)
// If the next item up is a function we check if it is an entry point // If the next item up is a function we check if it is an entry point
// and only then emit a linter warning // and only then emit a linter warning
&& !is_entrypoint_fn(cx, parent.to_def_id()) && !is_entrypoint_fn(cx, parent.to_def_id())

View File

@ -253,7 +253,11 @@ fn is_empty_body(cx: &LateContext<'_>, body: BodyId) -> bool {
impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters { impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
if let ItemKind::Fn(_, generics, body_id) = item.kind if let ItemKind::Fn {
generics,
body: body_id,
..
} = item.kind
&& !generics.params.is_empty() && !generics.params.is_empty()
&& !is_empty_body(cx, body_id) && !is_empty_body(cx, body_id)
&& (!self.avoid_breaking_exported_api || !cx.effective_visibilities.is_exported(item.owner_id.def_id)) && (!self.avoid_breaking_exported_api || !cx.effective_visibilities.is_exported(item.owner_id.def_id))

View File

@ -24,7 +24,12 @@ use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT};
pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
let attrs = cx.tcx.hir().attrs(item.hir_id()); let attrs = cx.tcx.hir().attrs(item.hir_id());
let attr = cx.tcx.get_attr(item.owner_id, sym::must_use); let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
if let hir::ItemKind::Fn(ref sig, _generics, ref body_id) = item.kind { if let hir::ItemKind::Fn {
ref sig,
body: ref body_id,
..
} = item.kind
{
let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id); let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
if let Some(attr) = attr { if let Some(attr) = attr {

View File

@ -36,7 +36,7 @@ fn result_err_ty<'tcx>(
} }
pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, large_err_threshold: u64, msrv: &Msrv) { pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, large_err_threshold: u64, msrv: &Msrv) {
if let hir::ItemKind::Fn(ref sig, _generics, _) = item.kind if let hir::ItemKind::Fn { ref sig, .. } = item.kind
&& let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span) && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span)
{ {
if cx.effective_visibilities.is_exported(item.owner_id.def_id) { if cx.effective_visibilities.is_exported(item.owner_id.def_id) {

View File

@ -149,7 +149,12 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
); );
} }
}, },
ItemKind::Fn(ref sig, generics, body_id) => { ItemKind::Fn {
ref sig,
generics,
body: body_id,
..
} => {
let body = cx.tcx.hir().body(body_id); let body = cx.tcx.hir().body(body_id);
for ty in sig.decl.inputs { for ty in sig.decl.inputs {

View File

@ -95,7 +95,13 @@ declare_lint_pass!(Lifetimes => [NEEDLESS_LIFETIMES, EXTRA_UNUSED_LIFETIMES]);
impl<'tcx> LateLintPass<'tcx> for Lifetimes { impl<'tcx> LateLintPass<'tcx> for Lifetimes {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if let ItemKind::Fn(ref sig, generics, id) = item.kind { if let ItemKind::Fn {
ref sig,
generics,
body: id,
..
} = item.kind
{
check_fn_inner(cx, sig, Some(id), None, generics, item.span, true); check_fn_inner(cx, sig, Some(id), None, generics, item.span, true);
} else if let ItemKind::Impl(impl_) = item.kind { } else if let ItemKind::Impl(impl_) = item.kind {
if !item.span.from_expansion() { if !item.span.from_expansion() {

View File

@ -75,7 +75,11 @@ fn get_parent_fn_ret_ty<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option
.. ..
}) => (), }) => (),
Node::Item(hir::Item { Node::Item(hir::Item {
kind: hir::ItemKind::Fn(FnSig { decl, .. }, _, _), kind:
hir::ItemKind::Fn {
sig: FnSig { decl, .. },
..
},
.. ..
}) })
| Node::TraitItem(hir::TraitItem { | Node::TraitItem(hir::TraitItem {

View File

@ -133,7 +133,7 @@ fn expr_ty_matches_p_ty(cx: &LateContext<'_>, expr: &Expr<'_>, p_expr: &Expr<'_>
}, },
// compare match_expr ty with RetTy in `fn foo() -> RetTy` // compare match_expr ty with RetTy in `fn foo() -> RetTy`
Node::Item(item) => { Node::Item(item) => {
if let ItemKind::Fn(..) = item.kind { if let ItemKind::Fn{ .. } = item.kind {
let output = cx let output = cx
.tcx .tcx
.fn_sig(item.owner_id) .fn_sig(item.owner_id)

View File

@ -496,7 +496,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
Node::Stmt(_) => return true, Node::Stmt(_) => return true,
Node::Block(..) => continue, Node::Block(..) => continue,
Node::Item(item) => { Node::Item(item) => {
if let ItemKind::Fn(_, _, body_id) = &item.kind if let ItemKind::Fn { body: body_id, .. } = &item.kind
&& let output_ty = return_ty(cx, item.owner_id) && let output_ty = return_ty(cx, item.owner_id)
&& rustc_hir_typeck::can_coerce(cx.tcx, cx.param_env, item.owner_id.def_id, ty, output_ty) && rustc_hir_typeck::can_coerce(cx.tcx, cx.param_env, item.owner_id.def_id, ty, output_ty)
{ {

View File

@ -192,7 +192,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) { fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
match it.kind { match it.kind {
hir::ItemKind::Fn(..) => { hir::ItemKind::Fn{ .. } => {
// ignore main() // ignore main()
if it.ident.name == sym::main { if it.ident.name == sym::main {
let at_root = cx.tcx.local_parent(it.owner_id.def_id) == CRATE_DEF_ID; let at_root = cx.tcx.local_parent(it.owner_id.def_id) == CRATE_DEF_ID;

View File

@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
return; return;
} }
match it.kind { match it.kind {
hir::ItemKind::Fn(..) => { hir::ItemKind::Fn{ .. } => {
let desc = "a function"; let desc = "a function";
let attrs = cx.tcx.hir().attrs(it.hir_id()); let attrs = cx.tcx.hir().attrs(it.hir_id());
check_missing_inline_attrs(cx, attrs, it.span, desc); check_missing_inline_attrs(cx, attrs, it.span, desc);

View File

@ -76,7 +76,7 @@ impl_lint_pass!(MutableKeyType<'_> => [ MUTABLE_KEY_TYPE ]);
impl<'tcx> LateLintPass<'tcx> for MutableKeyType<'tcx> { impl<'tcx> LateLintPass<'tcx> for MutableKeyType<'tcx> {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
if let hir::ItemKind::Fn(ref sig, ..) = item.kind { if let hir::ItemKind::Fn { ref sig, .. } = item.kind {
self.check_sig(cx, item.owner_id.def_id, sig.decl); self.check_sig(cx, item.owner_id.def_id, sig.decl);
} }
} }

View File

@ -144,7 +144,7 @@ impl NoEffect {
|diag| { |diag| {
for parent in cx.tcx.hir().parent_iter(stmt.hir_id) { for parent in cx.tcx.hir().parent_iter(stmt.hir_id) {
if let Node::Item(item) = parent.1 if let Node::Item(item) = parent.1
&& let ItemKind::Fn(..) = item.kind && let ItemKind::Fn{ .. } = item.kind
&& let Node::Block(block) = cx.tcx.parent_hir_node(stmt.hir_id) && let Node::Block(block) = cx.tcx.parent_hir_node(stmt.hir_id)
&& let [.., final_stmt] = block.stmts && let [.., final_stmt] = block.stmts
&& final_stmt.hir_id == stmt.hir_id && final_stmt.hir_id == stmt.hir_id

View File

@ -37,7 +37,7 @@ declare_lint_pass!(NoMangleWithRustAbi => [NO_MANGLE_WITH_RUST_ABI]);
impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi { impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
if let ItemKind::Fn(fn_sig, _, _) = &item.kind { if let ItemKind::Fn { sig: fn_sig, .. } = &item.kind {
let attrs = cx.tcx.hir().attrs(item.hir_id()); let attrs = cx.tcx.hir().attrs(item.hir_id());
let mut app = Applicability::MaybeIncorrect; let mut app = Applicability::MaybeIncorrect;
let fn_snippet = snippet_with_applicability(cx, fn_sig.span.with_hi(item.ident.span.lo()), "..", &mut app); let fn_snippet = snippet_with_applicability(cx, fn_sig.span.with_hi(item.ident.span.lo()), "..", &mut app);

View File

@ -189,7 +189,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
let mut parents = hir.parent_iter(body.value.hir_id); let mut parents = hir.parent_iter(body.value.hir_id);
let (item_id, sig, is_trait_item) = match parents.next() { let (item_id, sig, is_trait_item) = match parents.next() {
Some((_, Node::Item(i))) => { Some((_, Node::Item(i))) => {
if let ItemKind::Fn(sig, ..) = &i.kind { if let ItemKind::Fn { sig, .. } = &i.kind {
(i.owner_id, sig, false) (i.owner_id, sig, false)
} else { } else {
return; return;

View File

@ -204,7 +204,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
// Ensure this is not the final stmt, otherwise removing it would cause a compile error // Ensure this is not the final stmt, otherwise removing it would cause a compile error
&& let OwnerNode::Item(item) = cx.tcx.hir_owner_node(cx.tcx.hir().get_parent_item(expr.hir_id)) && let OwnerNode::Item(item) = cx.tcx.hir_owner_node(cx.tcx.hir().get_parent_item(expr.hir_id))
&& let ItemKind::Fn(_, _, body) = item.kind && let ItemKind::Fn { body, .. } = item.kind
&& let block = cx.tcx.hir().body(body).value && let block = cx.tcx.hir().body(body).value
&& let ExprKind::Block(block, _) = block.kind && let ExprKind::Block(block, _) = block.kind
&& !is_inside_let_else(cx.tcx, expr) && !is_inside_let_else(cx.tcx, expr)

View File

@ -130,9 +130,9 @@ impl LateLintPass<'_> for UnnecessaryBoxReturns {
} }
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
let ItemKind::Fn(signature, ..) = &item.kind else { let ItemKind::Fn { sig, .. } = &item.kind else {
return; return;
}; };
self.check_fn_item(cx, signature.decl, item.owner_id.def_id, item.ident.name); self.check_fn_item(cx, sig.decl, item.owner_id.def_id, item.ident.name);
} }
} }

View File

@ -245,7 +245,7 @@ fn item_search_pat(item: &Item<'_>) -> (Pat, Pat) {
ItemKind::ExternCrate(_) => (Pat::Str("extern"), Pat::Str(";")), ItemKind::ExternCrate(_) => (Pat::Str("extern"), Pat::Str(";")),
ItemKind::Static(..) => (Pat::Str("static"), Pat::Str(";")), ItemKind::Static(..) => (Pat::Str("static"), Pat::Str(";")),
ItemKind::Const(..) => (Pat::Str("const"), Pat::Str(";")), ItemKind::Const(..) => (Pat::Str("const"), Pat::Str(";")),
ItemKind::Fn(sig, ..) => (fn_header_search_pat(sig.header), Pat::Str("")), ItemKind::Fn { sig, .. } => (fn_header_search_pat(sig.header), Pat::Str("")),
ItemKind::ForeignMod { .. } => (Pat::Str("extern"), Pat::Str("}")), ItemKind::ForeignMod { .. } => (Pat::Str("extern"), Pat::Str("}")),
ItemKind::TyAlias(..) => (Pat::Str("type"), Pat::Str(";")), ItemKind::TyAlias(..) => (Pat::Str("type"), Pat::Str(";")),
ItemKind::Enum(..) => (Pat::Str("enum"), Pat::Str("}")), ItemKind::Enum(..) => (Pat::Str("enum"), Pat::Str("}")),

View File

@ -1397,7 +1397,7 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio
enclosing_node.and_then(|node| match node { enclosing_node.and_then(|node| match node {
Node::Block(block) => Some(block), Node::Block(block) => Some(block),
Node::Item(&Item { Node::Item(&Item {
kind: ItemKind::Fn(_, _, eid), kind: ItemKind::Fn { body: eid, .. },
.. ..
}) })
| Node::ImplItem(&ImplItem { | Node::ImplItem(&ImplItem {
@ -2565,7 +2565,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool {
// function scope // function scope
.any(|(_id, node)| { .any(|(_id, node)| {
if let Node::Item(item) = node { if let Node::Item(item) = node {
if let ItemKind::Fn(_, _, _) = item.kind { if let ItemKind::Fn { .. } = item.kind {
// Note that we have sorted the item names in the visitor, // Note that we have sorted the item names in the visitor,
// so the binary_search gets the same as `contains`, but faster. // so the binary_search gets the same as `contains`, but faster.
return names.binary_search(&item.ident.name).is_ok(); return names.binary_search(&item.ident.name).is_ok();
@ -2722,7 +2722,7 @@ impl<'tcx> ExprUseCtxt<'tcx> {
}) => ExprUseNode::ConstStatic(owner_id), }) => ExprUseNode::ConstStatic(owner_id),
Node::Item(&Item { Node::Item(&Item {
kind: ItemKind::Fn(..), kind: ItemKind::Fn { .. },
owner_id, owner_id,
.. ..
}) })

View File

@ -242,7 +242,7 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
let is_reachable_non_generic = matches!( let is_reachable_non_generic = matches!(
tcx.hir_node_by_def_id(local_def_id), tcx.hir_node_by_def_id(local_def_id),
Node::Item(&hir::Item { Node::Item(&hir::Item {
kind: hir::ItemKind::Static(..) | hir::ItemKind::Fn(..), kind: hir::ItemKind::Static(..) | hir::ItemKind::Fn{ .. },
.. ..
}) | Node::ImplItem(&hir::ImplItem { }) | Node::ImplItem(&hir::ImplItem {
kind: hir::ImplItemKind::Fn(..), kind: hir::ImplItemKind::Fn(..),

View File

@ -3,11 +3,9 @@
#[unstable(feature = "unstable", issue = "42")] #[unstable(feature = "unstable", issue = "42")]
#[rustc_intrinsic] #[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden] pub const unsafe fn size_of_val<T>(x: *const T) -> usize;
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
#[unstable(feature = "unstable", issue = "42")] #[unstable(feature = "unstable", issue = "42")]
#[rustc_const_unstable(feature = "unstable", issue = "42")] #[rustc_const_unstable(feature = "unstable", issue = "42")]
#[rustc_intrinsic] #[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden] pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize;
pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }

View File

@ -2,7 +2,7 @@
//! neither within a crate nor cross-crate. //! neither within a crate nor cross-crate.
//@ aux-build:unstable_intrinsic.rs //@ aux-build:unstable_intrinsic.rs
#![feature(staged_api, rustc_attrs, intrinsics)] #![feature(staged_api, rustc_attrs, intrinsics)]
#![stable(since="1.0.0", feature = "stable")] #![stable(since = "1.0.0", feature = "stable")]
#![feature(local)] #![feature(local)]
extern crate unstable_intrinsic; extern crate unstable_intrinsic;
@ -30,14 +30,12 @@ const fn const_main() {
#[unstable(feature = "local", issue = "42")] #[unstable(feature = "local", issue = "42")]
#[rustc_intrinsic] #[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden] pub const unsafe fn size_of_val<T>(x: *const T) -> usize;
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
#[unstable(feature = "local", issue = "42")] #[unstable(feature = "local", issue = "42")]
#[rustc_const_unstable(feature = "local", issue = "42")] #[rustc_const_unstable(feature = "local", issue = "42")]
#[rustc_intrinsic] #[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden] pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize;
pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.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) { pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
// Const stability attributes are not inherited from parent items. // Const stability attributes are not inherited from parent items.
#[rustc_intrinsic] #[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden] const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize);
const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
unimplemented!()
}
unsafe { copy(src, dst, count) } unsafe { copy(src, dst, count) }
//~^ ERROR cannot be (indirectly) exposed to stable //~^ ERROR cannot be (indirectly) exposed to stable

View File

@ -69,7 +69,7 @@ LL | const fn const_main() {
| |
error: intrinsic `copy::copy` cannot be (indirectly) exposed to stable 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) } 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) = 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)]` 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); LL | super::size_of_val(src);
| ^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -9,8 +9,7 @@
//@ rustc-env:RUST_BACKTRACE=0 //@ rustc-env:RUST_BACKTRACE=0
#[rustc_intrinsic] #[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() { fn main() {
unsafe { const_deallocate(std::ptr::null_mut(), 0, 0) } unsafe { const_deallocate(std::ptr::null_mut(), 0, 0) }

View File

@ -1,5 +1,5 @@
error: must be overridden by codegen backend, but isn't 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) } LL | unsafe { const_deallocate(std::ptr::null_mut(), 0, 0) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,7 +1,11 @@
// Tests the different rules for `fn` forms requiring the presence or lack of a body. // 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 main() {
fn f1(); //~ ERROR free function without a body fn f1(); //~ ERROR free function without a body
fn f1_rpit() -> impl Trait; //~ ERROR free function without a body
fn f2() {} // OK. fn f2() {} // OK.
trait X { trait X {

View File

@ -1,13 +1,21 @@
error: free function without a body 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(); LL | fn f1();
| ^^^^^^^- | ^^^^^^^-
| | | |
| help: provide a definition for the function: `{ <body> }` | 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 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(); LL | fn f1();
| ^^^^^^^- | ^^^^^^^-
@ -15,7 +23,7 @@ LL | fn f1();
| help: provide a definition for the function: `{ <body> }` | help: provide a definition for the function: `{ <body> }`
error: associated function in `impl` without 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(); LL | fn f3();
| ^^^^^^^- | ^^^^^^^-
@ -23,7 +31,7 @@ LL | fn f3();
| help: provide a definition for the function: `{ <body> }` | help: provide a definition for the function: `{ <body> }`
error: incorrect function inside `extern` block 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" { LL | extern "C" {
| ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body | ---------- `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 = 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 = 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

View File

@ -19,10 +19,7 @@ impl Copy for bool {}
#[stable(feature = "test", since = "1.0.0")] #[stable(feature = "test", since = "1.0.0")]
#[rustc_const_stable(feature = "test", since = "1.0.0")] #[rustc_const_stable(feature = "test", since = "1.0.0")]
#[rustc_intrinsic] #[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden] const unsafe fn unreachable() -> !;
const unsafe fn unreachable() -> ! {
loop {}
}
#[rustc_builtin_macro] #[rustc_builtin_macro]
macro_rules! cfg { macro_rules! cfg {

View File

@ -471,7 +471,6 @@ pub trait StructuralPartialEq {}
pub const fn drop<T: ~const Destruct>(_: T) {} pub const fn drop<T: ~const Destruct>(_: T) {}
#[rustc_intrinsic_must_be_overridden]
#[rustc_intrinsic] #[rustc_intrinsic]
const fn const_eval_select<ARG: Tuple, F, G, RET>( const fn const_eval_select<ARG: Tuple, F, G, RET>(
arg: ARG, arg: ARG,
@ -480,7 +479,4 @@ const fn const_eval_select<ARG: Tuple, F, G, RET>(
) -> RET ) -> RET
where where
F: const FnOnce<ARG, Output = RET>, F: const FnOnce<ARG, Output = RET>,
G: FnOnce<ARG, Output = RET>, G: FnOnce<ARG, Output = RET>;
{
loop {}
}