Skip to content

Commit 9fe4abc

Browse files
committed
[CS] Simplify Solution::resolveInterfaceType
Rather than attempting to re-implement `simplifyType`, tweak `Solution::simplifyType` such that it can map the resulting type out of context, and can turn type variables into their opened generic parameters.
1 parent 55189ba commit 9fe4abc

File tree

3 files changed

+36
-27
lines changed

3 files changed

+36
-27
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 5 additions & 1 deletion
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

lib/Sema/ConstraintSystem.cpp

Lines changed: 19 additions & 26 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.
@@ -4008,29 +4023,7 @@ ASTNode ConstraintSystem::includingParentApply(ASTNode node) {
40084023
}
40094024

40104025
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;
4026+
return simplifyType(type, /*wantInterfaceType*/ true);
40344027
}
40354028

40364029
std::optional<FunctionArgApplyInfo>

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)