Skip to content

Commit 6973cfd

Browse files
authored
Merge pull request #13109 from xedin/rdar-35541153
[CSBindings] Avoid binding type variables to collection types directly
2 parents 5dbdf45 + 5d5872b commit 6973cfd

File tree

5 files changed

+70
-11
lines changed

5 files changed

+70
-11
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
278278

279279
result.foundLiteralBinding(constraint->getProtocol());
280280
result.addPotentialBinding({defaultType, AllowedBindingKind::Subtypes,
281+
constraint->getKind(),
281282
constraint->getProtocol()});
282283
continue;
283284
}
@@ -305,6 +306,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
305306
result.foundLiteralBinding(constraint->getProtocol());
306307
exactTypes.insert(defaultType->getCanonicalType());
307308
result.addPotentialBinding({defaultType, AllowedBindingKind::Subtypes,
309+
constraint->getKind(),
308310
constraint->getProtocol()});
309311
}
310312

@@ -481,11 +483,11 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
481483
}
482484

483485
if (exactTypes.insert(type->getCanonicalType()).second)
484-
result.addPotentialBinding({type, kind, None},
486+
result.addPotentialBinding({type, kind, constraint->getKind()},
485487
/*allowJoinMeet=*/!adjustedIUO);
486488
if (alternateType &&
487489
exactTypes.insert(alternateType->getCanonicalType()).second)
488-
result.addPotentialBinding({alternateType, kind, None},
490+
result.addPotentialBinding({alternateType, kind, constraint->getKind()},
489491
/*allowJoinMeet=*/false);
490492
}
491493

@@ -566,8 +568,9 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
566568
continue;
567569

568570
++result.NumDefaultableBindings;
569-
result.addPotentialBinding(
570-
{type, AllowedBindingKind::Exact, None, constraint->getLocator()});
571+
result.addPotentialBinding({type, AllowedBindingKind::Exact,
572+
constraint->getKind(), None,
573+
constraint->getLocator()});
571574
}
572575

573576
// Determine if the bindings only constrain the type variable from above with

lib/Sema/CSSolver.cpp

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,21 @@ bool ConstraintSystem::tryTypeVariableBindings(
650650
}
651651
type = openUnboundGenericType(type, typeVar->getImpl().getLocator());
652652
type = type->reconstituteSugar(/*recursive=*/false);
653+
} else if ((binding.BindingSource == ConstraintKind::ArgumentConversion ||
654+
binding.BindingSource ==
655+
ConstraintKind::ArgumentTupleConversion) &&
656+
!type->hasTypeVariable() && isCollectionType(type)) {
657+
// If the type binding comes from the argument conversion, let's
658+
// instead of binding collection types directly let's try to
659+
// bind using temporary type variables substituted for element
660+
// types, that's going to ensure that subtype relationship is
661+
// always preserved.
662+
auto *BGT = type->castTo<BoundGenericType>();
663+
auto UGT = UnboundGenericType::get(BGT->getDecl(), BGT->getParent(),
664+
BGT->getASTContext());
665+
666+
type = openUnboundGenericType(UGT, typeVar->getImpl().getLocator());
667+
type = type->reconstituteSugar(/*recursive=*/false);
653668
}
654669

