Skip to content

Commit e6b35f4

Browse files
committed
pub async fn implementation coroutine (func::{closure#0}) is monomorphized, when func itself is monomorphized
1 parent 55d4364 commit e6b35f4

File tree

12 files changed

+141
-15
lines changed

12 files changed

+141
-15
lines changed

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1510,7 +1510,20 @@ impl<'v> RootCollector<'_, 'v> {
15101510
fn process_nested_body(&mut self, def_id: LocalDefId) {
15111511
match self.tcx.def_kind(def_id) {
15121512
DefKind::Closure => {
1513-
if self.strategy == MonoItemCollectionStrategy::Eager
1513+
// for 'pub async fn foo(..)' also trying to monomorphize foo::{closure}
1514+
let is_pub_fn_coroutine =
1515+
match *self.tcx.type_of(def_id).instantiate_identity().kind() {
1516+
ty::Coroutine(cor_id, _args) => {
1517+
let tcx = self.tcx;
1518+
let parent_id = tcx.parent(cor_id);
1519+
tcx.def_kind(parent_id) == DefKind::Fn
1520+
&& tcx.asyncness(parent_id).is_async()
1521+
&& tcx.visibility(parent_id).is_public()
1522+
}
1523+
ty::Closure(..) | ty::CoroutineClosure(..) => false,
1524+
_ => unreachable!(),
1525+
};
1526+
if (self.strategy == MonoItemCollectionStrategy::Eager || is_pub_fn_coroutine)
15141527
&& !self
15151528
.tcx
15161529
.generics_of(self.tcx.typeck_root_def_id(def_id.to_def_id()))
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//@ edition: 2024
2+
// When pub async fn is monomorphized, its implementation coroutine is also monomorphized
3+
//@ compile-flags: --crate-type=lib
4+
5+
//~ MONO_ITEM fn async_fn @@
6+
//~ MONO_ITEM fn async_fn::{closure#0} @@
7+
#[unsafe(no_mangle)]
8+
pub async fn async_fn(x: u64) -> bool {
9+
true
10+
}

tests/codegen/async-fn-debug-awaitee-field.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ pub async fn async_fn_test() {
1818

1919
pub async fn foo() {}
2020

21+
// NONMSVC: [[AWAITEE_TYPE:![0-9]*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[AWAITEE_SCOPE:![0-9]*]],
22+
// MSVC: [[AWAITEE_TYPE:![0-9]*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<async_fn_debug_awaitee_field::foo::async_fn_env$0>",
23+
// NONMSVC: [[AWAITEE_SCOPE]] = !DINamespace(name: "foo",
2124
// NONMSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[GEN_SCOPE:![0-9]*]],
2225
// MSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<async_fn_debug_awaitee_field::async_fn_test::async_fn_env$0>",
2326
// NONMSVC: [[GEN_SCOPE:!.*]] = !DINamespace(name: "async_fn_test",
2427
// CHECK: [[SUSPEND_STRUCT:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend0", scope: [[GEN]],
25-
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__awaitee", scope: [[SUSPEND_STRUCT]], {{.*}}, baseType: [[AWAITEE_TYPE:![0-9]*]],
26-
// NONMSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[AWAITEE_SCOPE:![0-9]*]],
27-
// MSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<async_fn_debug_awaitee_field::foo::async_fn_env$0>",
28-
// NONMSVC: [[AWAITEE_SCOPE]] = !DINamespace(name: "foo",
28+
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__awaitee", scope: [[SUSPEND_STRUCT]], {{.*}}, baseType: [[AWAITEE_TYPE]],

tests/coverage/async.cov-map

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,21 +103,21 @@ Number of file 0 mappings: 3
103103
Highest counter ID seen: (none)
104104

105105
Function name: async::g
106-
Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 01, 00, 16]
106+
Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 01, 00, 12]
107107
Number of files: 1
108108
- file 0 => $DIR/async.rs
109109
Number of expressions: 0
110110
Number of file 0 mappings: 1
111-
- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 22)
111+
- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 18)
112112
Highest counter ID seen: c0
113113

114114
Function name: async::g::{closure#0} (unused)
115-
Raw bytes (64): 0x[01, 01, 00, 0c, 00, 1b, 17, 00, 18, 00, 01, 0b, 00, 0c, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
115+
Raw bytes (64): 0x[01, 01, 00, 0c, 00, 1b, 13, 00, 14, 00, 01, 0b, 00, 0c, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
116116
Number of files: 1
117117
- file 0 => $DIR/async.rs
118118
Number of expressions: 0
119119
Number of file 0 mappings: 12
120-
- Code(Zero) at (prev + 27, 23) to (start + 0, 24)
120+
- Code(Zero) at (prev + 27, 19) to (start + 0, 20)
121121
- Code(Zero) at (prev + 1, 11) to (start + 0, 12)
122122
- Code(Zero) at (prev + 1, 9) to (start + 0, 10)
123123
- Code(Zero) at (prev + 0, 14) to (start + 0, 23)

tests/coverage/async.coverage

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
LL| |
2525
LL| 0|async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()`
2626
LL| |
27-
LL| 1|pub async fn g(x: u8) {
28-
^0
27+
LL| 1|async fn g(x: u8) {
28+
^0
2929
LL| 0| match x {
3030
LL| 0| y if e().await == y => (),
3131
LL| 0| y if f().await == y => (),

tests/coverage/async.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ async fn f() -> u8 { 1 }
2424

2525
async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()`
2626

27-
pub async fn g(x: u8) {
27+
async fn g(x: u8) {
2828
match x {
2929
y if e().await == y => (),
3030
y if f().await == y => (),

tests/ui/async-await/future-sizes/async-awaiting-fut.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
//@ compile-flags: -Z print-type-sizes --crate-type lib
1+
//@ compile-flags: -C panic=abort -Z print-type-sizes --crate-type lib
22
//@ edition:2021
33
//@ build-pass
44
//@ ignore-pass
5+
//@ only-x86_64
56

67
async fn wait() {}
78

tests/ui/async-await/future-sizes/async-awaiting-fut.stdout

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,36 @@ print-type-size variant `Returned`: 1024 bytes
4848
print-type-size upvar `.arg`: 1024 bytes
4949
print-type-size variant `Panicked`: 1024 bytes
5050
print-type-size upvar `.arg`: 1024 bytes
51+
print-type-size type: `std::task::Context<'_>`: 32 bytes, alignment: 8 bytes
52+
print-type-size field `.waker`: 8 bytes
53+
print-type-size field `.local_waker`: 8 bytes
54+
print-type-size field `.ext`: 16 bytes
55+
print-type-size field `._marker`: 0 bytes
56+
print-type-size field `._marker2`: 0 bytes
57+
print-type-size type: `std::panic::Location<'_>`: 24 bytes, alignment: 8 bytes
58+
print-type-size field `.file_bytes_with_nul`: 16 bytes
59+
print-type-size field `.line`: 4 bytes
60+
print-type-size field `.col`: 4 bytes
61+
print-type-size type: `core::task::wake::ExtData<'_>`: 16 bytes, alignment: 8 bytes
62+
print-type-size variant `Some`: 16 bytes
63+
print-type-size field `.0`: 16 bytes
64+
print-type-size variant `None`: 0 bytes
65+
print-type-size field `.0`: 0 bytes
66+
print-type-size type: `std::panic::AssertUnwindSafe<core::task::wake::ExtData<'_>>`: 16 bytes, alignment: 8 bytes
67+
print-type-size field `.0`: 16 bytes
68+
print-type-size type: `std::pin::Pin<&mut {async fn body of big_fut()}>`: 8 bytes, alignment: 8 bytes
69+
print-type-size field `.pointer`: 8 bytes
70+
print-type-size type: `std::pin::Pin<&mut {async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 8 bytes, alignment: 8 bytes
71+
print-type-size field `.pointer`: 8 bytes
72+
print-type-size type: `std::pin::Pin<&mut {async fn body of test()}>`: 8 bytes, alignment: 8 bytes
73+
print-type-size field `.pointer`: 8 bytes
74+
print-type-size type: `std::pin::Pin<&mut {async fn body of wait()}>`: 8 bytes, alignment: 8 bytes
75+
print-type-size field `.pointer`: 8 bytes
76+
print-type-size type: `std::ptr::DynMetadata<dyn std::any::Any>`: 8 bytes, alignment: 8 bytes
77+
print-type-size field `._vtable_ptr`: 8 bytes
78+
print-type-size field `._phantom`: 0 bytes
79+
print-type-size type: `std::ptr::NonNull<std::ptr::metadata::VTable>`: 8 bytes, alignment: 8 bytes
80+
print-type-size field `.pointer`: 8 bytes
5181
print-type-size type: `std::mem::ManuallyDrop<bool>`: 1 bytes, alignment: 1 bytes
5282
print-type-size field `.value`: 1 bytes
5383
print-type-size type: `std::mem::ManuallyDrop<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes
@@ -70,3 +100,6 @@ print-type-size discriminant: 1 bytes
70100
print-type-size variant `Unresumed`: 0 bytes
71101
print-type-size variant `Returned`: 0 bytes
72102
print-type-size variant `Panicked`: 0 bytes
103+
print-type-size type: `std::marker::PhantomData<*mut ()>`: 0 bytes, alignment: 1 bytes
104+
print-type-size type: `std::marker::PhantomData<dyn std::any::Any>`: 0 bytes, alignment: 1 bytes
105+
print-type-size type: `std::marker::PhantomData<fn(&()) -> &()>`: 0 bytes, alignment: 1 bytes

tests/ui/async-await/future-sizes/large-arg.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
//@ compile-flags: -Z print-type-sizes --crate-type=lib
1+
//@ compile-flags: -C panic=abort -Z print-type-sizes --crate-type=lib
22
//@ edition: 2021
33
//@ build-pass
44
//@ ignore-pass
5+
//@ only-x86_64
56

67
pub async fn test() {
78
let _ = a([0u8; 1024]).await;

tests/ui/async-await/future-sizes/large-arg.stdout

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,41 @@ print-type-size variant `Returned`: 1024 bytes
5858
print-type-size upvar `.t`: 1024 bytes
5959
print-type-size variant `Panicked`: 1024 bytes
6060
print-type-size upvar `.t`: 1024 bytes
61+
print-type-size type: `std::task::Context<'_>`: 32 bytes, alignment: 8 bytes
62+
print-type-size field `.waker`: 8 bytes
63+
print-type-size field `.local_waker`: 8 bytes
64+
print-type-size field `.ext`: 16 bytes
65+
print-type-size field `._marker`: 0 bytes
66+
print-type-size field `._marker2`: 0 bytes
67+
print-type-size type: `std::panic::Location<'_>`: 24 bytes, alignment: 8 bytes
68+
print-type-size field `.file_bytes_with_nul`: 16 bytes
69+
print-type-size field `.line`: 4 bytes
70+
print-type-size field `.col`: 4 bytes
71+
print-type-size type: `core::task::wake::ExtData<'_>`: 16 bytes, alignment: 8 bytes
72+
print-type-size variant `Some`: 16 bytes
73+
print-type-size field `.0`: 16 bytes
74+
print-type-size variant `None`: 0 bytes
75+
print-type-size field `.0`: 0 bytes
76+
print-type-size type: `std::panic::AssertUnwindSafe<core::task::wake::ExtData<'_>>`: 16 bytes, alignment: 8 bytes
77+
print-type-size field `.0`: 16 bytes
78+
print-type-size type: `std::pin::Pin<&mut {async fn body of a<[u8; 1024]>()}>`: 8 bytes, alignment: 8 bytes
79+
print-type-size field `.pointer`: 8 bytes
80+
print-type-size type: `std::pin::Pin<&mut {async fn body of b<[u8; 1024]>()}>`: 8 bytes, alignment: 8 bytes
81+
print-type-size field `.pointer`: 8 bytes
82+
print-type-size type: `std::pin::Pin<&mut {async fn body of c<[u8; 1024]>()}>`: 8 bytes, alignment: 8 bytes
83+
print-type-size field `.pointer`: 8 bytes
84+
print-type-size type: `std::pin::Pin<&mut {async fn body of test()}>`: 8 bytes, alignment: 8 bytes
85+
print-type-size field `.pointer`: 8 bytes
86+
print-type-size type: `std::ptr::DynMetadata<dyn std::any::Any>`: 8 bytes, alignment: 8 bytes
87+
print-type-size field `._vtable_ptr`: 8 bytes
88+
print-type-size field `._phantom`: 0 bytes
89+
print-type-size type: `std::ptr::NonNull<std::ptr::metadata::VTable>`: 8 bytes, alignment: 8 bytes
90+
print-type-size field `.pointer`: 8 bytes
91+
print-type-size type: `std::task::Poll<()>`: 1 bytes, alignment: 1 bytes
92+
print-type-size discriminant: 1 bytes
93+
print-type-size variant `Ready`: 0 bytes
94+
print-type-size field `.0`: 0 bytes
95+
print-type-size variant `Pending`: 0 bytes
96+
print-type-size type: `std::marker::PhantomData<*mut ()>`: 0 bytes, alignment: 1 bytes
97+
print-type-size type: `std::marker::PhantomData<dyn std::any::Any>`: 0 bytes, alignment: 1 bytes
98+
print-type-size type: `std::marker::PhantomData<fn(&()) -> &()>`: 0 bytes, alignment: 1 bytes

0 commit comments

Comments
 (0)