-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Variance should perhaps take into account 'static bounds. #59875
Comments
Similar problem to #57440. Possible workaround from that: struct Ptr<T: ?Sized + Pointee, U = <T as Pointee>::Meta> {
addr: usize,
meta: U,
t: std::marker::PhantomData<T>,
} |
@philipc Ahahahaha, that is clever, I love it! I'll try it and report back. |
Yes, this compiles: struct Ptr<T: ?Sized + Pointee<Meta = Meta>, Meta: 'static + Copy = <T as Pointee>::Meta> {
addr: usize,
meta: Meta,
_marker: std::marker::PhantomData<T>,
}
trait Pointee {
type Meta: 'static + Copy;
}
impl<T> Pointee for T {
type Meta = ();
}
impl<T> Pointee for [T] {
type Meta = usize;
}
fn covariant<'a>(p: Ptr<&'static ()>) -> Ptr<&'a ()> { p } |
Annoyingly enough, wrapping struct Newtype<'a>(Ptr<&'a ()>);
fn covariant_newtype<'a>(p: Newtype<'static>) -> Newtype<'a> { p } I believe this is because variance computation doesn't normalize? EDIT: this definition is covariant, OTOH (despite being equivalent): struct Newtype<'a>(Ptr<&'a (), ()>); |
I tried playing with something similar to fix another invariance problem I encountered, and I think there is another small problem with this workaround:
Users can still implement this by specifying the actual
(I don't know if that's relevant, but seems worth pointing out since that's another argument for allowing the variance in the issue. Also if you think there's another workaround I'm really interested to know!) |
This logic is flawed. Subtyping isn’t only about lifetimes, e.g. HRTB-like fn-pointer (or alternatively trait objects) types come into play, too. trait Pointee {
type Meta: 'static + Copy;
}
struct SomethingStatic<T: 'static>(T);
impl<T> Pointee for SomethingStatic<T> {
type Meta = fn(T);
}
struct CovariantPtr<T>(T);
fn demonstrate_subtyping(
x: CovariantPtr<SomethingStatic<for<'a> fn(&'a str)>>,
) -> CovariantPtr<SomethingStatic<fn(&'static str)>> {
x
} If |
Heh, I guess that was back when we still had hope to remove or weaken that subtyping relationship (cc @nikomatsakis). If we have to keep it, I agree there's no fix here (short of variance annotations on |
In my experiments, GATs are not very useful without variance annotations. I'm not sure of a good design, but some sort of variance annotations should be seriously considered. |
For example, when trying to build something resembling a pointer w/ optional metadata:
Ptr<T>
ends up invariant overT
even though lifetimes inT
cannot possibly affectT::Meta
(which has a'static
bound), and that results in errors like these:cc @rust-lang/wg-traits
The text was updated successfully, but these errors were encountered: