Skip to main content

Lower

Trait Lower 

Source
pub trait Lower<'short, T: ?Sized, Lifetime: Sealed = BoundTo<&'short Self>> {
    type Proxy: Deref<Target = T>;

    // Required method
    fn lower(&'short self) -> Self::Proxy;
}
Expand description

For some problems, neither std::ops::Deref nor Reborrow alone are sufficient. This can occur in cases where

  1. A ?Sized without lifetimes type is desired for a clean API.
  2. A container cannot implement Deref to a target type.

As a concrete example, consider the following:

use diskann_utils::Reborrow;

// A type participating in generalized references.
enum ThisOrThat {
    This(Vec<f32>),
    That(Vec<f64>),
}

enum ThisOrThatView<'a> {
    This(&'a [f32]),
    That(&'a [f64]),
}

impl<'a> Reborrow<'a> for ThisOrThat {
    type Target = ThisOrThatView<'a>;
    fn reborrow(&'a self) -> Self::Target {
        match self {
            Self::This(v) => ThisOrThatView::This(&*v),
            Self::That(v) => ThisOrThatView::That(&*v),
        }
    }
}

// We have a function taking a `?Sized` type.
fn takes_unsized<T: ?Sized>(_: &T) {}

fn calls_unsized<'a, U, T: ?Sized>(x: &'a U) {
    // How do I call `takes_unsized`?
}

The question we’re trying to answer is: how do we make a trait that allows both

  • calls_unsized::<'a, Vec<f32>, [f32]>
  • calls_unsized::<'a, ThisOrThat, ThisOrThatView<'a>>

Observe that Vec<f32> can use Deref to get to [f32], but no such implementation is possible for ThisOrThat.

§Lower

The Lower trait solves this problem by first lowering U to a proxy type that is then dereferencable to T. To solve the above example:






use diskann_utils::reborrow::Lower;

fn calls_unsized<'a, U, T: ?Sized>(x: &'a U)
where
    U: Lower<'a, T>,
{
    takes_unsized::<T>(&x.lower())
}

impl<'short> Lower<'short, ThisOrThatView<'short>> for ThisOrThat {
    type Proxy = diskann_utils::reborrow::Place<ThisOrThatView<'short>>;
    fn lower(&'short self) -> Self::Proxy {
        diskann_utils::reborrow::Place(self.reborrow())
    }
}

fn with_vec(x: &Vec<f32>) {
    calls_unsized::<Vec<f32>, [f32]>(x)
}

fn with_this_or_that<'a>(x: &'a ThisOrThat) {
    calls_unsized::<'a, ThisOrThat, ThisOrThatView<'a>>(x)
}

Note the use of [diskann_utils::reborrow::Place] to create a type that dereferences to the contained value.

Required Associated Types§

Source

type Proxy: Deref<Target = T>

The type of the proxy that dereferences to the target.

Required Methods§

Source

fn lower(&'short self) -> Self::Proxy

Cheaply lower self to its proxy type.

Implementations on Foreign Types§

Source§

impl<'a, T> Lower<'a, [T]> for Vec<T>

Source§

type Proxy = &'a [T]

Source§

fn lower(&'a self) -> Self::Proxy

Source§

impl<'a, T> Lower<'a, T> for Cow<'_, T>
where T: ToOwned + ?Sized,

Source§

type Proxy = &'a T

Source§

fn lower(&'a self) -> Self::Proxy

Source§

impl<'a, T> Lower<'a, T> for Box<T>
where T: ?Sized,

Source§

type Proxy = &'a T

Source§

fn lower(&'a self) -> Self::Proxy

Implementors§