-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #5948: Be more careful with capturing #5957
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
Conversation
Comment on last commit:
The problem is that while the old test indeed tested nothing of value, a new version of it would |
- it should not be Erased since that will remove the complete call, including the expression that is casted. It should be StableRealizable, so that a pure expression followed by a synthesized cast is still recognized as pure. - to make up for the loss of Erased, we take the method into account specifically when deciding whether a tree is erased.
Replace all instances of compiler-generated type casts by calls to `Any_typeCast` via `tpd.cast`. This will assume that all these calls are pure.
If tree is not a subtype of expected type, try to capture wildcard types in its type with fresh skolems.
Capture conversion is generally sound only if the LHS of a comparison is a path.
The previous code for `ModuleSerializationProxyConstructor` required capture conversion to work.
I am giving up. This is the worst sort of blindly testing the status quo! It tests some random code and if that code has changed (because there is some optimization applied now) it fails. Great! Problem is there's no way to automatically update the code. One has to go in manually and fix the expected program including all labels! Copy pasting from the diff does not work and there's no --update-check. As long as things are like this I am afraid that bytecode tests are throwaway tests. They blindly test the status quo, and if that changes our best action is to throw away the test.
It seems this is necessary for code generation. We got abstract method errors in typer/TermRefSet otherwise: ``` java.lang.AbstractMethodError: Method dotty/tools/dotc/typer/TermRefSet$$anon$1.accept(Ljava/lang/Object;Ljava/lang/Object;)V is abstract, took 2.601 sec [error] at dotty.tools.dotc.typer.TermRefSet$$anon$1.accept(Implicits.scala) [error] at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) [error] at dotty.tools.dotc.typer.TermRefSet.foreach(Implicits.scala:1638) [error] at dotty.tools.dotc.typer.TermRefSet.$plus$plus$eq(Implicits.scala:1634) ```
Reinstantiate DottyByteCodeTest with the change proposed by @allanrenucci. This reverts commit e04918e.
We now have a much simpler conversion scheme e05c1a7, where we just need to skolemize the type of a tree as a whole, no need to go replace parameters by TypeBoxes. |
test performance please |
performance test scheduled: 2 job(s) in queue, 1 running. |
Performance test finished successfully: Visit http://dotty-bench.epfl.ch/5957/ to see the changes. Benchmarks is based on merging with master (daf4ce9) |
Test case pos/capture.scala contains an explanation why a different scheme we tried does not work.
Unfortunately the simplified scheme failed a test: hmm-shonan/Lifters.scala. I have therefore reverted to the old scheme with TypeBoxes. The essence of the failure is condensed in test |
test performance please |
performance test scheduled: 1 job(s) in queue, 0 running. |
Performance test finished successfully: Visit http://dotty-bench.epfl.ch/5957/ to see the changes. Benchmarks is based on merging with master (daf4ce9) |
A SkolemType is not a symbol whose info is transformed separately. That's why mapping a SkolemType must involve mapping its info. A test case is the new version of pos_valueclasses/t7818.scala.
Since we now map the info of a SkolemType as part of mapping the SkolemType itself, it follows that SkolemTypes can't recursively refer to themselves. So `captureWildcards` in `Typer` avoids recursion now by using an approximating substitution instead (I wonder now how we ever could live without approximating substitutions!). This means that SkolemTypes don't need to be mutable anymore since there is no fixed point to construct.
test performance please |
performance test scheduled: 1 job(s) in queue, 1 running. |
Performance test finished successfully: Visit http://dotty-bench.epfl.ch/5957/ to see the changes. Benchmarks is based on merging with master (fda1250) |
Here's the status: I replaced the previous unsound capture conversion by two measures:
(2) alone would be sufficient, i.e. all tests pass with it. But performance tests indicate that it's better to also do (1). And, besides, (1) is in a sense less intrusive since we do not need to skolemize. So we should do it when we can. |
@smarter I am done now. Can you give it another look? |
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.
-
Your comment in Fix #5948: Be more careful with capturing #5957 (comment) explaining how capture conversion is actually not required but it makes sense to have it here anyway is informative, I think this information should be preserved in a comment in the code too.
-
I still think we could avoid having
leftRoot
be a mutable variable by nestingisSubArgs
inisSubType
, but maybe there's a good reason not to do that?
@@ -2697,10 +2698,47 @@ class Typer extends Namer | |||
case tree: Closure => cpy.Closure(tree)(tpt = TypeTree(pt)).withType(pt) | |||
} | |||
|
|||
/** Replace every top-level occurrence of a wildcard type argument by |
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'm not 100% clear on the notion of "top-level occurence" here, why is in an occurence in a branch of an AndOrType top-level, but not in the widened type of an ExprType
for example ?
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's because we have already widened the type before we pass it to captureWildcards
.
Yes, it's because that way we don't thread a lot of parameters through all recursive calls (in the implementation, not the source). That's why I'll make a note explaining that. |
No description provided.