You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Associated type behind a *mut unecessarily results in invariant subtyping #68375
cast_array_view fails to compile with the first definition of ptr, and succeeds with the second, despite the two functions being apparently identical.
I think the reason this is happening is most likely related to the fact that subtyping of *mutpointers is invariant on the type of their parameter, and structs containing *mut T pointers are invariant with respect to T. Since D::Elem is being stored behind a *mut pointer rustc has decided that ArrayBase is invariant with respect to D, instead of D::Elem.
PS: Thanks to /u/Patryk27 on reddit for looking at this and pointing me in the direction of the variance docs.
Using associated types always results in an invariant type bound, so that's where the invaraince is coming from. Also *mut T is invariant in T, as you noted, but this doesn't make ArrayBase<D> invariant in D, only invariant in D::Elem. But the fact that you used D::Elem makes it invariant in D.
Because there is no general way to figure out the lifetime relationships between the associated type and Self. So invariance is the only safe variance.
Is this documented somewhere? Maybe it should be added to the variance section of the nomicon?
I'm not sure, I just came across this in much the same way you did. It should be added to the nomicon (and the reference while we're at it).
I tend to agree with your conclusion that that suggests it would be possible to do better.
Actually trying to use that in real code (ndarray) results in me running into a different issue, which I believe is a version of #28895. I've added a minimized example to that issue.
Activity
RustyYato commentedon Jan 20, 2020
Using associated types always results in an invariant type bound, so that's where the invaraince is coming from. Also
*mut Tis invariant inT, as you noted, but this doesn't makeArrayBase<D>invariant inD, only invariant inD::Elem. But the fact that you usedD::Elemmakes it invariant inD.To get around this:
This allows Rust to reason about the variance of each parameter separately, which allows the code to pass
gmorenz commentedon Jan 20, 2020
Huh, ok. That leaves two questions
RustyYato commentedon Jan 20, 2020
Because there is no general way to figure out the lifetime relationships between the associated type and
Self. So invariance is the only safe variance.I'm not sure, I just came across this in much the same way you did. It should be added to the nomicon (and the reference while we're at it).
RustyYato commentedon Jan 20, 2020
Oh, you don't need the type alias. This works
This leads me to believe that we maybe could allow for a more lenient variance for associated types.
gmorenz commentedon Jan 20, 2020
I tend to agree with your conclusion that that suggests it would be possible to do better.
Actually trying to use that in real code (ndarray) results in me running into a different issue, which I believe is a version of #28895. I've added a minimized example to that issue.