Skip to content

Commit 0a75a07

Browse files
committed
[CSSolver] Don't drop bindings with type variables while applying solutions
If a (partial) solution has a type variable it could only be unbound if `FreeTypeVariableBinding` is set to `Allow`, in all other cases solution would either have a fully resolved type or a hole. `applySolution` shouldn't second guess `finalize()` and just apply a solution as given. This is very important for multi-statement closures because their elements are solved in isolation and opaque value types inferred for their result could contain not-yet-resolved type variables from outer context in their substitution maps (which it totally legal under bi-directional inference).
1 parent 2d052a0 commit 0a75a07

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

lib/Sema/CSSolver.cpp

+11-3
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ Solution ConstraintSystem::finalize() {
9090

9191
case FreeTypeVariableBinding::Allow:
9292
break;
93-
93+
9494
case FreeTypeVariableBinding::UnresolvedType:
9595
assignFixedType(tv, ctx.TheUnresolvedType);
9696
break;
@@ -99,6 +99,12 @@ Solution ConstraintSystem::finalize() {
9999

100100
// For each of the type variables, get its fixed type.
101101
for (auto tv : getTypeVariables()) {
102+
// This type variable has no binding. Allowed only
103+
// when `FreeTypeVariableBinding::Allow` is set,
104+
// which is checked above.
105+
if (!getFixedType(tv))
106+
continue;
107+
102108
solution.typeBindings[tv] = simplifyType(tv)->reconstituteSugar(false);
103109
}
104110

@@ -221,8 +227,10 @@ void ConstraintSystem::applySolution(const Solution &solution) {
221227

222228
// If we don't already have a fixed type for this type variable,
223229
// assign the fixed type from the solution.
224-
if (!getFixedType(binding.first) && !binding.second->hasTypeVariable())
225-
assignFixedType(binding.first, binding.second, /*updateState=*/false);
230+
if (getFixedType(binding.first))
231+
continue;
232+
233+
assignFixedType(binding.first, binding.second, /*updateState=*/false);
226234
}
227235

228236
// Register overload choices.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx10.15 -enable-experimental-feature ResultBuilderASTTransform -swift-version 5
2+
// REQUIRES: objc_interop
3+
// REQUIRES: OS=macosx
4+
5+
import SwiftUI
6+
7+
struct Configuration {
8+
}
9+
10+
struct Reader<Content: View> : View {
11+
struct Result {
12+
var view: AnyView?
13+
}
14+
15+
var content: (Result) -> (Content)
16+
17+
var body: some View { EmptyView() }
18+
}
19+
20+
struct MyLayout {
21+
func callAsFunction<V: View>(@ViewBuilder content: () -> V) -> some View { content() }
22+
}
23+
24+
struct Test<SubView: View>: View {
25+
var subView: SubView
26+
var body: some View { EmptyView() }
27+
}
28+
29+
func test() -> some View {
30+
Reader { result in
31+
MyLayout().callAsFunction {
32+
Test(subView: result.view)
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)