Skip to content

Extending core::ops::Index to return non-references #2

Open
@shepmaster

Description

@shepmaster

Motivation

There are times where "indexing" is desired but returning a literal reference is suboptimal or impossible.

@cuviper said (lightly edited by me):

For example, ndarray would want to return ArrayView<'_, ..>. For mutable indexing, it would want ArrayViewMut<'_, ..>. GAT indexing would need a distinct type Output<'_> [for each mutability]. Currently, without GAT, they use slice and slice_mut methods.

We recognize that this requires GATs and something else to be able to truly supplant core::ops::Index and the [] syntax.

Details

A concrete example of the problem:

#![feature(generic_associated_types)]

fn main() {
    let c = Container(42);
    // Nightly
    let w = c.index(());
    // Desired, strawman syntax
    let w = &c[()];
    w.hello();
}

struct Wrapper<'a>(&'a u8);

impl Wrapper<'_> {
    fn hello(&self) {
        eprintln!("Hello, {}", self.0);
    }
}

struct Container(u8);

impl Index<()> for Container {
    type Output<'a> = Wrapper<'a>;

    fn index(&self, index: ()) -> Self::Output<'_> {
        Wrapper(&self.0)
    }
}

pub trait Index<Idx>
where
    Idx: ?Sized,
{
    type Output<'a>: ?Sized
    where
        Self: 'a;

    fn index(&self, index: Idx) -> Self::Output<'_>;
}

References in the wild

Related traits

These traits might also conceptually benefit from similar ability:

  • Deref
  • Borrow

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions