Merge pull request #82775 from hamishknight/simple-fix-6.2

[6.2] [CS] Ensure type variables are eliminated by `Solution::simplifyType`
This commit is contained in:
Hamish Knight
2025-07-04 10:56:34 +01:00
committed by GitHub
5 changed files with 46 additions and 9 deletions

View File

@@ -1770,7 +1770,7 @@ Type Solution::simplifyType(Type type, bool wantInterfaceType) const {
if (wantInterfaceType)
type = type->mapTypeOutOfContext();
if (!(type->hasTypeVariable() || type->hasPlaceholder()))
if (!type->hasTypeVariableOrPlaceholder())
return type;
// Map type variables to fixed types from bindings.
@@ -1788,16 +1788,28 @@ Type Solution::simplifyType(Type type, bool wantInterfaceType) const {
});
ASSERT(!(wantInterfaceType && resolvedType->hasPrimaryArchetype()));
// Placeholders shouldn't be reachable through a solution, they are only
// useful to determine what went wrong exactly.
if (resolvedType->hasPlaceholder()) {
return resolvedType.transformRec([&](Type type) -> std::optional<Type> {
if (type->isPlaceholder())
return Type(cs.getASTContext().TheUnresolvedType);
return std::nullopt;
});
// We may have type variables and placeholders left over. These are solver
// allocated so cannot escape this function. Turn them into UnresolvedType.
// - Type variables may still be present from unresolved pack expansions where
// e.g the count type is a hole, so the pattern may never become a
// concrete type.
// - Placeholders may be present for any holes.
if (resolvedType->hasTypeVariableOrPlaceholder()) {
auto &ctx = cs.getASTContext();
resolvedType =
resolvedType.transformRec([&](Type type) -> std::optional<Type> {
if (!type->hasTypeVariableOrPlaceholder())
return type;
auto *typePtr = type.getPointer();
if (isa<TypeVariableType>(typePtr) || isa<PlaceholderType>(typePtr))
return Type(ctx.TheUnresolvedType);
return std::nullopt;
});
}
CONDITIONAL_ASSERT(!resolvedType->getRecursiveProperties().isSolverAllocated());
return resolvedType;
}

View File

@@ -798,3 +798,8 @@ do {
}
}
}
func testInvalidDecomposition() {
func id<T>(_ x: T) -> T {}
let (a, b) = id((repeat each undefined)) // expected-error {{cannot find 'undefined' in scope}}
}

View File

@@ -0,0 +1,4 @@
// {"kind":"complete","signature":"swift::constraints::Solution::simplifyType(swift::Type, bool) const"}
// RUN: %target-swift-ide-test -code-completion --code-completion-token=COMPLETE -code-completion-diagnostics -source-filename %s
for (a(b, d)) [
#^COMPLETE^#, 0, (repeat.c)].enumerated(

View File

@@ -0,0 +1,4 @@
// {"kind":"typecheck","signature":"swift::constraints::Solution::simplifyType(swift::Type, bool) const"}
// RUN: not %target-swift-frontend -typecheck %s
for (a(b, d)) in [(repeat .c)].enumerated(<#expression#>) {
}

View File

@@ -0,0 +1,12 @@
// {"signature":"(anonymous namespace)::SetExprTypes::walkToExprPost(swift::Expr*)"}
// RUN: not %target-swift-frontend -typecheck %s
typealias a<b, c> = c
struct d < each b {
typealias e< c > =
(repeat a< each b, c >)
typealias f< each c > = (repeat e< each c >
func 1 {
typealias g = h
(g<
i >
typealias g< each c > = f< repeat each c >