mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[CSSyntacticElement] Fix solution applicator to identify context correctly
`TapExpr` do not form their own declaration context which means that using `context.getAsDeclContext` is incorrect for them.
This commit is contained in:
committed by
Alex Hoppen
parent
4b091be1b9
commit
ff0c942aa9
@@ -1645,7 +1645,6 @@ class SyntacticElementSolutionApplication
|
||||
protected:
|
||||
Solution &solution;
|
||||
SyntacticElementContext context;
|
||||
Type resultType;
|
||||
RewriteTargetFn rewriteTarget;
|
||||
|
||||
/// All `func`s declared in the body of the closure.
|
||||
@@ -1658,24 +1657,39 @@ public:
|
||||
SyntacticElementSolutionApplication(Solution &solution,
|
||||
SyntacticElementContext context,
|
||||
RewriteTargetFn rewriteTarget)
|
||||
: solution(solution), context(context), rewriteTarget(rewriteTarget) {
|
||||
if (auto fn = AnyFunctionRef::fromDeclContext(context.getAsDeclContext())) {
|
||||
if (auto transform = solution.getAppliedBuilderTransform(*fn)) {
|
||||
resultType = solution.simplifyType(transform->bodyResultType);
|
||||
} else if (auto *closure =
|
||||
getAsExpr<ClosureExpr>(fn->getAbstractClosureExpr())) {
|
||||
resultType = solution.getResolvedType(closure)
|
||||
->castTo<FunctionType>()
|
||||
->getResult();
|
||||
} else {
|
||||
resultType = fn->getBodyResultType();
|
||||
}
|
||||
}
|
||||
}
|
||||
: solution(solution), context(context), rewriteTarget(rewriteTarget) {}
|
||||
|
||||
virtual ~SyntacticElementSolutionApplication() {}
|
||||
|
||||
private:
|
||||
Type getContextualResultType() const {
|
||||
// Taps do not have a contextual result type.
|
||||
if (context.is<TapExpr *>()) {
|
||||
return Type();
|
||||
}
|
||||
|
||||
auto fn = context.getAsAnyFunctionRef();
|
||||
|
||||
if (context.is<SingleValueStmtExpr *>()) {
|
||||
// if/switch expressions can have `return` inside.
|
||||
fn = AnyFunctionRef::fromDeclContext(context.getAsDeclContext());
|
||||
}
|
||||
|
||||
if (fn) {
|
||||
if (auto transform = solution.getAppliedBuilderTransform(*fn)) {
|
||||
return solution.simplifyType(transform->bodyResultType);
|
||||
} else if (auto *closure =
|
||||
getAsExpr<ClosureExpr>(fn->getAbstractClosureExpr())) {
|
||||
return solution.getResolvedType(closure)
|
||||
->castTo<FunctionType>()
|
||||
->getResult();
|
||||
} else {
|
||||
return fn->getBodyResultType();
|
||||
}
|
||||
}
|
||||
|
||||
return Type();
|
||||
}
|
||||
|
||||
ASTNode visit(Stmt *S, bool performSyntacticDiagnostics = true) {
|
||||
auto rewritten = ASTVisitor::visit(S);
|
||||
@@ -2031,17 +2045,18 @@ private:
|
||||
auto closure = context.getAsAbstractClosureExpr();
|
||||
if (closure && !closure.get()->hasSingleExpressionBody() &&
|
||||
closure.get()->getBody() == braceStmt) {
|
||||
auto resultType = getContextualResultType();
|
||||
if (resultType->getOptionalObjectType() &&
|
||||
resultType->lookThroughAllOptionalTypes()->isVoid() &&
|
||||
!braceStmt->getLastElement().isStmt(StmtKind::Return)) {
|
||||
return addImplicitVoidReturn(braceStmt);
|
||||
return addImplicitVoidReturn(braceStmt, resultType);
|
||||
}
|
||||
}
|
||||
|
||||
return braceStmt;
|
||||
}
|
||||
|
||||
ASTNode addImplicitVoidReturn(BraceStmt *braceStmt) {
|
||||
ASTNode addImplicitVoidReturn(BraceStmt *braceStmt, Type contextualResultTy) {
|
||||
auto &cs = solution.getConstraintSystem();
|
||||
auto &ctx = cs.getASTContext();
|
||||
|
||||
@@ -2056,7 +2071,7 @@ private:
|
||||
// number of times.
|
||||
{
|
||||
SyntacticElementTarget target(resultExpr, context.getAsDeclContext(),
|
||||
CTP_ReturnStmt, resultType,
|
||||
CTP_ReturnStmt, contextualResultTy,
|
||||
/*isDiscarded=*/false);
|
||||
cs.setTargetFor(returnStmt, target);
|
||||
|
||||
@@ -2077,6 +2092,8 @@ private:
|
||||
ASTNode visitReturnStmt(ReturnStmt *returnStmt) {
|
||||
auto &cs = solution.getConstraintSystem();
|
||||
|
||||
auto resultType = getContextualResultType();
|
||||
|
||||
if (!returnStmt->hasResult()) {
|
||||
// If contextual is not optional, there is nothing to do here.
|
||||
if (resultType->isVoid())
|
||||
|
||||
Reference in New Issue
Block a user