Skip to content

Commit b7e7493

Browse files
committed
[CSBindings] Prevent BindingSet::isViable from dropping viable bindings (v2)
The original attempt to do this was reverted by #77653 The problem is that the fix was too broad, I narrowed it down to non-exact uses of stdlib collections that support upcasts.
1 parent 87cd5f8 commit b7e7493

File tree

1 file changed

+31
-1
lines changed

1 file changed

+31
-1
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ using namespace swift;
3131
using namespace constraints;
3232
using namespace inference;
3333

34+
/// Check whether there exists a type that could be implicitly converted
35+
/// to a given type i.e. is the given type is Double or Optional<..> this
36+
/// function is going to return true because CGFloat could be converted
37+
/// to a Double and non-optional value could be injected into an optional.
38+
static bool hasConversions(Type);
39+
3440
static std::optional<Type> checkTypeOfBinding(TypeVariableType *typeVar,
3541
Type type);
3642

@@ -1209,7 +1215,31 @@ bool BindingSet::isViable(PotentialBinding &binding, bool isTransitive) {
12091215
if (!existingNTD || NTD != existingNTD)
12101216
continue;
12111217

1212-
// FIXME: What is going on here needs to be thoroughly re-evaluated.
1218+
// What is going on in this method needs to be thoroughly re-evaluated!
1219+
//
1220+
// This logic aims to skip dropping bindings if
1221+
// collection type has conversions i.e. in situations like:
1222+
//
1223+
// [$T1] conv $T2
1224+
// $T2 conv [(Int, String)]
1225+
// $T2.Element equal $T5.Element
1226+
//
1227+
// `$T1` could be bound to `(i: Int, v: String)` after
1228+
// `$T2` is bound to `[(Int, String)]` which is is a problem
1229+
// because it means that `$T2` was attempted to early
1230+
// before the solver had a chance to discover all viable
1231+
// bindings.
1232+
//
1233+
// Let's say existing binding is `[(Int, String)]` and
1234+
// relation is "exact", in this case there is no point
1235+
// tracking `[$T1]` because upcasts are only allowed for
1236+
// subtype and other conversions.
1237+
if (existing->Kind != AllowedBindingKind::Exact) {
1238+
if (existingType->isKnownStdlibCollectionType() &&
1239+
hasConversions(existingType)) {
1240+
continue;
1241+
}
1242+
}
12131243

12141244
// If new type has a type variable it shouldn't
12151245
// be considered viable.

0 commit comments

Comments
 (0)