mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #71272 from hamishknight/cleanup-return
[CS] Unify ReturnStmt handling
This commit is contained in:
@@ -491,7 +491,7 @@ struct SyntacticElementContext
|
||||
}
|
||||
}
|
||||
|
||||
bool isSingleExpressionClosure(ConstraintSystem &cs) {
|
||||
bool isSingleExpressionClosure(ConstraintSystem &cs) const {
|
||||
if (auto ref = getAsAnyFunctionRef()) {
|
||||
if (cs.getAppliedResultBuilderTransform(*ref))
|
||||
return false;
|
||||
@@ -1121,8 +1121,8 @@ private:
|
||||
|
||||
for (auto node : braceStmt->getElements()) {
|
||||
if (auto expr = node.dyn_cast<Expr *>()) {
|
||||
auto generatedExpr = cs.generateConstraints(
|
||||
expr, context.getAsDeclContext(), /*isInputExpression=*/false);
|
||||
auto generatedExpr =
|
||||
cs.generateConstraints(expr, context.getAsDeclContext());
|
||||
if (!generatedExpr) {
|
||||
hadError = true;
|
||||
}
|
||||
@@ -1248,33 +1248,7 @@ private:
|
||||
}
|
||||
|
||||
void visitReturnStmt(ReturnStmt *returnStmt) {
|
||||
// Single-expression closures are effectively a `return` statement,
|
||||
// so let's give them a special locator as to indicate that.
|
||||
// Return statements might not have a result if we have a closure whose
|
||||
// implicit returned value is coerced to Void.
|
||||
if (context.isSingleExpressionClosure(cs) && returnStmt->hasResult()) {
|
||||
auto *expr = returnStmt->getResult();
|
||||
assert(expr && "single expression closure without expression?");
|
||||
|
||||
expr = cs.generateConstraints(expr, context.getAsDeclContext(),
|
||||
/*isInputExpression=*/false);
|
||||
if (!expr) {
|
||||
hadError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
auto contextualResultInfo = getContextualResultInfo();
|
||||
cs.addConstraint(ConstraintKind::Conversion, cs.getType(expr),
|
||||
contextualResultInfo.getType(),
|
||||
cs.getConstraintLocator(
|
||||
context.getAsAbstractClosureExpr().get(),
|
||||
LocatorPathElt::ClosureBody(
|
||||
/*hasImpliedReturn=*/returnStmt->isImplied())));
|
||||
return;
|
||||
}
|
||||
|
||||
Expr *resultExpr;
|
||||
|
||||
if (returnStmt->hasResult()) {
|
||||
resultExpr = returnStmt->getResult();
|
||||
assert(resultExpr && "non-empty result without expression?");
|
||||
@@ -1286,10 +1260,10 @@ private:
|
||||
resultExpr = getVoidExpr(cs.getASTContext(), returnStmt->getEndLoc());
|
||||
}
|
||||
|
||||
auto contextualResultInfo = getContextualResultInfo();
|
||||
auto contextualResultInfo = getContextualResultInfoFor(returnStmt);
|
||||
|
||||
SyntacticElementTarget target(resultExpr, context.getAsDeclContext(),
|
||||
contextualResultInfo,
|
||||
/*isDiscarded=*/false);
|
||||
contextualResultInfo, /*isDiscarded=*/false);
|
||||
|
||||
if (cs.generateConstraints(target)) {
|
||||
hadError = true;
|
||||
@@ -1334,7 +1308,7 @@ private:
|
||||
createConjunction({resultElt}, locator);
|
||||
}
|
||||
|
||||
ContextualTypeInfo getContextualResultInfo() const {
|
||||
ContextualTypeInfo getContextualResultInfoFor(ReturnStmt *returnStmt) const {
|
||||
auto funcRef = AnyFunctionRef::fromDeclContext(context.getAsDeclContext());
|
||||
if (!funcRef)
|
||||
return {Type(), CTP_Unused};
|
||||
@@ -1343,8 +1317,18 @@ private:
|
||||
return {transform->bodyResultType, CTP_ReturnStmt};
|
||||
|
||||
if (auto *closure =
|
||||
getAsExpr<ClosureExpr>(funcRef->getAbstractClosureExpr()))
|
||||
return {cs.getClosureType(closure)->getResult(), CTP_ClosureResult};
|
||||
getAsExpr<ClosureExpr>(funcRef->getAbstractClosureExpr())) {
|
||||
// Single-expression closures need their contextual type locator anchored
|
||||
// on the closure itself. Otherwise we use the default contextual type
|
||||
// locator, which will be created for us.
|
||||
ConstraintLocator *loc = nullptr;
|
||||
if (context.isSingleExpressionClosure(cs) && returnStmt->hasResult()) {
|
||||
loc = cs.getConstraintLocator(
|
||||
closure, {LocatorPathElt::ClosureBody(
|
||||
/*hasImpliedReturn=*/returnStmt->isImplied())});
|
||||
}
|
||||
return {cs.getClosureType(closure)->getResult(), CTP_ClosureResult, loc};
|
||||
}
|
||||
|
||||
return {funcRef->getBodyResultType(), CTP_ReturnStmt};
|
||||
}
|
||||
@@ -2162,22 +2146,15 @@ private:
|
||||
mode = convertToResult;
|
||||
}
|
||||
|
||||
llvm::Optional<SyntacticElementTarget> resultTarget;
|
||||
if (auto target = cs.getTargetFor(returnStmt)) {
|
||||
resultTarget = *target;
|
||||
} else {
|
||||
// Single-expression closures have to handle returns in a special
|
||||
// way so the target has to be created for them during solution
|
||||
// application based on the resolved type.
|
||||
assert(context.isSingleExpressionClosure(cs));
|
||||
resultTarget = SyntacticElementTarget(
|
||||
resultExpr, context.getAsDeclContext(),
|
||||
mode == convertToResult ? CTP_ClosureResult : CTP_Unused,
|
||||
mode == convertToResult ? resultType : Type(),
|
||||
/*isDiscarded=*/false);
|
||||
auto target = *cs.getTargetFor(returnStmt);
|
||||
|
||||
// If we're not converting to a result, unset the contextual type.
|
||||
if (mode != convertToResult) {
|
||||
target.setExprConversionType(Type());
|
||||
target.setExprContextualTypePurpose(CTP_Unused);
|
||||
}
|
||||
|
||||
if (auto newResultTarget = rewriteTarget(*resultTarget)) {
|
||||
if (auto newResultTarget = rewriteTarget(target)) {
|
||||
resultExpr = newResultTarget->getAsExpr();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user