Skip to content

Fix gadt lhs union #10676

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 2 commits into from
Dec 15, 2020
Merged

Fix gadt lhs union #10676

merged 2 commits into from
Dec 15, 2020

Conversation

abgruszecki
Copy link
Contributor

@abgruszecki abgruszecki commented Dec 7, 2020

Fixes #10102.

@abgruszecki abgruszecki requested a review from smarter December 7, 2020 14:57
@abgruszecki
Copy link
Contributor Author

abgruszecki commented Dec 7, 2020

@smarter This is supposed to fix #10102. I think inFrozenGadt is, in principle, required in all places where I added it.
I tried to add test cases for that and could not. For the applied-type-related code, I don't think that can result in unsound constraints yet, but the freeze should be there in principle. For the later join-related code, I don't know how to produce a non-soft union in the relevant position.

Still, both .join-s approximate unions in the same way that .widenSingletons does, so I'm quite convinced they need to have the GADTs frozen.

@@ -434,15 +434,15 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
def widenOK =
(tp2.widenSingletons eq tp2)
&& (tp1.widenSingletons ne tp1)
&& recur(tp1.widenSingletons, tp2)
&& inFrozenGadt { recur(tp1.widenSingletons, tp2) }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this pattern (inFrozenGadt(recur)) should have its own method (inFrozenGadtRecur ?) which clearly documents how it differs from recur (the doc of recur says "recur should also not be used to compare approximated versions of the original types", but here we're intentionally violating that, which requires freezing the gadt bounds)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it was already violated before, since here we are recursing on approximations of the type. I'm not sure if there's anything special about inFrozenGadt here, rather, the docs of recur already suggest that it shouldn't be used here. I think the correct solution would be to add a comment to each of these calls explaining why they violate expectations of recur, but I don't know what to put in that comment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it was violated and thus broken before, but my understanding is that this violation is not a soundness issue as long as we freeze the gadt bounds, it just leads to missing solutions, but this is something we do intentionally in some situations.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So do you want me to add add a comment to all of these callsites that we intentionally call recur on an approximated type, as it doesn't in this specific case lead to unsoundness? I don't think this merits a new definition, not yet anyway seeing as it's isolated to a single match branch.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So do you want me to add add a comment to all of these callsites that we intentionally call recur on an approximated type, as it doesn't in this specific case lead to unsoundness?

Are there other callsites than the three for which you wrapped with inFrozenGadt? If there are others, shouldn't they also be wrapped with inFrozenGadt?

Copy link
Contributor Author

@abgruszecki abgruszecki Dec 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no other callsites that call .widenSingletons or .join, I checked that before opening the PR, should've mentioned it.

EDIT: because I guess you don't mean "are there any other callsites in TypeComparer which call recur w/ an approx'd type".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EDIT: because I guess you don't mean "are there any other callsites in TypeComparer which call recur w/ an approx'd type".

That is what I meant yes.

These approximations shouldn't be used to derive GADTs constraints, just as the
.widenSingleton approx shouldn't.
@abgruszecki abgruszecki marked this pull request as ready for review December 14, 2020 09:18
@abgruszecki abgruszecki requested a review from odersky December 14, 2020 16:28
@abgruszecki
Copy link
Contributor Author

@odersky are you still going to take a look at this, or should we just merge it?

@abgruszecki abgruszecki merged commit 02fbd14 into scala:master Dec 15, 2020
@abgruszecki abgruszecki deleted the fix-gadt-lhs-union branch December 15, 2020 22:30
@Kordyjan Kordyjan added this to the 3.0.0 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

GADT unsoundness: We can infer sufficient constraints when a union type is on the lhs of a subtype check
4 participants