Skip to content

Fix isStructuralTermSelectOrApply #15451

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

Merged
merged 1 commit into from
Jun 15, 2022
Merged

Conversation

odersky
Copy link
Contributor

@odersky odersky commented Jun 15, 2022

When looking at AppliedTypes, we want to go to the supertype (which is the dealiased type or upper bound),
not the underlying type (which is the type constructor).

This is the second bug in a week caused by a confusion of underlying and supertype for AppliedTypes. We
should do an audit of the codebase to see whether there are more cases like this.

Fixes #15448

@odersky
Copy link
Contributor Author

odersky commented Jun 15, 2022

@KacperFKorban If we can get this reviewed today, it could still be part of 3.2.

@odersky odersky force-pushed the fix-15448 branch 2 times, most recently from 96c508f to 697bd33 Compare June 15, 2022 09:39
When looking at AppliedTypes, we want to go to the supertype (which is the dealiased type or upper bound),
not the underlying type (which is the type constructor).

This is the second bug in a week caused by a confusion of unerlying and supertype for AppliedTypes. We
should do an audit of the codebase to see whether there are more cases like this.

Fixes scala#15448
@odersky
Copy link
Contributor Author

odersky commented Jun 15, 2022

How I fixed it:

The original example was quite complex. I reduced it a bit to the one in the "pos" test case of this commit. I then changed the opaque type to a normal type alias and verified that it did compile. I looked at the code after erasure and saw that it generated a conversion to Selectable followed by a call to applyDynamic in the case of a normal alias, but it generated none of that in the case of an opaque alias, which caused the crash in erasure.

I then took the compiling example and compiled it with -Yshow-tree-ids to find out where the necessary code was generated. I added -Ydebug-tree-with-id with one of the node ids in the generated code. That showed me a stack trace where the node was copied, which is unfortunately quite often the case, and which would require further instrumentation in the copier. (In fact that's a case that would be worthwhile to automate: re-run with id of original tree that got copied repeatedly until you hit the originally constructed tree). In my concrete case I found another node (the result of the implicit conversion) that was not copied, and that got me an informative stack trace. It showed that the tree was generated in adapt1, following a test isStructuralTermSelectOrApply. Further instrumentation showed that the hasRefinement test in isStructuralTermSelectOrApply was true for normal aliases but false for opaque aliases. I then looked at the logic. The opaque alias was upper bounded by a refined type as argument, why did it not find that refinement? Then it became clear. The reference to the opaque alias was an AppliedType, and we followed its underlying field, which gives us the type constructor. But we need the full upper bound, which is reached by superType instead.

In the meantime Kacper had minimized the example even more, this time to an example that should not compile. I added that as a neg test.

@KacperFKorban KacperFKorban merged commit fb6d004 into scala:main Jun 15, 2022
@Kordyjan Kordyjan added this to the 3.2.0 milestone Aug 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Selectable + opaque types cause crash
4 participants