From f537287363a41a580a23adcf4c24fa4a179d9deb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Wejdenst=C3=A5l?= Date: Sun, 23 Nov 2025 21:45:41 +0100 Subject: [PATCH 1/2] Inline attributes on async fn and async closures affect the poll impl instead of the desugared creator function. --- .../rustc_codegen_ssa/src/codegen_attrs.rs | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index fd3d7d2a3ded0..fb0e5e514c6b2 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -6,7 +6,10 @@ use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr}; use rustc_hir::attrs::{AttributeKind, InlineAttr, InstructionSetAttr, RtsanSetting, UsedBy}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; -use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items}; +use rustc_hir::{ + self as hir, Attribute, CoroutineDesugaring, CoroutineKind, CoroutineSource, LangItem, + find_attr, lang_items, +}; use rustc_middle::middle::codegen_fn_attrs::{ CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SanitizerFnAttrs, }; @@ -386,6 +389,15 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code } } + // #129347: desugared async coutines inherit inline attrs from the async fn/closure + if let Some(parent) = async_poll_inherit_inline(tcx, did.to_def_id()) { + let parent_attrs = tcx.codegen_fn_attrs(parent); + if matches!(parent_attrs.inline, InlineAttr::Never | InlineAttr::Hint | InlineAttr::Always) + { + codegen_fn_attrs.inline = parent_attrs.inline; + } + } + // When `no_builtins` is applied at the crate level, we should add the // `no-builtins` attribute to each function to ensure it takes effect in LTO. let crate_attrs = tcx.hir_attrs(rustc_hir::CRATE_HIR_ID); @@ -647,6 +659,23 @@ fn inherited_align<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option { tcx.codegen_fn_attrs(tcx.trait_item_of(def_id)?).alignment } +// Checks if the given DefId is a desugared async coroutine that should inherit inline attrs. +fn async_poll_inherit_inline(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + let Some(kind) = tcx.coroutine_kind(def_id) else { + return None; + }; + + if matches!( + kind, + CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Fn) + | CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure) + ) { + Some(tcx.parent(def_id)) + } else { + None + } +} + /// We now check the #\[rustc_autodiff\] attributes which we generated from the #[autodiff(...)] /// macros. There are two forms. The pure one without args to mark primal functions (the functions /// being differentiated). The other form is #[rustc_autodiff(Mode, ActivityList)] on top of the From fa35f7b77d40cdf77b2947d1536c58c886fa2457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Wejdenst=C3=A5l?= Date: Sun, 23 Nov 2025 23:55:48 +0100 Subject: [PATCH 2/2] Lower at the same place as #[track_caller] is handled. --- compiler/rustc_ast_lowering/src/expr.rs | 33 +++++++++++++++++++ compiler/rustc_ast_lowering/src/item.rs | 1 + .../rustc_codegen_ssa/src/codegen_attrs.rs | 31 +---------------- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 524f8b054cb49..bd67272195b53 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1,3 +1,4 @@ +use std::iter; use std::ops::ControlFlow; use std::sync::Arc; @@ -804,6 +805,37 @@ impl<'hir> LoweringContext<'_, 'hir> { } } + pub(super) fn forward_inline(&mut self, _span: Span, outer_hir_id: HirId, inner_hir_id: HirId) { + let Some(attrs) = self.attrs.get(&outer_hir_id.local_id) else { + return; + }; + + let Some((inline_attr, span)) = + find_attr!(*attrs, AttributeKind::Inline(attr, span) => (attr, span)) + else { + return; + }; + + let filtered_iter = attrs + .iter() + .cloned() + .filter(|attr| !matches!(attr, hir::Attribute::Parsed(AttributeKind::Inline(_, _)))); + + let filtered_attrs = self.arena.alloc_from_iter(filtered_iter); + + if filtered_attrs.is_empty() { + self.attrs.remove(&outer_hir_id.local_id); + } else { + self.attrs.insert(outer_hir_id.local_id, filtered_attrs); + } + + let attr = self.arena.alloc_from_iter(iter::once(hir::Attribute::Parsed( + AttributeKind::Inline(*inline_attr, *span), + ))); + + self.attrs.insert(inner_hir_id.local_id, attr); + } + /// Desugar `.await` into: /// ```ignore (pseudo-rust) /// match ::std::future::IntoFuture::into_future() { @@ -1167,6 +1199,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); this.maybe_forward_track_caller(body.span, closure_hir_id, expr.hir_id); + this.forward_inline(body.span, closure_hir_id, expr.hir_id); (parameters, expr) }); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index f5b7065247a08..5cb5f552ac17f 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1290,6 +1290,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // FIXME(async_fn_track_caller): Can this be moved above? let hir_id = expr.hir_id; this.maybe_forward_track_caller(body.span, fn_id, hir_id); + this.forward_inline(body.span, fn_id, hir_id); (parameters, expr) }) diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index fb0e5e514c6b2..fd3d7d2a3ded0 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -6,10 +6,7 @@ use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr}; use rustc_hir::attrs::{AttributeKind, InlineAttr, InstructionSetAttr, RtsanSetting, UsedBy}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; -use rustc_hir::{ - self as hir, Attribute, CoroutineDesugaring, CoroutineKind, CoroutineSource, LangItem, - find_attr, lang_items, -}; +use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items}; use rustc_middle::middle::codegen_fn_attrs::{ CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SanitizerFnAttrs, }; @@ -389,15 +386,6 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code } } - // #129347: desugared async coutines inherit inline attrs from the async fn/closure - if let Some(parent) = async_poll_inherit_inline(tcx, did.to_def_id()) { - let parent_attrs = tcx.codegen_fn_attrs(parent); - if matches!(parent_attrs.inline, InlineAttr::Never | InlineAttr::Hint | InlineAttr::Always) - { - codegen_fn_attrs.inline = parent_attrs.inline; - } - } - // When `no_builtins` is applied at the crate level, we should add the // `no-builtins` attribute to each function to ensure it takes effect in LTO. let crate_attrs = tcx.hir_attrs(rustc_hir::CRATE_HIR_ID); @@ -659,23 +647,6 @@ fn inherited_align<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option { tcx.codegen_fn_attrs(tcx.trait_item_of(def_id)?).alignment } -// Checks if the given DefId is a desugared async coroutine that should inherit inline attrs. -fn async_poll_inherit_inline(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - let Some(kind) = tcx.coroutine_kind(def_id) else { - return None; - }; - - if matches!( - kind, - CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Fn) - | CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure) - ) { - Some(tcx.parent(def_id)) - } else { - None - } -} - /// We now check the #\[rustc_autodiff\] attributes which we generated from the #[autodiff(...)] /// macros. There are two forms. The pure one without args to mark primal functions (the functions /// being differentiated). The other form is #[rustc_autodiff(Mode, ActivityList)] on top of the