-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Change distribute or #1001
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
Change distribute or #1001
Conversation
As the comment explains, this is not sound.
The fix solves two cases where we had a deep subtype before.
This looks better, but we are still making the assumption that type aliases and type bounds are invariant.There are two cases where we can have covariant aliases:
val c: Iterable[A] with FromIterator[C] = ???
val d: Iterable[A] with FromIterator[D] = ???
val cget = c.get()
var dget = d.get()
dget = cget where the inferred type of Unfortunately, if we avoid following aliases when variance != 0, we end up with the same deep subtyping issues we had before. Note that the soundness bug is also present in master, because we assume that we can follow the lower bound of a |
I think we can fix this by:
Then we can safely follow type aliases. |
Can you complete the example to give an actual classcast exception? Would On Tue, Dec 15, 2015 at 9:05 PM, Guillaume Martres <notifications@github.com
Martin Odersky |
So the reason we end up with these types is that at some point we call |
Since And/Or type themselves are parameterless, their the union and intersection of hgiher-kinded types has to be treated specially: The types have to be pulled under a common lambda.
If splitProjections is set, it is more efficient that way.
4e3620e
to
8e257a6
Compare
Rebased to master. Review by @smarter. |
case prefix: AndType => | ||
def isMissing(tp: Type) = tp match { | ||
case tp: TypeRef => !tp.info.exists | ||
case _ => false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't isMissing
too restrictive? If we have (S & T)#A
, then S#A
might be an alias in S
, so derived1
may not return a TypeRef
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't understand. isMissing
is supposed to detect when a branch of an |/& does not have a member with the given name. If it is an alias then it does have a member, so it won't be missing anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nevermind, I misunderstood how this function worked.
* or `tp2`, or are 0 of the latter disagree. | ||
* - bounds `Bi` are the intersection of the corresponding type parameter bounds | ||
* of `tp1` and `tp2`. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add @pre tparams1.length == tparams2.length
or add an assert.
Otherwise LGTM, I can't break it anymore :). |
More changes to alias tests and rewriting of lubs.
Removes known unsoundness and makes previously seen deep subtypes go away. Review by @smarter.