Skip to content

Commit 2c9d059

Browse files
committed
[CSBindings] Prevent BindingSet::isViable from dropping viable bindings
I think the original idea was to elide `Array<$T>` if there is a binding a resolved generic arguments i.e. `Array<Float>`, but the check doesn't account for the fact that bindings could be of different kinds and there are some implicit conversions that could be missed if we remove the bindings. For example, given the following constraints: `Array<$T0> conv $T1` `$T1 conv Array<(String, Int)>` `$T0` can be a supertype of `Array<$T0>` and subtype of `Array<(String, Int)>`. The solver should accept both types as viable bindings because the `$T0` could be bound to `(key: String, value: Int)` and that would match `Array<(String, Int)>` conversion.
1 parent 84e93a2 commit 2c9d059

File tree

3 files changed

+22
-2
lines changed

3 files changed

+22
-2
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,16 @@ bool BindingSet::isViable(PotentialBinding &binding, bool isTransitive) {
12051205
if (!existingNTD || NTD != existingNTD)
12061206
continue;
12071207

1208+
// What is going on here needs to be thoroughly re-evaluated,
1209+
// but at least for now, let's not filter bindings of different
1210+
// kinds so if we have a situation like: `Array<$T0> conv $T1`
1211+
// and `$T1 conv Array<(String, Int)>` we can't lose `Array<$T0>`
1212+
// as a binding because `$T0` could be inferred to
1213+
// `(key: String, value: Int)` and binding `$T1` to `Array<(String, Int)>`
1214+
// eagerly would be incorrect.
1215+
if (existing->Kind != binding.Kind)
1216+
continue;
1217+
12081218
// If new type has a type variable it shouldn't
12091219
// be considered viable.
12101220
if (type->hasTypeVariable())

test/Constraints/array_literal.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,3 +415,13 @@ do {
415415
]
416416
}
417417
}
418+
419+
420+
do {
421+
func f<R>(fn: () -> [R]) -> [R] { [] }
422+
423+
// Requires collection upcast from Array<(key: String, value: String)> to `Array<(String, String)>`
424+
func g(v: [String: String]) {
425+
let _: [(String, String)] = f { return Array(v) } + v // Ok
426+
}
427+
}

validation-test/Sema/SwiftUI/rdar98862079.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct MyView : View {
2222

2323
var body: some View {
2424
test(value: true ? $newBounds.maxBinding : $newBounds.minBinding, in: bounds)
25-
// expected-error@-1 2 {{result values in '? :' expression have mismatching types 'Binding<Binding<Double>?>' and 'Binding<Double>'}}
26-
// expected-note@-2 2 {{arguments to generic parameter 'Value' ('Binding<Double>?' and 'Double') are expected to be equal}}
25+
// expected-error@-1 {{cannot convert value of type 'Binding<Binding<Double>?>' to expected argument type 'Binding<Double>'}}
26+
// expected-note@-2 {{arguments to generic parameter 'Value' ('Binding<Double>?' and 'Double') are expected to be equal}}
2727
}
2828
}

0 commit comments

Comments
 (0)