Pre-RFC: typed context injection

After thinking a bit more about my proposal for "capabilities" emulation through NamedCx, I realize that my solution is terribly unsound.

I assume that I can uphold an invariant that all NamedX objects with the same namespace ocurring in a CxRaw will have the same pointee type, making it sound to write:

struct MyNamespace;

fn consumer<T, V>(cx: Cx<NamedMut<'_, MyNamespace, T>, NamedMut<'_, MyNamespace, V>>) {
    let value: &mut T = cx;
    let value: &mut V = cx;
    // This should be sound because `T` and `V` should have been specified as
    // the same type in order to construct `CxRaw`.
}

Unfortunately, while this invariant is easy to uphold on its own, it breaks down when combining the feature with AnyCx merging:

fn merge<L: AnyCx, R: AnyCx>(left: L, right: R) -> Cx<L, R> {
    // Previously, I asserted that this would work because distinct generic parameters
    // are assumed not to alias.
    Cx::new((left, right))
}

fn caller(cx_a: CxMut<NamedMut<'_, MyNamespace, *mut u32>>, cx_b: CxMut<NamedMut<'_, MyNamespace, Box<u32>>>) {
    // Unfortunately, this allows us to break our oh-so-important invariant.
    let merged = merge(cx_a, cx_b);

    // Oh no! We just transmuted some random `*mut u32` into a `Box<u32>`!
    consumer::<u32, i32>(merged);
}

Luckily, there's a much easier way to solve the original problem: use the tried-and-true bundle type technique. Best of all, it doesn't require any complex additions to the existing proposal!

trait HasLogger {
    type Logger: Logger;
}

trait HasDatabase {
    type Database: Database;
}

trait HasTracing {
    type Tracing: Tracing;
}

trait HasBundleForCx1: HasLogger + HasDatabase {}

type Cx1<'a, B> = Cx<
    &'a mut <B as HasLogger>::Logger>,
    &'a mut <B as HasDatabase>::Database,
>;

trait HasBundleForCx2: HasLogger + HasTracing {}

type Cx2<'a, B> = Cx<
    &'a mut <B as HasLogger>::Logger,
    &'a mut <B as HasDatabase>::Tracing,
>;

type ParentCx<'a, B> = Cx<Cx1<'a, B>, Cx2<'a, B>>;

trait HasBundleForParent: HasBundleForCx1 + HasBundleForCx2 {}

fn consumer<B: ?Sized + HasBundleForParent>(cx: ParentCx<'_, B>) {
    let logger: &mut B::Logger = cx;
    let tracing &mut B::Tracing = cx;

    // This already works because of the no-alias assumptions.
    let _ = (logger, tracing);
}

fn caller(cx: Cx<&mut MyLogger, &mut MyDatabase, &mut MyTracing>) {
    consumer::<
        // We'll likely have to augment `Cx`'s inference system to allow
        // this to be inferred automatically.
        dyn HasBundleForParent<
            Logger = MyLogger,
            Database = MyDatabase,
            Tracing = MyTracing,
        >,
    >(cx);
}

I have no clue what I was thinking earlier today.