rust/library/core/src
Jacob Pratt 9c1c0bfcb2
Rollup merge of #123203 - jkarneges:context-ext, r=Amanieu
Add `Context::ext`

This change enables `Context` to carry arbitrary extension data via a single `&mut dyn Any` field.

```rust
#![feature(context_ext)]

impl Context {
    fn ext(&mut self) -> &mut dyn Any;
}

impl ContextBuilder {
    fn ext(self, data: &'a mut dyn Any) -> Self;

    fn from(cx: &'a mut Context<'_>) -> Self;
    fn waker(self, waker: &'a Waker) -> Self;
}
```

Basic usage:

```rust
struct MyExtensionData {
    executor_name: String,
}

let mut ext = MyExtensionData {
    executor_name: "foo".to_string(),
};

let mut cx = ContextBuilder::from_waker(&waker).ext(&mut ext).build();

if let Some(ext) = cx.ext().downcast_mut::<MyExtensionData>() {
    println!("{}", ext.executor_name);
}
```

Currently, `Context` only carries a `Waker`, but there is interest in having it carry other kinds of data. Examples include [LocalWaker](https://github.com/rust-lang/rust/issues/118959), [a reactor interface](https://github.com/rust-lang/libs-team/issues/347), and [multiple arbitrary values by type](https://docs.rs/context-rs/latest/context_rs/). There is also a general practice in the ecosystem of sharing data between executors and futures via thread-locals or globals that would arguably be better shared via `Context`, if it were possible.

The `ext` field would provide a low friction (to stabilization) solution to enable experimentation. It would enable experimenting with what kinds of data we want to carry as well as with what data structures we may want to use to carry such data.

Dedicated fields for specific kinds of data could still be added directly on `Context` when we have sufficient experience or understanding about the problem they are solving, such as with `LocalWaker`. The `ext` field would be for data for which we don't have such experience or understanding, and that could be graduated to dedicated fields once proven.

Both the provider and consumer of the extension data must be aware of the concrete type behind the `Any`. This means it is not possible for the field to carry an abstract interface. However, the field can carry a concrete type which in turn carries an interface. There are different ways one can imagine an interface-carrying concrete type to work, hence the benefit of being able to experiment with such data structures.

## Passing interfaces

Interfaces can be placed in a concrete type, such as a struct, and then that type can be casted to `Any`. However, one gotcha is `Any` cannot contain non-static references. This means one cannot simply do:

```rust
struct Extensions<'a> {
    interface1: &'a mut dyn Trait1,
    interface2: &'a mut dyn Trait2,
}

let mut ext = Extensions {
    interface1: &mut impl1,
    interface2: &mut impl2,
};

let ext: &mut dyn Any = &mut ext;
```

To work around this without boxing, unsafe code can be used to create a safe projection using accessors. For example:

```rust
pub struct Extensions {
    interface1: *mut dyn Trait1,
    interface2: *mut dyn Trait2,
}

impl Extensions {
    pub fn new<'a>(
        interface1: &'a mut (dyn Trait1 + 'static),
        interface2: &'a mut (dyn Trait2 + 'static),
        scratch: &'a mut MaybeUninit<Self>,
    ) -> &'a mut Self {
        scratch.write(Self {
            interface1,
            interface2,
        })
    }

    pub fn interface1(&mut self) -> &mut dyn Trait1 {
        unsafe { self.interface1.as_mut().unwrap() }
    }

    pub fn interface2(&mut self) -> &mut dyn Trait2 {
        unsafe { self.interface2.as_mut().unwrap() }
    }
}

let mut scratch = MaybeUninit::uninit();
let ext: &mut Extensions = Extensions::new(&mut impl1, &mut impl2, &mut scratch);

// ext can now be casted to `&mut dyn Any` and back, and used safely
let ext: &mut dyn Any = ext;
```

## Context inheritance

Sometimes when futures poll other futures they want to provide their own `Waker` which requires creating their own `Context`. Unfortunately, polling sub-futures with a fresh `Context` means any properties on the original `Context` won't get propagated along to the sub-futures. To help with this, some additional methods are added to `ContextBuilder`.

Here's how to derive a new `Context` from another, overriding only the `Waker`:

```rust
let mut cx = ContextBuilder::from(parent_cx).waker(&new_waker).build();
```
2024-04-02 20:37:40 -04:00
..
alloc SeqCst->Relaxed in doc examples. 2024-03-19 15:27:11 +01:00
array Import the 2021 prelude in the core crate 2024-03-25 13:12:06 -07:00
ascii implement Default for AsciiChar 2024-02-13 12:04:44 +01:00
async_iter Step all bootstrap cfgs forward 2024-02-08 07:44:34 -05:00
cell Add some optimizations 2023-10-13 14:54:33 +02:00
char Auto merge of #122616 - Jules-Bertholet:casemappingiter-layout, r=Nilstrieb 2024-03-29 07:02:56 +00:00
cmp Use generic NonZero everywhere in core. 2024-02-22 15:17:33 +01:00
convert Import the 2021 prelude in the core crate 2024-03-25 13:12:06 -07:00
ffi step cfgs 2024-03-20 08:49:13 -04:00
fmt Rename Arguments::as_const_str to as_statically_known_str 2024-03-23 21:49:29 -07:00
future Use root obligation on E0277 for some cases 2024-03-03 18:53:35 +00:00
hash Add fn const BuildHasherDefault::new 2024-03-29 17:10:17 +01:00
intrinsics Rollup merge of #122935 - RalfJung:with-exposed-provenance, r=Amanieu 2024-04-02 20:37:39 -04:00
io BorrowedCursor docs clarification 2024-03-10 09:48:56 +01:00
iter Import the 2021 prelude in the core crate 2024-03-25 13:12:06 -07:00
macros Fix error message for env! when env var is not valid Unicode 2024-04-01 05:44:45 +01:00
mem Auto merge of #122582 - scottmcm:swap-intrinsic-v2, r=oli-obk 2024-03-23 13:57:55 +00:00
net Import the 2021 prelude in the core crate 2024-03-25 13:12:06 -07:00
num Rollup merge of #123226 - scottmcm:u32-shifts, r=WaffleLapkin 2024-04-02 21:22:01 +02:00
ops Extract helper, fix comment on DerefPure 2024-03-25 19:39:45 -04:00
panic add panic location to 'panicked while processing panic' 2024-03-23 09:44:04 +01:00
prelude Remove RustcEncodable/Decodable from 2024 prelude 2024-03-22 13:30:48 -07:00
ptr Rollup merge of #122935 - RalfJung:with-exposed-provenance, r=Amanieu 2024-04-02 20:37:39 -04:00
slice Auto merge of #122945 - andy-k:sorted-vec-example, r=jhpratt 2024-04-02 03:14:05 +00:00
str move assert_unsafe_preconditions to its own file 2024-03-23 18:44:17 +01:00
sync stabilize ptr.is_aligned, move ptr.is_aligned_to to a new feature gate 2024-03-29 19:59:46 -04:00
task set tracking issue 2024-04-02 15:45:53 -07:00
unicode Bump Unicode printables to version 15.1, align to unicode_data 2024-03-28 11:21:52 +01:00
any.rs Improve wording in std::any explanation 2024-03-29 10:10:52 -07:00
arch.rs Rust is a proper name: rust → Rust 2024-03-07 07:49:22 +01:00
ascii.rs Use generic NonZero internally. 2024-02-15 08:09:42 +01:00
asserting.rs [RFC 2011] Library code 2022-05-22 07:18:32 -03:00
bool.rs core is now compilable 2023-04-16 07:20:26 +00:00
borrow.rs doc: replace wrong punctuation mark 2023-07-28 14:46:17 +02:00
cell.rs Explain why we don't use intrinsics::is_nonoverlapping 2024-03-09 13:36:36 -05:00
clone.rs Add basic trait impls for f16 and f128 2024-03-28 15:02:51 -04:00
cmp.rs Auto merge of #118310 - scottmcm:three-way-compare, r=davidtwco 2024-04-02 19:21:44 +00:00
default.rs Add basic trait impls for f16 and f128 2024-03-28 15:02:51 -04:00
error.md Fix minor grammar typo 2023-09-06 09:47:22 -07:00
error.rs style library/core/src/error.rs 2024-03-02 16:03:23 +08:00
escape.rs Use generic NonZero internally. 2024-02-15 08:09:42 +01:00
hint.rs move assert_unsafe_preconditions to its own file 2024-03-23 18:44:17 +01:00
internal_macros.rs add track_caller for arith ops 2023-11-24 00:54:06 +08:00
intrinsics.rs Auto merge of #123385 - matthiaskrgr:rollup-v69vjbn, r=matthiaskrgr 2024-04-02 21:23:53 +00:00
lib.rs Auto merge of #123085 - tgross35:f16-f128-step4.0-libs-basic-impls, r=Amanieu 2024-03-30 21:58:49 +00:00
marker.rs warn against implementing Freeze 2024-03-31 22:15:48 +02:00
option.rs Import the 2021 prelude in the core crate 2024-03-25 13:12:06 -07:00
panic.rs Distinguish between library and lang UB in assert_unsafe_precondition 2024-03-08 18:53:58 -05:00
panicking.rs core/panicking: fix outdated comment 2024-03-23 21:36:22 +01:00
pin.rs chore: fix some comments 2024-03-27 22:32:53 +08:00
primitive.rs
primitive_docs.rs Use generic NonZero everywhere in core. 2024-02-22 15:17:33 +01:00
result.rs Import the 2021 prelude in the core crate 2024-03-25 13:12:06 -07:00
time.rs Implement Duration::as_millis_{f64,f32} 2024-03-14 01:37:12 +03:00
tuple.rs Rollup merge of #118307 - scottmcm:tuple-eq-simpler, r=joshtriplett 2024-02-11 08:25:41 +01:00
ub_checks.rs refactor check_{lang,library}_ub: use a single intrinsic, put policy into library 2024-03-23 18:45:05 +01:00
unit.rs Import the 2021 prelude in the core crate 2024-03-25 13:12:06 -07:00