Skip to content

[CS] Allow ExprPatterns to be type-checked in the solver #64280

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 11 commits into from
Jun 7, 2023

Conversation

hamishknight
Copy link
Contributor

@hamishknight hamishknight commented Mar 10, 2023

Previously we would wait until CSApply, which would trigger their type-checking in coercePatternToType. This caused a number of bugs, and hampered solver-based completion, which does not run CSApply. Instead, type-check ExprPatterns as a part of solving the overall pattern. We can then modify coercePatternToType to accept a closure, which allows the solver to take over rewriting the ExprPatterns it has already solved.

This then sets the stage for the complete removal of coercePatternToType, and doing all pattern type-checking in the solver.

This PR also includes a couple of cleanups/fixes for getTypeForPattern, and some other pattern crasher fixes.

Resolves #61850
Resolves #63374
rdar://104954155
rdar://105782480
rdar://106598067
rdar://107709341
rdar://107420031
rdar://109419240

Copy link
Contributor

@xedin xedin left a comment

Choose a reason for hiding this comment

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

LGTM! It might make sense to have an alternative version of this where we either use a TypeJoinExpr to type-check expr patterns that convert to the same generic parameter or simply enable bi-directional checking for patterns since each pattern is solved separately anyway and it doesn't seem like they are too complex.

EEP->setType(patternTy);
return EEP;
} else {
// ...but for non-optional types it can never match! Diagnose it.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can this be detected during solving?

Copy link
Contributor Author

@hamishknight hamishknight Apr 12, 2023

Choose a reason for hiding this comment

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

Yes, but we also need to diagnose for cases that don't yet go through the constraint system. We should be able to move this into the constraint system when we delete coercePatternToType

Copy link
Contributor

Choose a reason for hiding this comment

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

Fair enough! We could start with cases that do go through the solver and expand later too :)

@hamishknight
Copy link
Contributor Author

@swift-ci please test

@hamishknight
Copy link
Contributor Author

@swift-ci please test source compatibility

@hamishknight
Copy link
Contributor Author

@swift-ci please SourceKit stress test

@hamishknight
Copy link
Contributor Author

@xedin Mind taking a look at 4063549? I believe that should be the only change since you last looked at this

@hamishknight hamishknight requested a review from xedin June 2, 2023 17:02
The TypedPattern and IsPattern constraints were
incorrectly written, with conversions propagating
out of the patterns, when really conversions
ought to propagate into patterns. In any case, it
seems like we really want equality here. Fix the
constraints to use equality, and have the cast
constraint operate on the external pattern type
instead of the subpattern type.
Order them such that if they were changed to
conversions, they would be sound. This shouldn't
make a difference, but unfortunately it turns out
pattern equality is not symmetric. As such, tweak
the pattern equality logic to account for the
reversed types. This allows us to remove a special
case from function matching.
This shouldn't be necessary, we should be able to
solve with type variables instead. This makes sure
we don't end up with weird special cases that only
occur when an external type is present.
Push the only null case that can occur up into the
caller.
We should never CSGen a null Type for patterns.
Instead of walking the single ASTNode from the
target, walk all AST nodes associated with the
target to find the completion expr. This is needed
to find the completion expr in a pattern for an
initialization target.
Previously we would wait until CSApply, which
would trigger their type-checking in
`coercePatternToType`. This caused a number of
bugs, and hampered solver-based completion, which
does not run CSApply. Instead, form a conjunction
of all the ExprPatterns present, which preserves
some of the previous isolation behavior (though
does not provide complete isolation).

We can then modify `coercePatternToType` to accept
a closure, which allows the solver to take over
rewriting the ExprPatterns it has already solved.

This then sets the stage for the complete removal
of `coercePatternToType`, and doing all pattern
type-checking in the solver.
This is wrong because there's nowhere to put any
conversion that is introduced, meaning that we'll
likely crash in SILGen. Change the constraint to
equality, which matches what we do outside of the
constraint system.

rdar://107709341
There's still plenty of more work to do here for
pattern diagnostics, including introducing a
bunch of new locator elements, and handling things
like argument list mismatches. This at least lets
us fall back to a generic mismatch diagnostic.
Previously if the cast was unresolved, we would
emit a warning and bail with `nullptr`. This is
wrong, because the caller expects a `nullptr`
return to mean we emitted an error. Change the
diagnostic to an error to fix this. This may
appear source breaking, but in reality previously
we were failing to add the cast at all in this case,
which lead to a crash in SILGen. We really do
want to reject these cases as errors, as this
will give us a better opportunity to fall back to
type-checking as ExprPatterns, and better matches
the constraint solver type-checking.

Also while we're here, change the diagnostic for
the case where we don't have an existential context
type from the confusing "enum doesn't have member"
diagnostic to the pattern mismatch diagnostic.

rdar://107420031
@hamishknight
Copy link
Contributor Author

Going to stick to the conjunction implementation for now

@hamishknight
Copy link
Contributor Author

@swift-ci please smoke test and merge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants