-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Approximate MatchTypes with lub of case bodies, if non-recursive #19761
Conversation
@mbovel @EugeneFlesselle @sjrd cc @nicolasstucki Do you remember why we don't approximate match types with the lub of their bodies? I thought I had done this experiment before, before Seb's reimplementation, proving how it's wrong. Doing the experiment now, it seems to work. So, is this wrong? I.e. unsound? |
I do not remember. |
At the very least, it does not correspond to anything that was ever specified or documented. Doing that would require a dedicated rule in the type system. Off the top of my head, I don't see why it would be unsound. But that's also assuming that type bounds are correctly checked in the bodies, which IIUC is not done yet? |
I believe so: |
I like the approach of caching the lub once during typing, much smarter. I'll try that change. |
I'm wondering however if doing the check during subtyping might make use of a narrowed context ? In any case, I think this would be a great improvement. |
@@ -2863,6 +2863,8 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling | |||
disjointnessBoundary(tp.effectiveBounds.hi) | |||
case tp: ErrorType => | |||
defn.AnyType | |||
case NoType => // ParamRef#superTypeNormalized can return NoType |
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.
That seems to be a problem with ParamRef#superTypeNormalized
rather than with disjointnessBoundary
.
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.
What should superTypeNormalized
do?
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.
It should return the declared type of the corresponding param, which is supposed to be its underlying
. I don't see a scenario in which superTypeNormalized
should ever return NoType
, except possibly for AnyKind
itself.
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.
Apparently, it can happen that it is not initialised:
https://github.com/lampepfl/dotty/blob/e994cf06eeee23e8a55a086907957e43140f2112/compiler/src/dotty/tools/dotc/core/Types.scala#L4690-L4695
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.
That sort of explains it, although it's still concerning that we're attempting to read it from provablyDisjoint
when it hasn't been initialized yet. Looks like a time bomb waiting to explode later due to weird compilation order issues.
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.
Yes, and this is not the only case, I ran into a similar issue where normalisation relies on the underlying
type, which is not always set as expected. For a TypeRef
, it goes through the denotation info, of which the completion seemed a bit unpredictable to me (heavily influenced by small changes in where things happen to be reduced).
Also (maybe) unrelated the normalization depends on the gadt ctx which doesn't seem to be reliably populated when using NamedType
s.
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.
I guess I should've opted for AnyKind rather than Any, as the more conservative approach.
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.
I would still be less uncomfortable if we specifically handled ParamRef
to deal with its superTypeNormalized
returning NoType
; instead of having this "catch-all" NoType
. That would limit the blast radius of this workaround. We should also clearly comment that it is a workaround.
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.
Sure thing.
And apply changes due to scala/scala3#19761
Fixes #19710