-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Type member inference issue #6199
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
Comments
I had a long look at this. The root cause is that we don't support existential types anymore. To see why, let's try to answer the question: What is the type of
But if you actually try to give the parameter type of the argument Dotty, not having existential types uses an "avoidance"algorithm instead. Since the result type To fix this, the program should be rewritten so that parameter types could be given explicitly. If you can write them explicitly, there's a good chance they can be inferred as well. Both of the following would work:
As a way to improve the situation we plan to improve support for stable values. I.e. we would provide ways to declare a method like |
Is there going to be an automatic rewrite for things like this?
…On Mon, Apr 1, 2019, 8:38 AM odersky ***@***.***> wrote:
I had a long look at this. The root cause is that we don't support
existential types anymore.
To see why, let's try to answer the question: What is the type of unit.bar
?
scalac said: _1.State => _1.State where _1 is hypothetical value of type
Foo.
But if you actually try to give the parameter type of the argument bar =>
bar explicitly, it does not work, since _1.State is not a legal type you
can write. So something fishy is going on here.
Dotty, not having existential types uses an "avoidance"algorithm instead.
Since the result type Bar[_1.State]is not expressible, it has to be
approximated from below (since it is argument position). That's what gives
Nothing.
To fix this, the program should be rewritten so that parameter types could
be given explicitly. If you can write them explicitly, there's a good
chance they can be inferred as well.
Both of the following would work:
- Make unit a val instead of a def, or
- Make unit have to Foo { type State = Any }
As a way to improve the situation we plan to improve support for stable
values. I.e. we would provide ways to declare a method like unit stable,
which means it will be treated like a val in paths. That would then be a
third way to make the program compile.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#6199 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAGAUBHPIewi2dKzJtc7ujtDCPAabalWks5vcf3VgaJpZM4cVPsY>
.
|
I think the scheme we used for as-seen-from before 91ee02f supported this kind of usecase. It has a complexity cost but if this pattern is prevalent enough it might be worth bringing back a variant of it. |
I'm pretty sure I use it in multiple places
…On Mon, Apr 1, 2019 at 12:22 PM Guillaume Martres ***@***.***> wrote:
I think the scheme we used for as-seen-from before 91ee02f
<91ee02f>
supported this kind of usecase. It has a complexity cost but if this
pattern is prevalent enough it might be worth bringing back a variant of it.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#6199 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAGAUCf2Bw63pFKGdowjWaDpu8ZpngYXks5vcjJegaJpZM4cVPsY>
.
|
So, removal of existentials means that any path-dependent type whose path prefix is not present as a bound val in scope just can't be interacted with meaningfully anymore? |
Prior to scala@91ee02f, unstable prefixes appearing in selection types were handled in a two-pass approach which can be summarized as: 1. Type the selection with the unstable prefix, if this prefix appears in a position where it cannot be widened away, mark it with a special annotation. 2. If the result of the selection contains this annotation, retype it after having wrapped its prefix in a skolem. This got replaced by the use of an `ApproximatingTypeMap` which can always construct a valid (but potentially approximated) type for the selection. Most of the time this is all we need but there are some cases where skolemizing the prefix is still useful as witnessed by the tests added in this commit. They are now handled by unconditionally skolemizing unstable prefixes. To avoid any potential performance impact from this, we teach `asSeenFrom` to always widen these prefixes first and only make use of the skolem to avoid returning an approximation. Since this almost never occurs (it happens only once when compiling Dotty) this means we incur almost no extra cost (the skolem itself still needs to be allocated unconditionally in advance, this cannot be delegated to `asSeenFrom` because it's supposed to be an idempotent operation and each skolem is unique).
Prior to scala@91ee02f, unstable prefixes appearing in selection types were handled in a two-pass approach which can be summarized as: 1. Type the selection with the unstable prefix, if this prefix appears in a position where it cannot be widened away, mark it with a special annotation. 2. If the result of the selection contains this annotation, retype it after having wrapped its prefix in a skolem. This got replaced by the use of an `ApproximatingTypeMap` which can always construct a valid (but potentially approximated) type for the selection. Most of the time this is all we need but there are some cases where skolemizing the prefix is still useful as witnessed by the tests added in this commit. They are now handled by unconditionally skolemizing unstable prefixes. To avoid any potential performance impact from this, we teach `asSeenFrom` to always widen these prefixes first and only make use of the skolem to avoid returning an approximation. Since this almost never occurs (it happens only once when compiling Dotty) this means we incur almost no extra cost (the skolem itself still needs to be allocated unconditionally in advance, this cannot be delegated to `asSeenFrom` because it's supposed to be an idempotent operation and each skolem is unique).
Prior to scala@91ee02f, unstable prefixes appearing in selection types were handled in a two-pass approach which can be summarized as: 1. Type the selection with the unstable prefix, if this prefix appears in a position where it cannot be widened away, mark it with a special annotation. 2. If the result of the selection contains this annotation, retype it after having wrapped its prefix in a skolem. This got replaced by the use of an `ApproximatingTypeMap` which can always construct a valid (but potentially approximated) type for the selection. Most of the time this is all we need but there are some cases where skolemizing the prefix is still useful as witnessed by the tests added in this commit. They are now handled by unconditionally skolemizing unstable prefixes. To avoid any potential performance impact from this, we teach `asSeenFrom` to always widen these prefixes first and only make use of the skolem to avoid returning an approximation. Since this almost never occurs (it happens only once when compiling Dotty) this means we incur almost no extra cost (the skolem itself still needs to be allocated unconditionally in advance, this cannot be delegated to `asSeenFrom` because it's supposed to be an idempotent operation and each skolem is unique).
Prior to scala@91ee02f, unstable prefixes appearing in selection types were handled in a two-pass approach which can be summarized as: 1. Type the selection with the unstable prefix, if this prefix appears in a position where it cannot be widened away, mark it with a special annotation. 2. If the result of the selection contains this annotation, retype it after having wrapped its prefix in a skolem. This got replaced by the use of an `ApproximatingTypeMap` which can always construct a valid (but potentially approximated) type for the selection. Most of the time this is all we need but there are some cases where skolemizing the prefix is still useful as witnessed by the tests added in this commit. They are now handled by unconditionally skolemizing unstable prefixes. To avoid any potential performance impact from this, we teach `asSeenFrom` to always widen these prefixes first and only make use of the skolem to avoid returning an approximation. Since this almost never occurs (it happens only once when compiling Dotty) this means we incur almost no extra cost (the skolem itself still needs to be allocated unconditionally in advance, this cannot be delegated to `asSeenFrom` because it's supposed to be an idempotent operation and each skolem is unique).
Fix #6199: Use a skolemized prefix in asSeenFrom when needed
The code below compiles with scalac 2.12, but not with dotty
Code like this will produce following compilation error:
If we change the declaration of Bar to
case class Bar[A]()
(got rid of covariance) we will get another error:If we change
unit
to be aval
instead ofdef
it compiles, but this is just a distilled, minimum code that produces the same error as we encountered during scalaz-zio compilation with dotty0.13.0-RC1
, see related ticket zio/zio#702The text was updated successfully, but these errors were encountered: