# Get waker vtable derived from \`Wake\` trait

**URL:** <https://internals.rust-lang.org/t/get-waker-vtable-derived-from-wake-trait/21485>\
**Category:** libs\
**Created:** [September 5, 2024, 11:36am UTC](https://internals.rust-lang.org/t/get-waker-vtable-derived-from-wake-trait/21485 "2024-09-05T11:36:33Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![wyfo](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/wyfo/32/10031_2.png) [@wyfo](https://internals.rust-lang.org/u/wyfo)\
**Post date:** [September 5, 2024, 11:36am UTC](https://internals.rust-lang.org/t/get-waker-vtable-derived-from-wake-trait/21485/1 "2024-09-05T11:36:33Z")

</div>

[Tracking Issue for `waker_getters` · Issue #96992 · rust-lang/rust · GitHub](https://github.com/rust-lang/rust/issues/96992) as well as [Stabilize `waker_getters` by kevinmehall · Pull Request #129919 · rust-lang/rust · GitHub](https://github.com/rust-lang/rust/pull/129919) have been merged today.

It allows notably to retrieve the vtable of a `Waker`, and that can be used for example to match on it and identify the current async runtime, as presented in this [comment](https://github.com/rust-lang/rust/issues/96992#issuecomment-1538244706). When I implemented asynchronous support in PyO3, I was also needing this feature (and I had to use a dirty hack based on TLS while waiting for it).

However, to avoid useless unsafe code, I'm using the `Wake` trait to craft my coroutine runtime `Waker`, and there's the rub... I cannot use `waker_getters` feature because I don't have access to the vtable of the wakers derived from `Arc<W> where W: Wake`. **The `waker_getters` feature is quite unusable with `Arc<W> where W: Wake`.**

I tried two times ([here](https://github.com/rust-lang/rust/issues/96992#issuecomment-1835665839) and [here](https://github.com/rust-lang/rust/issues/96992#issuecomment-2041233153)) to highlight this problem in the issue, proposing two different ways of making the feature compatible with the `Wake` trait, but my attempts were kind of ignored. So I make a new attempt here.

A possible solution to the problem could be this implementation:

```rust
impl<W: Wake + Send + Sync + 'static> Arc<W> {
    const fn waker_vtable() -> &'static RawWakerVTable { /*...*/ }
}

```

It could also be done with an extension trait, something like:

```rust
pub trait WakeExt: Wake + Send + Sync + 'static {
    /// Vtable of waker derived from `Arc<Self>`.
    fn waker_vtable() -> &'static RawWakerVTable { /*...*/ }
    fn try_from_waker(waker: Waker) -> Result<Arc<Self>, Waker> { /*...*/ }
    fn try_from_waker_ref(waker: &Waker) -> Result<&Self, &Waker> { /*...*/ }
}
impl<W: Wake + Send + Sync + 'static> WakeExt for W {}

```

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [September 5, 2024, 6:13pm UTC](https://internals.rust-lang.org/t/get-waker-vtable-derived-from-wake-trait/21485/2 "2024-09-05T18:13:52Z")

</div>

> [@wyfo](#):
>
> A possible solution to the problem could be this implementation:

Unfortunately, this doesn't work like you want it to, and would be a massive footgun to expose in this way. Even though you have `const fn` returning `&'static`, since the static storage relies on constant promotion, calling the function twice may return a reference to different addresses\[1\]. If the address is semantically meaningful, you _must_ use a `static` (or only operationally create the value a single time). And it's not possible to have a generic `static` (nor to create references to `static` within `const fn`).

* * *

1. Within a single codegen unit, the value is most likely to only exist once. However, across multiple codegen units, the function may get monomorphized more than once for one of various different reasons, creating multiple compiled versions of the function each with their own copy of the promoted static data. In the worst case, these copies are in different lazy loaded dynamic libraries and fundamentally can't be unified with each other.

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jrose/32/9591_2.png) [@jrose](https://internals.rust-lang.org/u/jrose)\
**Post date:** [September 5, 2024, 7:50pm UTC](https://internals.rust-lang.org/t/get-waker-vtable-derived-from-wake-trait/21485/3 "2024-09-05T19:50:52Z")

</div>

And conversely, though it is pretty unlikely for a waker, if two functions have identical behavior, some optimization modes might unify them, and then the vtables might get unified too. So you could have false negatives _and_ false positives.

---

<div class="post-metadata">

**Author:** ![wyfo](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/wyfo/32/10031_2.png) [@wyfo](https://internals.rust-lang.org/u/wyfo)\
**Post date:** [September 6, 2024, 11:56am UTC](https://internals.rust-lang.org/t/get-waker-vtable-derived-from-wake-trait/21485/4 "2024-09-06T11:56:18Z")

</div>

Thank you for your answers, which perfectly explains the problem. So I guess I will have to define my own vtable with some `unsafe`, but I'm fine with this justification.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [September 6, 2024, 1:32pm UTC](https://internals.rust-lang.org/t/get-waker-vtable-derived-from-wake-trait/21485/5 "2024-09-06T13:32:10Z")

</div>

(NOT A CONTRIBUTION)

On the other hand, I believe `RawWakerVTable` could have a constructor that is parameterized by `W: Wake` and takes no arguments. Users could use this to define the static for their `Wake` type without writing any unsafe code.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [February 28, 2026, 1:33pm UTC](https://internals.rust-lang.org/t/get-waker-vtable-derived-from-wake-trait/21485/8 "2026-02-28T13:33:09Z")

</div>

This topic was automatically closed 540 days after the last reply. New replies are no longer allowed.
