Skip to content

Commit 680541d

Browse files
authored
Merge pull request #76682 from slavapestov/worse-than-best-solution
Sema: Check worseThanBestSolution() in a better place
2 parents bfc4f95 + 4d980ec commit 680541d

File tree

7 files changed

+52
-44
lines changed

7 files changed

+52
-44
lines changed

include/swift/Sema/ConstraintLocator.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,18 @@ class LocatorPathElt::KeyPathComponent final : public StoredIntegerElement<1> {
751751
}
752752
};
753753

754+
class LocatorPathElt::ProtocolCompositionMemberType final : public StoredIntegerElement<1> {
755+
public:
756+
ProtocolCompositionMemberType(unsigned index)
757+
: StoredIntegerElement(ConstraintLocator::GenericArgument, index) {}
758+
759+
unsigned getIndex() const { return getValue(); }
760+
761+
static bool classof(const LocatorPathElt *elt) {
762+
return elt->getKind() == ConstraintLocator::ProtocolCompositionMemberType;
763+
}
764+
};
765+
754766
class LocatorPathElt::GenericArgument final : public StoredIntegerElement<1> {
755767
public:
756768
GenericArgument(unsigned index)

include/swift/Sema/ConstraintLocatorPathElts.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ CUSTOM_LOCATOR_PATH_ELT(ContextualType)
7676
SIMPLE_LOCATOR_PATH_ELT(DynamicLookupResult)
7777

7878
/// The superclass of a protocol composition type.
79-
SIMPLE_LOCATOR_PATH_ELT(ProtocolCompositionSuperclassType)
79+
CUSTOM_LOCATOR_PATH_ELT(ProtocolCompositionMemberType)
8080

8181
/// The constraint of an existential type.
8282
SIMPLE_LOCATOR_PATH_ELT(ExistentialConstraintType)

lib/AST/TypeJoinMeet.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -460,8 +460,18 @@ CanType TypeJoin::visitProtocolType(CanType second) {
460460
auto *secondDecl =
461461
cast<ProtocolDecl>(second->getNominalOrBoundGenericNominal());
462462

463-
if (firstDecl->getInheritedProtocols().empty() &&
464-
secondDecl->getInheritedProtocols().empty())
463+
SmallVector<Type, 4> firstMembers;
464+
for (auto *decl : firstDecl->getInheritedProtocols())
465+
if (!decl->getInvertibleProtocolKind())
466+
firstMembers.push_back(decl->getDeclaredInterfaceType());
467+
468+
SmallVector<Type, 4> secondMembers;
469+
for (auto *decl : secondDecl->getInheritedProtocols())
470+
if (!decl->getInvertibleProtocolKind())
471+
secondMembers.push_back(decl->getDeclaredInterfaceType());
472+
473+
if (firstMembers.empty() &&
474+
secondMembers.empty())
465475
return TheAnyType;
466476

467477
if (firstDecl->inheritsFrom(secondDecl))
@@ -473,14 +483,6 @@ CanType TypeJoin::visitProtocolType(CanType second) {
473483
// One isn't the supertype of the other, so instead, treat each as
474484
// if it's a protocol composition of its inherited members, and join
475485
// those.
476-
SmallVector<Type, 4> firstMembers;
477-
for (auto *decl : firstDecl->getInheritedProtocols())
478-
firstMembers.push_back(decl->getDeclaredInterfaceType());
479-
480-
SmallVector<Type, 4> secondMembers;
481-
for (auto *decl : secondDecl->getInheritedProtocols())
482-
secondMembers.push_back(decl->getDeclaredInterfaceType());
483-
484486
return computeProtocolCompositionJoin(firstMembers, secondMembers);
485487
}
486488

lib/Sema/CSSimplify.cpp

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3630,10 +3630,8 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2,
36303630
TypeMatchOptions subflags = TMF_GenerateConstraints;
36313631

36323632
// Handle opaque archetypes.
3633-
if (auto arch1 = type1->getAs<ArchetypeType>()) {
3634-
auto arch2 = type2->castTo<ArchetypeType>();
3635-
auto opaque1 = cast<OpaqueTypeArchetypeType>(arch1);
3636-
auto opaque2 = cast<OpaqueTypeArchetypeType>(arch2);
3633+
if (auto opaque1 = type1->getAs<OpaqueTypeArchetypeType>()) {
3634+
auto opaque2 = type2->castTo<OpaqueTypeArchetypeType>();
36373635
assert(opaque1->getDecl() == opaque2->getDecl());
36383636

36393637
// It's possible to declare a generic requirement like Self == Self.Iterator
@@ -3707,34 +3705,24 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2,
37073705
locator);
37083706
}
37093707

3710-
if (type1->isExistentialType()) {
3711-
auto layout1 = type1->getExistentialLayout();
3712-
auto layout2 = type2->getExistentialLayout();
3708+
// Members of protocol compositions have to match.
3709+
if (auto pct1 = type1->getAs<ProtocolCompositionType>()) {
3710+
auto pct2 = type2->castTo<ProtocolCompositionType>();
37133711

3714-
// Explicit AnyObject and protocols must match exactly.
3715-
if (layout1.hasExplicitAnyObject != layout2.hasExplicitAnyObject)
3712+
auto members1 = pct1->getMembers();
3713+
auto members2 = pct2->getMembers();
3714+
if (members1.size() != members2.size())
37163715
return getTypeMatchFailure(locator);
3717-
3718-
if (layout1.getProtocols().size() != layout2.getProtocols().size())
3716+
if (pct1->getInverses() != pct2->getInverses())
37193717
return getTypeMatchFailure(locator);
3720-
3721-
for (unsigned i: indices(layout1.getProtocols())) {
3722-
if (layout1.getProtocols()[i] != layout2.getProtocols()[i])
3723-
return getTypeMatchFailure(locator);
3724-
}
3725-
3726-
// This is the only interesting case. We might have type variables
3727-
// on either side of the superclass constraint, so make sure we
3728-
// recursively call matchTypes() here.
3729-
if (layout1.explicitSuperclass || layout2.explicitSuperclass) {
3730-
if (!layout1.explicitSuperclass || !layout2.explicitSuperclass)
3731-
return getTypeMatchFailure(locator);
3732-
3718+
if (pct1->hasExplicitAnyObject() != pct2->hasExplicitAnyObject())
3719+
return getTypeMatchFailure(locator);
3720+
for (unsigned i = 0, e = members1.size(); i < e; ++i) {
3721+
auto member1 = members1[i];
3722+
auto member2 = members2[i];
37333723
auto subLocator = locator.withPathElement(
3734-
ConstraintLocator::ProtocolCompositionSuperclassType);
3735-
auto result = matchTypes(layout1.explicitSuperclass,
3736-
layout2.explicitSuperclass,
3737-
ConstraintKind::Bind, subflags,
3724+
LocatorPathElt::ProtocolCompositionMemberType(i));
3725+
auto result = matchTypes(member1, member2, ConstraintKind::Bind, subflags,
37383726
subLocator);
37393727
if (result.isFailure())
37403728
return result;

lib/Sema/CSStep.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ StepResult ComponentStep::take(bool prevFailed) {
319319
// One of the previous components created by "split"
320320
// failed, it means that we can't solve this component.
321321
if ((prevFailed && DependsOnPartialSolutions.empty()) ||
322-
CS.isTooComplex(Solutions))
322+
CS.isTooComplex(Solutions) || CS.worseThanBestSolution())
323323
return done(/*isSuccess=*/false);
324324

325325
// Setup active scope, only if previous component didn't fail.
@@ -925,6 +925,10 @@ StepResult ConjunctionStep::resume(bool prevFailed) {
925925
// Rewind back the constraint system information.
926926
ActiveChoice.reset();
927927

928+
// Reset the best score which was updated by `ConstraintSystem::finalize`
929+
// while forming solution(s) for the current element.
930+
CS.solverState->BestScore.reset();
931+
928932
if (CS.isDebugMode())
929933
getDebugLogger() << ")\n";
930934

lib/Sema/ConstraintLocator.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ unsigned LocatorPathElt::getNewSummaryFlags() const {
5858
case ConstraintLocator::UnresolvedMember:
5959
case ConstraintLocator::ParentType:
6060
case ConstraintLocator::ExistentialConstraintType:
61-
case ConstraintLocator::ProtocolCompositionSuperclassType:
61+
case ConstraintLocator::ProtocolCompositionMemberType:
6262
case ConstraintLocator::LValueConversion:
6363
case ConstraintLocator::DynamicType:
6464
case ConstraintLocator::SubscriptMember:
@@ -278,9 +278,11 @@ void LocatorPathElt::dump(raw_ostream &out) const {
278278
out << "existential constraint type";
279279
break;
280280

281-
case ConstraintLocator::ProtocolCompositionSuperclassType:
282-
out << "protocol composition superclass type";
281+
case ConstraintLocator::ProtocolCompositionMemberType: {
282+
auto memberElt = elt.castTo<LocatorPathElt::ProtocolCompositionMemberType>();
283+
out << "protocol composition member " << llvm::utostr(memberElt.getIndex());
283284
break;
285+
}
284286

285287
case ConstraintLocator::LValueConversion:
286288
out << "@lvalue-to-inout conversion";

lib/Sema/ConstraintSystem.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6145,7 +6145,7 @@ void constraints::simplifyLocator(ASTNode &anchor,
61456145
case ConstraintLocator::SequenceElementType:
61466146
case ConstraintLocator::ConstructorMemberType:
61476147
case ConstraintLocator::ExistentialConstraintType:
6148-
case ConstraintLocator::ProtocolCompositionSuperclassType:
6148+
case ConstraintLocator::ProtocolCompositionMemberType:
61496149
break;
61506150

61516151
case ConstraintLocator::GenericArgument:

0 commit comments

Comments
 (0)