mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[CSBindings] Prevent BindingSet::isViable from dropping viable bindings (v2)
The original attempt to do this was reverted by https://github.com/swiftlang/swift/pull/77653 The problem is that the fix was too broad, I narrowed it down to non-exact uses of stdlib collections that support upcasts.
This commit is contained in:
@@ -31,6 +31,12 @@ using namespace swift;
|
||||
using namespace constraints;
|
||||
using namespace inference;
|
||||
|
||||
/// Check whether there exists a type that could be implicitly converted
|
||||
/// to a given type i.e. is the given type is Double or Optional<..> this
|
||||
/// function is going to return true because CGFloat could be converted
|
||||
/// to a Double and non-optional value could be injected into an optional.
|
||||
static bool hasConversions(Type);
|
||||
|
||||
static std::optional<Type> checkTypeOfBinding(TypeVariableType *typeVar,
|
||||
Type type);
|
||||
|
||||
@@ -1209,7 +1215,31 @@ bool BindingSet::isViable(PotentialBinding &binding, bool isTransitive) {
|
||||
if (!existingNTD || NTD != existingNTD)
|
||||
continue;
|
||||
|
||||
// FIXME: What is going on here needs to be thoroughly re-evaluated.
|
||||
// What is going on in this method needs to be thoroughly re-evaluated!
|
||||
//
|
||||
// This logic aims to skip dropping bindings if
|
||||
// collection type has conversions i.e. in situations like:
|
||||
//
|
||||
// [$T1] conv $T2
|
||||
// $T2 conv [(Int, String)]
|
||||
// $T2.Element equal $T5.Element
|
||||
//
|
||||
// `$T1` could be bound to `(i: Int, v: String)` after
|
||||
// `$T2` is bound to `[(Int, String)]` which is is a problem
|
||||
// because it means that `$T2` was attempted to early
|
||||
// before the solver had a chance to discover all viable
|
||||
// bindings.
|
||||
//
|
||||
// Let's say existing binding is `[(Int, String)]` and
|
||||
// relation is "exact", in this case there is no point
|
||||
// tracking `[$T1]` because upcasts are only allowed for
|
||||
// subtype and other conversions.
|
||||
if (existing->Kind != AllowedBindingKind::Exact) {
|
||||
if (existingType->isKnownStdlibCollectionType() &&
|
||||
hasConversions(existingType)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// If new type has a type variable it shouldn't
|
||||
// be considered viable.
|
||||
|
||||
Reference in New Issue
Block a user