@@ -283,7 +283,7 @@ void ConstraintSystem::PotentialBindings::inferTransitiveProtocolRequirements(
283
283
}
284
284
285
285
void ConstraintSystem::PotentialBindings::inferTransitiveBindings (
286
- ConstraintSystem &cs, llvm::SmallPtrSetImpl<CanType> &existingTypes,
286
+ ConstraintSystem &cs,
287
287
const llvm::SmallDenseMap<TypeVariableType *,
288
288
ConstraintSystem::PotentialBindings>
289
289
&inferredBindings) {
@@ -343,13 +343,10 @@ void ConstraintSystem::PotentialBindings::inferTransitiveBindings(
343
343
if (type->isHole ())
344
344
continue ;
345
345
346
- if (!existingTypes.insert (type->getCanonicalType ()).second )
347
- continue ;
348
-
349
346
if (ConstraintSystem::typeVarOccursInType (TypeVar, type))
350
347
continue ;
351
348
352
- addPotentialBinding (
349
+ ( void ) addPotentialBinding (
353
350
binding.withSameSource (type, BindingKind::Supertypes));
354
351
}
355
352
}
@@ -359,14 +356,8 @@ void ConstraintSystem::PotentialBindings::finalize(
359
356
ConstraintSystem &cs,
360
357
llvm::SmallDenseMap<TypeVariableType *, ConstraintSystem::PotentialBindings>
361
358
&inferredBindings) {
362
- // We need to make sure that there are no duplicate bindings in the
363
- // set, otherwise solver would produce multiple identical solutions.
364
- llvm::SmallPtrSet<CanType, 4 > existingTypes;
365
- for (const auto &binding : Bindings)
366
- existingTypes.insert (binding.BindingType ->getCanonicalType ());
367
-
368
359
inferTransitiveProtocolRequirements (cs, inferredBindings);
369
- inferTransitiveBindings (cs, existingTypes, inferredBindings);
360
+ inferTransitiveBindings (cs, inferredBindings);
370
361
}
371
362
372
363
Optional<ConstraintSystem::PotentialBindings>
@@ -500,8 +491,8 @@ bool ConstraintSystem::LiteralRequirement::isCoveredBy(
500
491
return bool (TypeChecker::conformsToProtocol (type, getProtocol (), useDC));
501
492
}
502
493
503
- bool ConstraintSystem::PotentialBindings::isLiteralCoveredBy (
504
- const LiteralRequirement &literal, PotentialBinding &binding,
494
+ std::pair< bool , Type> ConstraintSystem::PotentialBindings::isLiteralCoveredBy (
495
+ const LiteralRequirement &literal, const PotentialBinding &binding,
505
496
bool canBeNil) const {
506
497
auto type = binding.BindingType ;
507
498
switch (binding.Kind ) {
@@ -516,29 +507,24 @@ bool ConstraintSystem::PotentialBindings::isLiteralCoveredBy(
516
507
}
517
508
518
509
if (type->isTypeVariableOrMember () || type->isHole ())
519
- return false ;
510
+ return std::make_pair ( false , Type ()) ;
520
511
521
512
bool requiresUnwrap = false ;
522
513
do {
523
514
if (literal.isCoveredBy (type, CS.DC )) {
524
- // FIXME: Side-effect like this is not great (to say the least),
525
- // but this is an artifact of the binding collection which could
526
- // be fixed separately.
527
- if (requiresUnwrap)
528
- binding.BindingType = type;
529
- return true ;
515
+ return std::make_pair (true , requiresUnwrap ? type : binding.BindingType );
530
516
}
531
517
532
518
// Can't unwrap optionals if there is `ExpressibleByNilLiteral`
533
519
// conformance requirement placed on the type variable.
534
520
if (canBeNil)
535
- return false ;
521
+ return std::make_pair ( false , Type ()) ;
536
522
537
523
// If this literal protocol is not a direct requirement it
538
524
// would not be possible to change optionality while inferring
539
525
// bindings for a supertype, so this hack doesn't apply.
540
526
if (!literal.isDirectRequirement ())
541
- return false ;
527
+ return std::make_pair ( false , Type ()) ;
542
528
543
529
// If we're allowed to bind to subtypes, look through optionals.
544
530
// FIXME: This is really crappy special case of computing a reasonable
@@ -551,14 +537,17 @@ bool ConstraintSystem::PotentialBindings::isLiteralCoveredBy(
551
537
}
552
538
}
553
539
554
- return false ;
540
+ return std::make_pair ( false , Type ()) ;
555
541
} while (true );
556
542
}
557
543
558
- void ConstraintSystem::PotentialBindings::addPotentialBinding (
544
+ bool ConstraintSystem::PotentialBindings::addPotentialBinding (
559
545
PotentialBinding binding, bool allowJoinMeet) {
560
546
assert (!binding.BindingType ->is <ErrorType>());
561
547
548
+ if (Bindings.count (binding))
549
+ return false ;
550
+
562
551
// If this is a non-defaulted supertype binding,
563
552
// check whether we can combine it with another
564
553
// supertype binding by computing the 'join' of the types.
@@ -585,7 +574,7 @@ void ConstraintSystem::PotentialBindings::addPotentialBinding(
585
574
// If new binding has been joined with at least one of existing
586
575
// bindings, there is no reason to include it into the set.
587
576
if (joined)
588
- return ;
577
+ return false ;
589
578
}
590
579
591
580
// If the type variable can't bind to an lvalue, make sure the
@@ -596,7 +585,7 @@ void ConstraintSystem::PotentialBindings::addPotentialBinding(
596
585
}
597
586
598
587
if (!isViable (binding))
599
- return ;
588
+ return false ;
600
589
601
590
// Check whether the given binding covers any of the literal protocols
602
591
// associated with this type variable.
@@ -614,13 +603,24 @@ void ConstraintSystem::PotentialBindings::addPotentialBinding(
614
603
615
604
auto &info = literal.second ;
616
605
617
- if (info.viableAsBinding () &&
618
- isLiteralCoveredBy (info, binding, allowsNil))
619
- info.setCoveredBy (binding.getSource ());
606
+ if (!info.viableAsBinding ())
607
+ continue ;
608
+
609
+ bool isCovered = false ;
610
+ Type adjustedTy;
611
+
612
+ std::tie (isCovered, adjustedTy) =
613
+ isLiteralCoveredBy (info, binding, allowsNil);
614
+
615
+ if (!isCovered)
616
+ continue ;
617
+
618
+ binding = binding.withType (adjustedTy);
619
+ info.setCoveredBy (binding.getSource ());
620
620
}
621
621
}
622
622
623
- Bindings.push_back (std::move (binding));
623
+ return Bindings.insert (std::move (binding));
624
624
}
625
625
626
626
void ConstraintSystem::PotentialBindings::addLiteral (Constraint *constraint) {
@@ -675,15 +675,33 @@ void ConstraintSystem::PotentialBindings::addLiteral(Constraint *constraint) {
675
675
LiteralRequirement literal (
676
676
constraint, TypeChecker::getDefaultType (protocol, CS.DC ), isDirect);
677
677
678
- {
678
+ if (literal. viableAsBinding ()) {
679
679
bool allowsNil = canBeNil ();
680
680
681
- for (auto &binding : Bindings) {
682
- if (!literal.isCovered () &&
683
- isLiteralCoveredBy (literal, binding, allowsNil)) {
684
- literal.setCoveredBy (binding.getSource ());
685
- break ;
681
+ for (auto binding = Bindings.begin (); binding != Bindings.end ();
682
+ ++binding) {
683
+ bool isCovered = false ;
684
+ Type adjustedTy;
685
+
686
+ std::tie (isCovered, adjustedTy) =
687
+ isLiteralCoveredBy (literal, *binding, allowsNil);
688
+
689
+ // No luck here, let's try next literal requirement.
690
+ if (!isCovered)
691
+ continue ;
692
+
693
+ // If the type has been adjusted, we need to re-insert
694
+ // the binding but skip all of the previous checks.
695
+ //
696
+ // It's okay to do this here since iteration stops after
697
+ // first covering binding has been found.
698
+ if (adjustedTy) {
699
+ Bindings.erase (binding);
700
+ Bindings.insert (binding->withType (adjustedTy));
686
701
}
702
+
703
+ literal.setCoveredBy (binding->getSource ());
704
+ break ;
687
705
}
688
706
}
689
707
@@ -756,10 +774,8 @@ ConstraintSystem::inferBindingsFor(TypeVariableType *typeVar, bool finalize) {
756
774
auto constraints = CG.gatherConstraints (
757
775
typeVar, ConstraintGraph::GatheringKind::EquivalenceClass);
758
776
759
- llvm::SmallPtrSet<CanType, 4 > exactTypes;
760
-
761
777
for (auto *constraint : constraints) {
762
- bool failed = bindings.infer (*this , exactTypes, constraint);
778
+ bool failed = bindings.infer (*this , constraint);
763
779
764
780
// Upon inference failure let's produce an empty set of bindings.
765
781
if (failed)
@@ -979,9 +995,8 @@ ConstraintSystem::getPotentialBindingForRelationalConstraint(
979
995
// / Retrieve the set of potential type bindings for the given
980
996
// / representative type variable, along with flags indicating whether
981
997
// / those types should be opened.
982
- bool ConstraintSystem::PotentialBindings::infer (
983
- ConstraintSystem &cs, llvm::SmallPtrSetImpl<CanType> &exactTypes,
984
- Constraint *constraint) {
998
+ bool ConstraintSystem::PotentialBindings::infer (ConstraintSystem &cs,
999
+ Constraint *constraint) {
985
1000
switch (constraint->getKind ()) {
986
1001
case ConstraintKind::Bind:
987
1002
case ConstraintKind::Equal:
@@ -998,9 +1013,7 @@ bool ConstraintSystem::PotentialBindings::infer(
998
1013
break ;
999
1014
1000
1015
auto type = binding->BindingType ;
1001
- if (exactTypes.insert (type->getCanonicalType ()).second ) {
1002
- addPotentialBinding (*binding);
1003
-
1016
+ if (addPotentialBinding (*binding)) {
1004
1017
// Determines whether this type variable represents an object
1005
1018
// of the optional type extracted by force unwrap.
1006
1019
if (auto *locator = TypeVar->getImpl ().getLocator ()) {
@@ -1014,7 +1027,7 @@ bool ConstraintSystem::PotentialBindings::infer(
1014
1027
// delaying bindings for as long as possible.
1015
1028
if (isExpr<ForceValueExpr>(anchor) &&
1016
1029
TypeVar->getImpl ().canBindToLValue () && !type->is <LValueType>()) {
1017
- addPotentialBinding (binding->withType (LValueType::get (type)));
1030
+ ( void ) addPotentialBinding (binding->withType (LValueType::get (type)));
1018
1031
DelayedBy.push_back (constraint);
1019
1032
}
1020
1033
@@ -1025,10 +1038,9 @@ bool ConstraintSystem::PotentialBindings::infer(
1025
1038
// helps to avoid creating a thunk to support it.
1026
1039
auto voidType = cs.getASTContext ().TheEmptyTupleType ;
1027
1040
if (locator->isLastElement <LocatorPathElt::ClosureResult>() &&
1028
- binding->Kind == AllowedBindingKind::Supertypes &&
1029
- exactTypes.insert (voidType).second ) {
1030
- addPotentialBinding ({voidType, binding->Kind , constraint},
1031
- /* allowJoinMeet=*/ false );
1041
+ binding->Kind == AllowedBindingKind::Supertypes) {
1042
+ (void )addPotentialBinding ({voidType, binding->Kind , constraint},
1043
+ /* allowJoinMeet=*/ false );
1032
1044
}
1033
1045
}
1034
1046
}
0 commit comments