I am facing a problem that can be demonstrated as follows. In the code below, the generic associated type (Machine::Datum<'a>
) for MyMachine
is MyDatum<'a>
. For all 'a
, MyDatum<'a>
implements MaybeString<'a
>`:
impl<'a> MaybeString<'a> for MyDatum<'a> { /* … */ }
Yet for<'a> <M as Machine>::Datum<'a>: MaybeString<'a>
is not fulfilled when M
is MyMachine
.
Here is the code example:
#![feature(generic_associated_types)]
struct MyDatum<'a> {
s: &'a str,
}
trait MaybeString<'a> {
fn get_str(&self) -> Option<&'a str>;
}
impl<'a> MaybeString<'a> for MyDatum<'a> {
fn get_str(&self) -> Option<&'a str> {
Some(self.s)
}
}
trait Machine {
type Datum<'a>;
}
struct MyMachine {}
impl Machine for MyMachine {
type Datum<'a> = MyDatum<'a>;
}
fn run<M>(m: M)
where
M: Machine,
for<'a> <M as Machine>::Datum<'a>: MaybeString<'a>,
{
}
fn main() {
run(MyMachine {});
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `for<'a> <_ as Machine>::Datum<'a>: MaybeString<'a>` is not satisfied
--> src/main.rs:35:5
|
35 | run(MyMachine {});
| ^^^ the trait `for<'a> MaybeString<'a>` is not implemented for `<_ as Machine>::Datum<'a>`
|
note: required by a bound in `run`
--> src/main.rs:30:40
|
27 | fn run<M>(m: M)
| --- required by a bound in this
...
30 | for<'a> <M as Machine>::Datum<'a>: MaybeString<'a>,
| ^^^^^^^^^^^^^^^ required by this bound in `run`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error
Am I expecting too much from the compiler to recognize this? What can I do? Add a bound for each lifetime that I actually need/use?
Not sure of that's even possible with(out?) introducing bogus lifetime arguments to the function.
Update: Doesn't work, because a lifetime given as argument must live as long as the function runs, see details below:
Details
#![feature(generic_associated_types)]
struct MyDatum<'a> {
s: &'a str,
}
trait MaybeString<'a> {
fn from_str(s: &'a str) -> Self;
fn get_str(&self) -> Option<&'a str>;
}
impl<'a> MaybeString<'a> for MyDatum<'a> {
fn from_str(s: &'a str) -> Self {
MyDatum { s }
}
fn get_str(&self) -> Option<&'a str> {
Some(self.s)
}
}
trait Machine {
type Datum<'a>;
}
struct MyMachine {}
impl Machine for MyMachine {
type Datum<'a> = MyDatum<'a>;
}
fn run<'a1, M>(_m: M)
where
M: Machine,
//<M as Machine>::Datum<'static>: MaybeString<'static>,
<M as Machine>::Datum<'a1>: MaybeString<'a1>,
{
//let s = "Static";
//let _ = <M as Machine>::Datum::<'_>::from_str(s);
let s1_string = "Non-static".to_string();
let s1 = &s1_string;
let _ = <M as Machine>::Datum::<'_>::from_str(s1);
}
fn main() {
run(MyMachine {});
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0597]: `s1_string` does not live long enough
--> src/main.rs:40:14
|
31 | fn run<'a1, M>(_m: M)
| --- lifetime `'a1` defined here
...
40 | let s1 = &s1_string;
| ^^^^^^^^^^ borrowed value does not live long enough
41 | let _ = <M as Machine>::Datum::<'_>::from_str(s1);
| ----------------------------------------- argument requires that `s1_string` is borrowed for `'a1`
42 | }
| - `s1_string` dropped here while still borrowed
For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground` due to previous error
It looks like I need a HRTB here. But the compiler doesn't recognize that MyMachine
fulfills it.