655670
// FIXME: We want the locator that indicates where the binding came
@@ -697,7 +712,8 @@ bool ConstraintSystem::tryTypeVariableBindings(
697712
= *((*binding.DefaultedProtocol)->getKnownProtocolKind());
698713
for (auto altType : getAlternativeLiteralTypes(knownKind)) {
699714
if (exploredTypes.insert(altType->getCanonicalType()).second)
700-
newBindings.push_back({altType, AllowedBindingKind::Subtypes,
715+
newBindings.push_back({altType, AllowedBindingKind::Subtypes,
716+
binding.BindingSource,
701717
binding.DefaultedProtocol});
702718
}
703719
}
@@ -710,7 +726,7 @@ bool ConstraintSystem::tryTypeVariableBindings(
710726
// Try lvalue qualification in addition to rvalue qualification.
711727
auto subtype = LValueType::get(type);
712728
if (exploredTypes.insert(subtype->getCanonicalType()).second)
713-
newBindings.push_back({subtype, binding.Kind, None});
729+
newBindings.push_back({subtype, binding.Kind, binding.BindingSource});
714730
}
715731

716732
if (binding.Kind == AllowedBindingKind::Subtypes) {
@@ -719,7 +735,8 @@ bool ConstraintSystem::tryTypeVariableBindings(
719735
if (scalarIdx >= 0) {
720736
auto eltType = tupleTy->getElementType(scalarIdx);
721737
if (exploredTypes.insert(eltType->getCanonicalType()).second)
722-
newBindings.push_back({eltType, binding.Kind, None});
738+
newBindings.push_back(
739+
{eltType, binding.Kind, binding.BindingSource});
723740
}
724741
}
725742

@@ -733,10 +750,12 @@ bool ConstraintSystem::tryTypeVariableBindings(
733750
if (auto otherTypeVar = objTy->getAs<TypeVariableType>()) {
734751
if (typeVar->getImpl().canBindToLValue() ==
735752
otherTypeVar->getImpl().canBindToLValue()) {
736-
newBindings.push_back({objTy, binding.Kind, None});
753+
newBindings.push_back(
754+
{objTy, binding.Kind, binding.BindingSource});
737755
}
738756
} else {
739-
newBindings.push_back({objTy, binding.Kind, None});
757+
newBindings.push_back(
758+
{objTy, binding.Kind, binding.BindingSource});
740759
}
741760
}
742761
}
@@ -753,7 +772,11 @@ bool ConstraintSystem::tryTypeVariableBindings(
753772

754773
// If we haven't seen this supertype, add it.
755774
if (exploredTypes.insert((*simpleSuper)->getCanonicalType()).second)
756-
newBindings.push_back({*simpleSuper, binding.Kind, None});
775+
newBindings.push_back({
776+
*simpleSuper,
777+
binding.Kind,
778+
binding.BindingSource,
779+
});
757780
}
758781
}
759782

lib/Sema/ConstraintSystem.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,18 @@ Optional<Type> ConstraintSystem::isSetType(Type type) {
577577
return None;
578578
}
579579

580+
bool ConstraintSystem::isCollectionType(Type type) {
581+
auto &ctx = type->getASTContext();
582+
if (auto *structType = type->getAs<BoundGenericStructType>()) {
583+
auto *decl = structType->getDecl();
584+
if (decl == ctx.getArrayDecl() || decl == ctx.getDictionaryDecl() ||
585+
decl == ctx.getSetDecl())
586+
return true;
587+
}
588+
589+
return false;
590+
}
591+
580592
bool ConstraintSystem::isAnyHashableType(Type type) {
581593
if (auto tv = type->getAs<TypeVariableType>()) {
582594
auto fixedType = getFixedType(tv);

lib/Sema/ConstraintSystem.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1998,6 +1998,9 @@ class ConstraintSystem {
19981998
/// element type of the set.
19991999
static Optional<Type> isSetType(Type t);
20002000

2001+
/// Determine if the type in question is one of the known collection types.
2002+
static bool isCollectionType(Type t);
2003+
20012004
/// \brief Determine if the type in question is AnyHashable.
20022005
bool isAnyHashableType(Type t);
20032006

@@ -2552,6 +2555,9 @@ class ConstraintSystem {
25522555
/// The kind of bindings permitted.
25532556
AllowedBindingKind Kind;
25542557

2558+
/// The kind of the constraint this binding came from.
2559+
ConstraintKind BindingSource;
2560+
25552561
/// The defaulted protocol associated with this binding.
25562562
Optional<ProtocolDecl *> DefaultedProtocol;
25572563

@@ -2560,9 +2566,11 @@ class ConstraintSystem {
25602566
ConstraintLocator *DefaultableBinding = nullptr;
25612567

25622568
PotentialBinding(Type type, AllowedBindingKind kind,
2569+
ConstraintKind bindingSource,
25632570
Optional<ProtocolDecl *> defaultedProtocol = None,
25642571
ConstraintLocator *defaultableBinding = nullptr)
2565-
: BindingType(type), Kind(kind), DefaultedProtocol(defaultedProtocol),
2572+
: BindingType(type), Kind(kind), BindingSource(bindingSource),
2573+
DefaultedProtocol(defaultedProtocol),
25662574
DefaultableBinding(defaultableBinding) {}
25672575

25682576
bool isDefaultableBinding() const { return DefaultableBinding != nullptr; }

test/Constraints/generics.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,3 +528,16 @@ do {
528528
_ = { baz($0) }(construct_generic { d }) // Ok
529529
}
530530
}
531+
532+
// rdar://problem/35541153 - Generic parameter inference bug
533+
534+
func rdar35541153() {
535+
func foo<U: Equatable, V: Equatable, C: Collection>(_ c: C) where C.Element == (U, V) {}
536+
func bar<K: Equatable, V, C: Collection>(_ c: C, _ k: K, _ v: V) where C.Element == (K, V) {}
537+
538+
let x: [(a: Int, b: Int)] = []
539+
let y: [(k: String, v: Int)] = []
540+
541+
foo(x) // Ok
542+
bar(y, "ultimate question", 42) // Ok
543+
}

0 commit comments

Comments
 (0)