Skip to content

Higher-ranked lifetime causes inconsistent behavior with trait bounds. #34256

@pierzchalski

Description

@pierzchalski

Existing code uses trait bounds to force side-conditions on associated types. For instance, IntoIterator is defined (in part) as follows:

Original snippet from 2016 (no longer syntactically legal)
trait IntoIterator where Self::IntoIter::Item == Self::Item {
    type Item;
    type IntoIter: Iterator;
}
trait IntoIterator {
    type Item;
    type IntoIter: Iterator<Item = Self::Item>;
}

Similarly, we can define a side-condition using higher-ranked lifetimes:

trait BorrowIterator where for<'a> &'a Self: IntoIterator {}

This is necessary when we want to implement a trait for a (non-reference) type T, but want to require trait implementations on &'a T where those trait implementations can refer to the borrow lifetime 'a.

However, the former concrete trait bounds are usable as trait bounds in functions. For instance, the following will compile:

fn needs_iter<T: IntoIterator>(){}

Whereas this will fail:

fn needs_borrow_iter<T: BorrowIterator>(){}

With the error:

error: the trait bound `for<'a> &'a T: std::iter::Iterator` is not satisfied [--explain E0277]
  --> <anon>:19:1
19 |> fn needs_borrow_iter<T: BorrowIterator>()
   |> ^
note: `&'a T` is not an iterator; maybe try calling `.iter()` or a similar method
note: required because of the requirements on the impl of `for<'a> std::iter::IntoIterator` for `&'a T`
note: required by `BorrowIterator`

This is doubly puzzling since T: IntoIterator doesn't require T: Iterator.

See #34142 which shows similar issues with bounds on function definitions.
See #27113 which shows issues with 'outlives' relations in where-clauses.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-higher-rankedArea: Higher-ranked things (e.g., lifetimes, types, trait bounds aka HRTBs)A-lifetimesArea: Lifetimes / regionsA-type-systemArea: Type systemC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions