Skip to content

Commit ecfaa76

Browse files
authored
Merge pull request #78386 from hamishknight/fix-resolve-interface-type
2 parents ed2f43e + 9fb064a commit ecfaa76

File tree

4 files changed

+40
-41
lines changed

4 files changed

+40
-41
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,7 +1652,11 @@ class Solution {
16521652

16531653
/// Simplify the given type by substituting all occurrences of
16541654
/// type variables for their fixed types.
1655-
Type simplifyType(Type type) const;
1655+
///
1656+
/// \param wantInterfaceType If true, maps the resulting type out of context,
1657+
/// and replaces type variables for opened generic parameters with the
1658+
/// generic parameter types. Should only be used for diagnostic logic.
1659+
Type simplifyType(Type type, bool wantInterfaceType = false) const;
16561660

16571661
// To aid code completion, we need to attempt to convert type placeholders
16581662
// back into underlying generic parameters if possible, since type
@@ -1789,10 +1793,6 @@ class Solution {
17891793
/// "resolved" concrete type.
17901794
Type getResolvedType(ASTNode node) const;
17911795

1792-
/// Resolve type variables present in the raw type, using generic parameter
1793-
/// types where possible.
1794-
Type resolveInterfaceType(Type type) const;
1795-
17961796
Type getContextualType(ASTNode anchor) const {
17971797
for (const auto &entry : contextualTypes) {
17981798
if (entry.first == anchor) {

lib/Sema/CSSyntacticElement.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1989,8 +1989,7 @@ class SyntacticElementSolutionApplication
19891989
for (auto *expected : caseStmt->getCaseBodyVariablesOrEmptyArray()) {
19901990
assert(expected->hasName());
19911991
auto prev = expected->getParentVarDecl();
1992-
auto type = solution.resolveInterfaceType(
1993-
solution.getType(prev)->mapTypeOutOfContext());
1992+
auto type = solution.getResolvedType(prev)->mapTypeOutOfContext();
19941993
expected->setInterfaceType(type);
19951994
}
19961995
}

lib/Sema/ConstraintSystem.cpp

Lines changed: 22 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1721,14 +1721,29 @@ void Solution::recordSingleArgMatchingChoice(ConstraintLocator *locator) {
17211721
MatchCallArgumentResult::forArity(1)});
17221722
}
17231723

1724-
Type Solution::simplifyType(Type type) const {
1724+
Type Solution::simplifyType(Type type, bool wantInterfaceType) const {
1725+
// If we've been asked for an interface type, start by mapping any archetypes
1726+
// out of context.
1727+
if (wantInterfaceType)
1728+
type = type->mapTypeOutOfContext();
1729+
17251730
if (!(type->hasTypeVariable() || type->hasPlaceholder()))
17261731
return type;
17271732

17281733
// Map type variables to fixed types from bindings.
17291734
auto &cs = getConstraintSystem();
1730-
auto resolvedType = cs.simplifyTypeImpl(
1731-
type, [&](TypeVariableType *tvt) -> Type { return getFixedType(tvt); });
1735+
auto resolvedType =
1736+
cs.simplifyTypeImpl(type, [&](TypeVariableType *tvt) -> Type {
1737+
// If we want the interface type, use the generic parameter if we
1738+
// have one, otherwise map the fixed type out of context.
1739+
if (wantInterfaceType) {
1740+
if (auto *gp = tvt->getImpl().getGenericParameter())
1741+
return gp;
1742+
return getFixedType(tvt)->mapTypeOutOfContext();
1743+
}
1744+
return getFixedType(tvt);
1745+
});
1746+
ASSERT(!(wantInterfaceType && resolvedType->hasPrimaryArchetype()));
17321747

17331748
// Placeholders shouldn't be reachable through a solution, they are only
17341749
// useful to determine what went wrong exactly.
@@ -4007,32 +4022,6 @@ ASTNode ConstraintSystem::includingParentApply(ASTNode node) {
40074022
return node;
40084023
}
40094024

4010-
Type Solution::resolveInterfaceType(Type type) const {
4011-
auto resolvedType = type.transformRec([&](Type type) -> std::optional<Type> {
4012-
if (auto *tvt = type->getAs<TypeVariableType>()) {
4013-
// If this type variable is for a generic parameter, return that.
4014-
if (auto *gp = tvt->getImpl().getGenericParameter())
4015-
return gp;
4016-
4017-
// Otherwise resolve its fixed type, mapped out of context.
4018-
auto fixed = simplifyType(tvt);
4019-
return resolveInterfaceType(fixed->mapTypeOutOfContext());
4020-
}
4021-
if (auto *dmt = type->getAs<DependentMemberType>()) {
4022-
// For a dependent member, first resolve the base.
4023-
auto newBase = resolveInterfaceType(dmt->getBase());
4024-
4025-
// Then reconstruct using its associated type.
4026-
assert(dmt->getAssocType());
4027-
return DependentMemberType::get(newBase, dmt->getAssocType());
4028-
}
4029-
return std::nullopt;
4030-
});
4031-
4032-
assert(!resolvedType->hasArchetype());
4033-
return resolvedType;
4034-
}
4035-
40364025
std::optional<FunctionArgApplyInfo>
40374026
Solution::getFunctionArgApplyInfo(ConstraintLocator *locator) const {
40384027
// It's only valid to use `&` in argument positions, but we need
@@ -4125,13 +4114,12 @@ Solution::getFunctionArgApplyInfo(ConstraintLocator *locator) const {
41254114
auto *callee = choice ? choice->getDeclOrNull() : nullptr;
41264115
if (callee && callee->hasInterfaceType()) {
41274116
// If we have a callee with an interface type, we can use it. This is
4128-
// preferable to resolveInterfaceType, as this will allow us to get a
4129-
// GenericFunctionType for generic decls.
4117+
// preferable to simplifyType for the function, as this will allow us to get
4118+
// a GenericFunctionType for generic decls.
41304119
//
41314120
// Note that it's possible to find a callee without an interface type. This
41324121
// can happen for example with closure parameters, where the interface type
4133-
// isn't set until the solution is applied. In that case, use
4134-
// resolveInterfaceType.
4122+
// isn't set until the solution is applied. In that case, use simplifyType.
41354123
fnInterfaceType = callee->getInterfaceType();
41364124

41374125
// Strip off the curried self parameter if necessary.
@@ -4152,7 +4140,7 @@ Solution::getFunctionArgApplyInfo(ConstraintLocator *locator) const {
41524140
}
41534141
#endif
41544142
} else {
4155-
fnInterfaceType = resolveInterfaceType(rawFnType);
4143+
fnInterfaceType = simplifyType(rawFnType, /*wantInterfaceType*/ true);
41564144
}
41574145

41584146
auto argIdx = applyArgElt->getArgIdx();

test/Constraints/issue-77924.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// https://github.com/swiftlang/swift/issues/77924
4+
func foo<T>(_ x: (T) -> Void) {
5+
(a: 0, b: x).b(0) // expected-error {{cannot convert value of type 'Int' to expected argument type 'T'}}
6+
}
7+
8+
func bar<T>(_ x: T) {} // expected-note {{generic parameters are always considered '@escaping'}}
9+
10+
func baz(_ fn: () -> Void) {
11+
(a: 0, b: bar).b(fn) // expected-error {{converting non-escaping parameter 'fn' to generic parameter 'T' may allow it to escape}}
12+
}

0 commit comments

Comments
 (0)