about summary refs log tree commit diff
path: root/compiler/rustc_monomorphize
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-09-01 10:54:40 +0000
committerbors <bors@rust-lang.org>2025-09-01 10:54:40 +0000
commitc0bb3b98bb7aac24a37635e5d36d961e0b14f435 (patch)
tree61c53e7080714662cea1a0730b225b5778ab66b2 /compiler/rustc_monomorphize
parent84a17470220e7adf249b18d7c0178dfbede89462 (diff)
parentc2c58cbc65343f1a227885c7a5893f3e6d616e82 (diff)
downloadrust-c0bb3b98bb7aac24a37635e5d36d961e0b14f435.tar.gz
rust-c0bb3b98bb7aac24a37635e5d36d961e0b14f435.zip
Auto merge of #143290 - azhogin:azhogin/link-pub-async-impls, r=oli-obk
pub async fn impl is monomorphized when func itself is monomorphized

Implentation coroutine (`func::{closure#0}`) is monomorphized, when func itself is monomorphized.

Currently, when `pub async fn foo(..)` is exported from lib and used in several dependent crates, only 'header' function is monomorphized in the defining crate. 'header' function, returning coroutine object, is monomorphized, but the coroutine's poll function (which actually implements all the logic for the function) is not. In such situation, `func::{closure#0}` will be monomorphized in every dependency.

This PR adds monomorphization for `func::{closure#0}` (coroutine poll function), when func itself is monomorphized.

Simple test with one lib async function and ten dependent crates (executable) that use the function, shows 5-7% compilation time improvement (single-threaded).
Diffstat (limited to 'compiler/rustc_monomorphize')
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs15
1 files changed, 14 insertions, 1 deletions
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 6a836442c32..cffeb6f9807 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1535,7 +1535,20 @@ impl<'v> RootCollector<'_, 'v> {
     fn process_nested_body(&mut self, def_id: LocalDefId) {
         match self.tcx.def_kind(def_id) {
             DefKind::Closure => {
-                if self.strategy == MonoItemCollectionStrategy::Eager
+                // for 'pub async fn foo(..)' also trying to monomorphize foo::{closure}
+                let is_pub_fn_coroutine =
+                    match *self.tcx.type_of(def_id).instantiate_identity().kind() {
+                        ty::Coroutine(cor_id, _args) => {
+                            let tcx = self.tcx;
+                            let parent_id = tcx.parent(cor_id);
+                            tcx.def_kind(parent_id) == DefKind::Fn
+                                && tcx.asyncness(parent_id).is_async()
+                                && tcx.visibility(parent_id).is_public()
+                        }
+                        ty::Closure(..) | ty::CoroutineClosure(..) => false,
+                        _ => unreachable!(),
+                    };
+                if (self.strategy == MonoItemCollectionStrategy::Eager || is_pub_fn_coroutine)
                     && !self
                         .tcx
                         .generics_of(self.tcx.typeck_root_def_id(def_id.to_def_id()))