1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
use PhantomData;
/// Placeholder for a type parameter that a struct carries but never stores.
///
/// `PhantomData<fn(T) -> T>` is used instead of `PhantomData<T>` so the marker is `MaybeSend` /
/// `MaybeSync` even when `T` is not, and stays invariant in `T`.
/// For more detail: <https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns>
///
/// The marker still ties the struct's lifetime to `T`: `MarkerType<&'a U>` is not `'static`.
/// There is no way to avoid that. `PhantomData<X>: 'r` holds only if `X: 'r`, and the check is
/// structural over `X`, so every spelling that mentions `T` inherits `T`'s lifetime. The trait
/// object trick suggested in
/// <https://users.rust-lang.org/t/getting-phantomdata-to-have-a-static-lifetime/38505> does not
/// work either: `PhantomData<Box<dyn Fn(T) -> T + 'static>>` and
/// `PhantomData<*const (dyn Fn(T) -> T + 'static)>` are both rejected — a `dyn Trait + 'static`
/// object bound does not erase the lifetimes of the trait's own arguments.
///
/// The only real escape is to not name the type parameter on the struct at all. Operators carry it
/// because it would otherwise be an unconstrained impl parameter (E0207): in
/// `impl<'or, T0, T, E, OE, F> Observable<'or, T, E> for Map<OE, F> where OE: Observable<'or, T0, E>`
/// the source item type `T0` appears only in a where-clause trait bound, which does not constrain
/// it. Making `Observable` carry associated `Item` / `Err` types instead of generic parameters
/// would turn `T0` into the projection `OE::Item` and remove the marker from most adapters, the way
/// `std::iter::Map<I, F>` needs no marker. That is a crate-wide breaking change, it does not help
/// the operators whose parameter is chosen by the caller (`with_item_type::<T>`,
/// `with_error_type::<E>`, `collect::<C>`), and it makes things worse for `Create`, whose `T` / `E`
/// sit in the *input* type of its builder closure, which never constrains anything.
///
/// In practice the leak costs little: nearly every `T: 'static` bound in this crate comes from a
/// scheduler owning a value across a task, not from this marker, and where a marker does add a
/// lifetime the source observable already carries the same lifetime anyway.
pub type MarkerType<T> = ;
cfg_if!