My issue is similar to this one How do I specify an associated type with a lifetime parameter?, although slightly different.
I know, that with use of generic associated type (GATs), I can do the following
trait Displayable {
type SomeState<'a>;
fn show(&self, data: &mut Self::SomeState<'_>) -> String;
}
struct ThirdPartyState<'a> {
title: &'a str,
}
struct MyMutableState<'a> {
third: ThirdPartyState<'a>,
buffer: Vec<u8>,
}
struct ArticleView;
impl Displayable for ArticleView {
type SomeState<'a> = MyMutableState<'a>;
fn show(&self, data: &mut MyMutableState<'_>) -> String {
format!("👋 {}, {}", data.third.title, data.buffer.len())
}
}
This works fine (playground)
However, both Displayable
and ThirdPartyState<'a>
are not mine, and the trait itself looks like so:
trait Displayable {
type SomeState;
fn show(&self, data: &mut Self::SomeState) -> String;
}
Is there any way to constrain lifetime inside this failing impl:
impl<'a> Displayable for ArticleView {
type SomeState = MyMutableState<'a>;
fn show(&self, data: &mut MyMutableState<'_>) -> String {
format!("👋 {}, {}", data.third.title, data.buffer.len())
}
}
Failing example in the playground.
Which obviously fails with:
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
--> src/main.rs:19:6
|
19 | impl<'a> Displayable for ArticleView {
| ^^ unconstrained lifetime parameter
I only see two options here to address this issue, even tho I would argue that none of them is ideal:
the first one by having :
impl Displayable for ArticleView {
type SomeState = MyMutableState<'static>;
fn show(&self, data: &mut MyMutableState<'_>) -> String {
format!("👋 {}, {}", data.third.title, data.buffer.len())
}
}
This fixes the error at this level, but it makes MyMutableState
only working with a &'static str
for ThirdPartyState
.
The second one, as first suggested by @GiM and @ChayimFriedman in their comment, required you to have a lifetime for ArticleView
:
Comment of @GiM :
@ChayimFriedman yeah adding lifetime (and phantom data) seems to work, although that doesn't seem like a great solution :/ play.rust-lang.org/?gist=66e4d23b7439ce60243201eb3509a953
So the result will be :
use std::marker::PhantomData;
struct ArticleView<'a> {
// Note that the version of @DiM use `phantom: PhantomData<&'a u32>` which has no difference except personal preferences
_phantom: PhantomData<&'a ()>,
}
impl<'a> Displayable for ArticleView<'a> {
type SomeState = MyMutableState<'a>;
fn show(&self, data: &mut MyMutableState<'_>) -> String {
format!("👋 {}, {}", data.third.title, data.buffer.len())
}
}
This unfortunately changes the way ArticleView
is constructed (ArticleView { _phantom: PhantomData }
instead of ArticleView
)
Otherwise, I actually don't thinks there is a way to constrains a lifetime to this impl
without being able to modify the trait
you want to implements