-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Rework type inference #4080
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
Rework type inference #4080
Conversation
x || t.mightBeProvisional && { | ||
t.mightBeProvisional = t match { | ||
case t: TypeVar => | ||
!t.inst.exists |
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.
An instantiated TypeVar could have its underlying type refer to another uninstantiated TypeVar and therefore still be provisional I think.
test performance please |
performance test scheduled: 1 job(s) in queue, 0 running. |
performance test failed: Error line number: 24 [check /data/workspace/bench/logs/pull-4080-03-07-00.16.out for more information] |
test performance please |
performance test scheduled: 1 job(s) in queue, 0 running. |
Performance test finished successfully: Visit http://dotty-bench.epfl.ch/4080/ to see the changes. Benchmarks is based on merging with master (4be2e76) |
test performance please |
performance test scheduled: 1 job(s) in queue, 0 running. |
Changing the interpolation scheme uncovered several cache invalidation problems with - the asSeenFrom cache in Denotations - the superType cache in AppliedType - the lastDenotation cache in NamedType The new denotation scheme performed essentially same operations as the old one, but sometimes in a different order. I am still not quite sure how the differences made the cache invalidations fail. On the other hand, it is quite plausible (obvious even, in retrospect) that the previous invalidation schemes are incomplete. So this commit replaces them with a common algorithm that does not rely on the previous global state represented by `ephemeral`.
Allow to define what gets shown as a result on a backtrace
The previous scheme created a `val showOp = <some closure>` value for each trace operation. It was unused if tracing was disabled. Still might be better to avoid its creation in the first place.
-Yshow-no-inline suppresses "inlined from" parts when printing trees. This is useful when one has deeply inlined structures, as is the case when looking at `trace`ed code.
Used for small, linked sets. Normal immutable sets are about as fast for 0 - 4 elements, but are not linked for larger sizes.
Identify them by number. Helps in the same way other fixed numbering schemes help understand debug output.
- Fix isProvisional condition for TypeVars - Force recomputation via memberDenot in NamedType if previous prefix was provisional
Need to follow up later on what caused it to fail.
Avoids needlessly complicated inferred types such as C[_ >: 1.type <: Singleton] by detecting that that this is equivalent to `C[1.type]`.
Hashes ruin diffability; replace them with the serial `id` numbers.
We missed some cases before.
Major changes from previous one: - We explicitly keep track in typer of which variables should and which should not be interpolated. This replaces searching trees for embedded variable definitions, which is fragile e.g. in the presence of eta expansion. - We compute variances starting with all variables found in the type, not just teh qualifying ones. The previous scheme caused some variance information to be missed, which caused some variables to be mis-classified as non-occurring. i4032.scala is a test case. Unfortunately, fixing this caused several other tricky inference failures because which were previously hidden because some variables were already instantiated prematurely. Examples were hamp.scala, hmap-covariant.scala, and i2300.scala. - We interpolate at the end of typedUnadapted instead of at the beginning of `adapt`. Managing instantiatable variables turned out easier this way.
1060d12
to
04d1588
Compare
Rebased |
Performance test finished successfully: Visit http://dotty-bench.epfl.ch/4080/ to see the changes. Benchmarks is based on merging with master (bdfe740) |
Call simplify and interpolateTypeVars in the same situations.
04d1588
to
a6e1d19
Compare
test performance please |
performance test scheduled: 1 job(s) in queue, 1 running. |
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 like it!
@@ -76,6 +76,11 @@ class TyperState(previous: TyperState /* | Null */) { | |||
/** The uninstantiated variables */ | |||
def uninstVars = constraint.uninstVars | |||
|
|||
/** The set of uninstantiated type varibles which have this state as their owning state */ |
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.
typo: varibles -> variables
trace(i"adapting ${tree.showSummary}: ${tree.tpe} to $pt", show = true) { | ||
assert(ctx.phase == ctx.erasurePhase.next, ctx.phase) | ||
assert(ctx.phase == ctx.erasurePhase || ctx.phase == ctx.erasurePhase.next, ctx.phase) |
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.
Why did this change?
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.
Not sure why. Some transform ran at phase erasure and used the erasure typer to do it. Seems legit. Not sure why it did not run before.
* Y <: X | ||
* | ||
* Then `Y` also occurs co-variantly in `T` because it needs to be minimized in order to constrain | ||
* `T` teh least. See `variances` for more detail. |
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.
typo: teh -> the
Performance test finished successfully: Visit http://dotty-bench.epfl.ch/4080/ to see the changes. Benchmarks is based on merging with master (bdfe740) |
Type variable instantiation should only occur in Typer, TreeChecker and during exhaustiveness checking. This was not enforced until now, and wa not always true before scala#4080.
Type variable instantiation should only occur in Typer, TreeChecker and during exhaustiveness checking, this means that no uninstantiated type variable should exist outside of these phases. This was not enforced until now, and was not always true before scala#4080.
Type variable instantiation should only occur in Typer, TreeChecker and during exhaustiveness checking, this means that no uninstantiated type variable should exist outside of these phases. This was not enforced until now, and was not always true before scala#4080.
Type variable instantiation should only occur in Typer, TreeChecker and during exhaustiveness checking, this means that no uninstantiated type variable should exist outside of these phases. This was not enforced until now, and was not always true before scala#4080.
This is an attempt to put type inference on a more solid basis. The main two commits are
Drop Ephemeral 90a661b
Changing the interpolation scheme uncovered several cache invalidation problems with
The new interpolation scheme performed essentially the same operations as the old one, but sometimes in a different order. I am still not quite sure how the differences made the cache invalidations fail. On the other hand, it is quite plausible (obvious even, in retrospect) that the previous invalidation schemes are incomplete. So this commit replaces them with a common algorithm that does not rely on the previous global state represented by
ephemeral
.New interpolation scheme 417f0c8
Variable interpolation "improves" types by instantiating type variables that do not appear in the result of a type derivation, or that appear only co- or only contra-variantly. This is convenient because it keeps the constraints small. It is also necessary since some operations have more or better solutions once type variables are instantiated. For instance, the members of a type
variable
are the members of
U
. But assumingX
is covariant once it is instantiated toT
we get more members. Similarly for implicit searches.The major changes from the previous interpolation scheme are the following:
which should not be interpolated. This replaces searching trees
for embedded variable definitions, which is fragile e.g. in the
presence of eta expansion.
not just the qualifying ones. The previous scheme caused some
variance information to be missed, which caused some variables
to be mis-classified as non-occurring. i4032.scala is a test case.
Unfortunately, fixing this caused several other tricky inference
failures which were previously hidden because some variables
were already instantiated prematurely. Examples were hmap.scala,
hmap-covariant.scala, and i2300.scala. In all these cases there was another
problem which was masked by the fact that some type variables had
already been instantiated where they should not have been.
typedUnadapted
instead of at thebeginning of
adapt
. Tracking instantiatable variables turned outto be easier this way.