-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
[Typed throws] Infer thrown error type for multi-statement closures #70478
base: main
Are you sure you want to change the base?
Conversation
@swift-ci please smoke test |
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.
The approach looks good to me, I left a few comments inline. Don't forget to add new fixes/diagnostics for situations when error type cannot be determined.
!CS.getAppliedResultBuilderTransform(closure) && | ||
!closure->hasSingleExpressionBody()) { | ||
return Type( | ||
CS.createTypeVariable(thrownErrorLocator, TVO_CanBindToHole)); |
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.
If this is allowed to bind to a hole we should handle it in TypeVariableBinding::fixForHole
by producing an appropriate fix otherwise we'd end up crashing during solution verification when the type cannot be inferred.
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 suspect I don't need it to bind to a hole at all, thank you for noticing this.
referencedVars.push_back(thrownErrorTypeVar); | ||
constraints.push_back( | ||
Constraint::createCaughtError(cs, Type(thrownErrorTypeVar), closure, | ||
locator, referencedVars)); |
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.
A couple of points here:
-
This constraint needs a custom locator, maybe use
ClosureThrownError
just like the type variable but it cannot be directly on the closure. -
I don't think
referencedVars
needs to be passed here because the constraint itself doesn't actually reference all of these variables and there is no risk of it being disconnected from the conjunction.
@@ -1092,10 +1105,11 @@ class SyntacticElementConstraintGenerator | |||
void visitBraceStmt(BraceStmt *braceStmt) { | |||
auto &ctx = cs.getASTContext(); | |||
|
|||
ClosureExpr *closure = nullptr; |
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.
Nit: Doesn't seem to be necessary since it's not used anywhere else?
CatchNode catchNode, | ||
TypeMatchOptions flags, | ||
ConstraintLocatorBuilder locator) { | ||
Type caughtErrorType = inferCaughtErrorType(catchNode); |
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.
Since it's only used in multi-statement closures at the moment it's guaranteed to have all the throw sites resolved by the time it comes to this constraint (since it's the last in the body). The situation is more interesting for single-expression closures because they support bi-directional inference and the constraint needs to be re-activated every time something in one of its throw sites gets resolved.
I think what needs to happen to support single-expression closures is:
CaughtError
constraint needs to reference all of the relevant (relevance should be determined by thePotentialThrowSite
) type variables from all of its potential throw sites; This way it would never run into the risk of being disconnected from its context;- Referencing these variables also triggers re-activation which is the most important.
- Simplification logic needs to go over all of the referenced variables and check whether they are fixed before attempting to call
inferCaughtErrorType
and re-introduce the constraint otherwise; CaughtError
constraint for single-expression closures could be introduced @ https://github.com/apple/swift/blob/main/lib/Sema/CSSyntacticElement.cpp#L1132 when all of the potential throw sites in the body have been identified.
} | ||
|
||
Type ConstraintSystem::inferCaughtErrorType(CatchNode catchNode) { | ||
ASTContext &ctx = getASTContext(); |
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.
Nit: appears to be unused.
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.
Right, thanks!
No description provided.