I'm trying to use HRTBs to express that a value passed to a function implements a trait for any reference to the value. The actual use case is on a trait impl, but it's simpler to demonstrate with functions.
It looks almost exactly like #56556, but that issue has been closed, and at least some of the examples on the issue no longer fail.
I can't decide if this is just an edge case that fix didn't cover, or if this is one of those situations where the lifetimes in the type are causing issues and I am just not seeing where.
pub trait Trait {}
impl<'a, T> Trait for &'a T where T: Trait {}
impl<'a> Trait for &'a str {}
fn check_hrtb<T>(_: T)
where
for<'a> &'a T: IntoIterator,
for<'a> <&'a T as IntoIterator>::Item: Trait,
{
}
fn check<'a, T>(_: T)
where
T: 'a,
&'a T: IntoIterator,
<&'a T as IntoIterator>::Item: Trait,
{
}
fn main() {
check(["hi"]); // Works
check_hrtb(["hi"]); // Fails with error below
}
Output:
error[E0277]: the trait bound `for<'a> <&'a _ as IntoIterator>::Item: Trait` is not satisfied
--> src/main.rs:24:16
|
24 | check_hrtb(["hi"]);
| ---------- ^^^^^^ the trait `for<'a> Trait` is not implemented for `<&'a _ as IntoIterator>::Item`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `Trait`:
&'a T
&'a str
note: required by a bound in `check_hrtb`
--> src/main.rs:10:44
|
7 | fn check_hrtb<T>(_: T)
| ---------- required by a bound in this
...
10 | for<'a> <&'a T as IntoIterator>::Item: Trait,
| ^^^^^ required by this bound in `check_hrtb`
I had a follow-up thought that maybe this is because your concrete implementation was for &str when the bounds on the check need &&str (i.e. they have to go through the blanket &-lifting implementation). But implementing on &&str (or str) directly doesn't help, so I guess that's not it.
The complier should handle this case IMO, since all I did is supply the type of the parameter (minus a lifetime even). Your use-case is a bit different from the minimum examples in that issue, so maybe file a new issue or ask in the issue if they think it's the same problem.
If you want to keep the ergonomics, you can move your higher-ranked function/method bounds onto a trait of their own. The compiler seems to do better when handles inference first and then checks HRTB, versus trying to infer underneath a HRTB. Unfortunately it requires a lot of boiler-plate for patterns like these.
I discovered the actual problem I was having was totally unrelated, and this issue was purely from how I attempted to reduce the original issue for the question.
Which now I can obviously see didn't work because Value has to be the same for any 'a. Not sure why I didn't see that immediately.
The solution was to just get rid of Value and suffer the fully qualified associated type syntax (for<'a> <<&'a Values as IntoIterator>::Item as Pair>::First), but I was experimenting on a function and not the impl which is when I hit the issue that this thread ended up being about. When I just tried it on the impl it worked fine.
That workaround is interesting though. I'm sure it will come in handy at some point, thank you for sharing it!