[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.
This commit is contained in:
Pavel Yaskevich
2024-09-16 09:54:10 -07:00
parent 84e93a26ea
commit 2c9d05991f
3 changed files with 22 additions and 2 deletions

View File

@@ -1205,6 +1205,16 @@ bool BindingSet::isViable(PotentialBinding &binding, bool isTransitive) {
if (!existingNTD || NTD != existingNTD)
continue;
// What is going on here needs to be thoroughly re-evaluated,
// but at least for now, let's not filter bindings of different
// kinds so if we have a situation like: `Array<$T0> conv $T1`
// and `$T1 conv Array<(String, Int)>` we can't lose `Array<$T0>`
// as a binding because `$T0` could be inferred to
// `(key: String, value: Int)` and binding `$T1` to `Array<(String, Int)>`
// eagerly would be incorrect.
if (existing->Kind != binding.Kind)
continue;
// If new type has a type variable it shouldn't
// be considered viable.
if (type->hasTypeVariable())