---
# System prepended metadata

title: '#[refine] user stories'

---

# #[refine] user stories

## All the things we might want to test

Features:

- [ ] Impl trait in return position
- [ ] Impl trait in argument position
- [ ] Where clause refinement
- [ ] Lifetime refinement (explicit)
- [ ] Lifetime refinement (elided)
- [ ] Safe refinement of unsafe method
- [ ] Return type bounds
- [ ] (Extension) Adding generic arguments

Variations:

- [ ] Warn-by-default vs allow-by-default vs error-by-default
- [ ] Current lifetime behavior (refinement allowed but unusable)
- [ ] Refinement allowed and usable without `#[refine]`
- [ ] Allow `#[refine]` on individual arguments, return types, or where clauses
- [ ] `#[refine('a, ExactSizeIterator)]`
- [ ] RPIT captures all lifetimes in scope

Scenarios:

- [x] Adding impl Trait bounds to a trait method's return type
- [ ] Using a concrete type in place of `-> impl Trait`
- [x] Making code generic that already depends on `#[refine]`
- [ ] Migrating from RPITIT to associated type, or vice versa
- [ ] `impl From<&u32>` requires a named lifetime
- [ ] Surprising refinement: Carelessly putting a concrete type
- [ ] Surprising refinement: Subtle elided lifetime mismatch
- [ ] Surprising refinement: Missing where clause 

## TODO: scenario of a breaking change involving lifetimes

## Scenario: Refining a return type using `-> impl Trait`

Let's say the standard library defines the following `IntoIter` trait.

```rust
trait IntoIter {
    type Item;
    fn into_iter(self) -> impl Iterator<Item = Self::Item>;
}
```

A library maintainer creates a very simple data structure, `MyVec`, that is internally based on the `Vec` type. 
    
```rust
pub struct MyVec<T> {
    inner: Vec<T>,
}

impl<T> MyVec<T> {
    pub fn new() -> MyVec<T> { ... }
    pub fn push(&mut self, elem: T) { ... }
    pub fn len(&self) -> usize { ... }
}
```

The maintainer then implements the `Iterable` trait for `MyVec`.

```rust
impl<T> IntoIter for MyVec<T> {
    type Item = T;
    fn iter(self) -> impl Iterator<Item = T> {
        self.inner.into_iter()
    }
}
```

Later, she realizes that she wants to expose the `rev` operation to reverse an iterator. This operation is only available on the `DoubleEndedIterator` trait, which inherits from `Iterator`.

```rust
for item in my_vec.into_iter().rev() {
    //                         ^^^
    // error: the trait bound `impl Iterator<Item = T>: DoubleEndedIterator`
    //        is not satisfied
    ...
}
```

Since the iterator for `Vec` already exposes this functionality, she simply changes the signature on her `IntoIter` implementation to reflect this. This results in a different compiler error.

```rust
impl<T> IntoIter for MyVec<T> {
    type Item = T;
    fn iter(self) -> impl DoubleEndedIterator<Item = T> {
        //                ^^^^^^^^^^^^^^^^^^^
        // error: impl return type does not match the return type in the trait
        // note: expected `impl Iterator<Item = T>`, saw `impl DoubleEndedIterator<Item = T>`
        // note: consider changing the signature:
        //     fn iter(self) -> impl Iterator<Item = T> {
        //                           ^^^^^^^^
        // note: consider adding `#[refine]`:
        //     #[refine]
        //     +++++++++
        //     fn iter(self) -> impl DoubleEndedIterator<Item = T> {
        self.inner.into_iter()
    }
}
```

Following the second suggestion, the maintainer adds `#[refine]` to the method signature, and everything compiles.

```rust
impl<T> IntoIter for MyVec<T> {
    type Item = T;
    #[refine]
    fn iter(self) -> impl DoubleEndedIterator<Item = T> {
        self.inner.into_iter()
    }
}
```

## Scenario: Unexpected Erasure of Refined Information

A library maintainer writes a trait and trait implementation like this:

```rust
trait IntoErasedIterator {
  fn into_erased_iter(self) -> impl Iterator;
}
impl<T> IntoErasedIterator for Vec<T> {
  #[refine]
  fn into_erased_iter(self) -> impl ExactSizeIterator {
    self.into_iter()
  }
}
```

A library user then uses the refined information like this when the receiver type is known:

```rust
fn main() {
  let x = vec![1, 2, 3];
  let it = x.into_erased_iter();
  println!("{}", it.len());
}
```

However, they then decide to refactor their code and erased the refined information via impl Trait in argument position: 

```rust
fn main() {
  let x = vec![1, 2, 3];
  extracted(x);
}
fn extracted(x: impl IntoErasedIterator) {
  let it = x.into_erased_iter();
  println!("{}", it.len()); // error: it does not have method `len`
}
```

And now this unexpectedly causes a compiler error.
