Skip to content

Commit 5525a78

Browse files
Merge pull request swiftlang#33663 from AnthonyLatsis/unbound-closure-retty
CSGen: Infer generic arguments for explicit closure result types
2 parents 50ea66d + 61d86d5 commit 5525a78

File tree

2 files changed

+40
-38
lines changed

2 files changed

+40
-38
lines changed

lib/Sema/CSGen.cpp

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2058,48 +2058,38 @@ namespace {
20582058
// parameter or return type is omitted, a fresh type variable is used to
20592059
// stand in for that parameter or return type, allowing it to be inferred
20602060
// from context.
2061-
auto getExplicitResultType = [&]() -> Type {
2062-
if (!closure->hasExplicitResultType()) {
2063-
return Type();
2064-
}
2061+
Type resultTy = [&] {
2062+
if (closure->hasExplicitResultType()) {
2063+
if (auto declaredTy = closure->getExplicitResultType()) {
2064+
return declaredTy;
2065+
}
20652066

2066-
if (auto declaredTy = closure->getExplicitResultType()) {
2067-
return declaredTy;
2067+
const auto resolvedTy = resolveTypeReferenceInExpression(
2068+
closure->getExplicitResultTypeRepr(),
2069+
TypeResolverContext::InExpression,
2070+
// Introduce type variables for unbound generics.
2071+
OpenUnboundGenericType(
2072+
CS, CS.getConstraintLocator(
2073+
closure, ConstraintLocator::ClosureResult)));
2074+
if (resolvedTy)
2075+
return resolvedTy;
20682076
}
20692077

2070-
return resolveTypeReferenceInExpression(
2071-
closure->getExplicitResultTypeRepr(),
2072-
TypeResolverContext::InExpression, nullptr);
2073-
};
2074-
2075-
Type resultTy;
2076-
auto *resultLoc =
2077-
CS.getConstraintLocator(closure, ConstraintLocator::ClosureResult);
2078-
if (auto explicityTy = getExplicitResultType()) {
2079-
resultTy = explicityTy;
2080-
} else {
2081-
auto getContextualResultType = [&]() -> Type {
2082-
if (auto contextualType = CS.getContextualType(closure)) {
2083-
if (auto fnType = contextualType->getAs<FunctionType>())
2084-
return fnType->getResult();
2085-
}
2086-
return Type();
2087-
};
2088-
2089-
if (auto contextualResultTy = getContextualResultType()) {
2090-
resultTy = contextualResultTy;
2091-
} else {
2092-
// If no return type was specified, create a fresh type
2093-
// variable for it and mark it as possible hole.
2094-
//
2095-
// If this is a multi-statement closure, let's mark result
2096-
// as potential hole right away.
2097-
resultTy = CS.createTypeVariable(
2098-
resultLoc,
2099-
shouldTypeCheckInEnclosingExpression(closure)
2100-
? 0 : TVO_CanBindToHole);
2078+
if (auto contextualType = CS.getContextualType(closure)) {
2079+
if (auto fnType = contextualType->getAs<FunctionType>())
2080+
return fnType->getResult();
21012081
}
2102-
}
2082+
2083+
// If no return type was specified, create a fresh type
2084+
// variable for it and mark it as possible hole.
2085+
//
2086+
// If this is a multi-statement closure, let's mark result
2087+
// as potential hole right away.
2088+
return Type(CS.createTypeVariable(
2089+
CS.getConstraintLocator(closure, ConstraintLocator::ClosureResult),
2090+
shouldTypeCheckInEnclosingExpression(closure) ? 0
2091+
: TVO_CanBindToHole));
2092+
}();
21032093

21042094
return FunctionType::get(closureParams, resultTy, extInfo);
21052095
}

test/Constraints/closures.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,3 +1030,15 @@ func sr12815() {
10301030
.doesntExist2() { $0 }
10311031
}
10321032
}
1033+
1034+
// Make sure we can infer generic arguments in an explicit result type.
1035+
let explicitUnboundResult1 = { () -> Array in [0] }
1036+
let explicitUnboundResult2: (Array<Bool>) -> Array<Int> = {
1037+
(arr: Array) -> Array in [0]
1038+
}
1039+
// FIXME: Should we prioritize the contextual result type and infer Array<Int>
1040+
// rather than using a type variable in these cases?
1041+
// expected-error@+1 {{unable to infer closure type in the current context}}
1042+
let explicitUnboundResult3: (Array<Bool>) -> Array<Int> = {
1043+
(arr: Array) -> Array in [true]
1044+
}

0 commit comments

Comments
 (0)