the problem is when rust tries to find a implementation for a specific trait it goes through all impl blocks with all theoretically possible generic parameters
(well it does something logically equivalent, what i just described would take enough energy to boil the oceans, but lets ignore that)
for example if i have
impl<T> From<T> for Foo
and i write Foo::from(20i32)
the compiler would first generate the bound, Foo: From<i32>, then go through all the impls:
T = i128, Foo: From<i128>: WRONG
T = String, Foo: From<String> : WRONG
T = UdpSocket, from = Foo: From<UdpSocket> : WRONG
...
T = i32, Foo: From<i32> : RIGHT
...
and selects the implementation that was right, in this case there is only one such implementation, so the compiler is sound.
now lets imagine that your impl was accepted, and the compiler tries to prove the bound MyWidget: StatefulWidget, there are infinite lifetimes, and all lifetimes result in a implementation of the trait, so going through all the impls would look like this:
'a = 'static, MyWidget: StatefulWidget: RIGHT
'a = '1, MyWidget: StatefulWidget: RIGHT
'a = '2, MyWidget: StatefulWidget: RIGHT
...
'a = '∞, MyWidget: StatefulWidget: RIGHT
and now the compiler has an infinite amount of implementations to choose from, all of which are valid, so everything catches on fire and the sky turns green.
Why do I have to do PhantomData
i do not see any PhantomData in the example, i assume you did something like
struct MyWidget<'a> {
_marker: PhantomData<&'a ()>,
}
impl<'a> StatefulWidget for MyWidget<'a> {
...
}
that technically works, as all MyWidget now have a specific lifetime, and the implementation of StatefulWidget is for that lifetime, but it is too restrictive, and unlikely to do what you want (MyWidget would now be very difficult to move around or use with different states)
what you actually want is GATs, generic associated types:
trait StatefulWidget {
type State<'a>: ?Sized;
...
}
impl StatefulWidget for MyWidget {
type State<'a> = State<'a>;
...
}
the difference is that now there is not an infinite amount of implementations, there is a finite amount (1), but each implementations has a infinite amount of Sate associated types, one for each lifetime.