mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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.
This commit is contained in:
@@ -1652,7 +1652,11 @@ public:
|
||||
|
||||
/// Simplify the given type by substituting all occurrences of
|
||||
/// type variables for their fixed types.
|
||||
Type simplifyType(Type type) const;
|
||||
///
|
||||
/// \param wantInterfaceType If true, maps the resulting type out of context,
|
||||
/// and replaces type variables for opened generic parameters with the
|
||||
/// generic parameter types. Should only be used for diagnostic logic.
|
||||
Type simplifyType(Type type, bool wantInterfaceType = false) const;
|
||||
|
||||
// To aid code completion, we need to attempt to convert type placeholders
|
||||
// back into underlying generic parameters if possible, since type
|
||||
|
||||
@@ -1721,14 +1721,29 @@ void Solution::recordSingleArgMatchingChoice(ConstraintLocator *locator) {
|
||||
MatchCallArgumentResult::forArity(1)});
|
||||
}
|
||||
|
||||
Type Solution::simplifyType(Type type) const {
|
||||
Type Solution::simplifyType(Type type, bool wantInterfaceType) const {
|
||||
// If we've been asked for an interface type, start by mapping any archetypes
|
||||
// out of context.
|
||||
if (wantInterfaceType)
|
||||
type = type->mapTypeOutOfContext();
|
||||
|
||||
if (!(type->hasTypeVariable() || type->hasPlaceholder()))
|
||||
return type;
|
||||
|
||||
// Map type variables to fixed types from bindings.
|
||||
auto &cs = getConstraintSystem();
|
||||
auto resolvedType = cs.simplifyTypeImpl(
|
||||
type, [&](TypeVariableType *tvt) -> Type { return getFixedType(tvt); });
|
||||
auto resolvedType =
|
||||
cs.simplifyTypeImpl(type, [&](TypeVariableType *tvt) -> Type {
|
||||
// If we want the interface type, use the generic parameter if we
|
||||
// have one, otherwise map the fixed type out of context.
|
||||
if (wantInterfaceType) {
|
||||
if (auto *gp = tvt->getImpl().getGenericParameter())
|
||||
return gp;
|
||||
return getFixedType(tvt)->mapTypeOutOfContext();
|
||||
}
|
||||
return getFixedType(tvt);
|
||||
});
|
||||
ASSERT(!(wantInterfaceType && resolvedType->hasPrimaryArchetype()));
|
||||
|
||||
// Placeholders shouldn't be reachable through a solution, they are only
|
||||
// useful to determine what went wrong exactly.
|
||||
@@ -4008,29 +4023,7 @@ ASTNode ConstraintSystem::includingParentApply(ASTNode node) {
|
||||
}
|
||||
|
||||
Type Solution::resolveInterfaceType(Type type) const {
|
||||
auto resolvedType = type.transformRec([&](Type type) -> std::optional<Type> {
|
||||
if (auto *tvt = type->getAs<TypeVariableType>()) {
|
||||
// If this type variable is for a generic parameter, return that.
|
||||
if (auto *gp = tvt->getImpl().getGenericParameter())
|
||||
return gp;
|
||||
|
||||
// Otherwise resolve its fixed type, mapped out of context.
|
||||
auto fixed = simplifyType(tvt);
|
||||
return resolveInterfaceType(fixed->mapTypeOutOfContext());
|
||||
}
|
||||
if (auto *dmt = type->getAs<DependentMemberType>()) {
|
||||
// For a dependent member, first resolve the base.
|
||||
auto newBase = resolveInterfaceType(dmt->getBase());
|
||||
|
||||
// Then reconstruct using its associated type.
|
||||
assert(dmt->getAssocType());
|
||||
return DependentMemberType::get(newBase, dmt->getAssocType());
|
||||
}
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
assert(!resolvedType->hasArchetype());
|
||||
return resolvedType;
|
||||
return simplifyType(type, /*wantInterfaceType*/ true);
|
||||
}
|
||||
|
||||
std::optional<FunctionArgApplyInfo>
|
||||
|
||||
12
test/Constraints/issue-77924.swift
Normal file
12
test/Constraints/issue-77924.swift
Normal file
@@ -0,0 +1,12 @@
|
||||
// RUN: %target-typecheck-verify-swift
|
||||
|
||||
// https://github.com/swiftlang/swift/issues/77924
|
||||
func foo<T>(_ x: (T) -> Void) {
|
||||
(a: 0, b: x).b(0) // expected-error {{cannot convert value of type 'Int' to expected argument type 'T'}}
|
||||
}
|
||||
|
||||
func bar<T>(_ x: T) {} // expected-note {{generic parameters are always considered '@escaping'}}
|
||||
|
||||
func baz(_ fn: () -> Void) {
|
||||
(a: 0, b: bar).b(fn) // expected-error {{converting non-escaping parameter 'fn' to generic parameter 'T' may allow it to escape}}
|
||||
}
|
||||
Reference in New Issue
Block a user