Skip to content
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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

DougGregor
Copy link
Member

No description provided.

@DougGregor
Copy link
Member Author

@swift-ci please smoke test

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.

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));
Copy link
Contributor

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.

Copy link
Member Author

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));
Copy link
Contributor

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;
Copy link
Contributor

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);
Copy link
Contributor

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 the PotentialThrowSite) 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();
Copy link
Contributor

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.

Copy link
Member Author

Choose a reason for hiding this comment

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

Right, thanks!

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.

2 participants