@@ -791,27 +791,41 @@ class TypeWitnessSystem final {
791
791
// / The int:
792
792
// / - A flag indicating whether the resolved type is ambiguous. When set,
793
793
// / the resolved type is null.
794
- llvm::PointerIntPair<Type, 1 , bool > ResolvedTyAndIsAmbiguous;
794
+ // / - A flag indicating whether the resolved type is 'preferred', meaning
795
+ // / it came from the exact protocol we're checking conformance to.
796
+ // / A preferred type takes precedence over a non-preferred type.
797
+ llvm::PointerIntPair<Type, 2 , unsigned > ResolvedTyAndFlags;
795
798
796
799
public:
797
- EquivalenceClass (Type ty) : ResolvedTyAndIsAmbiguous(ty, false ) {}
800
+ EquivalenceClass (Type ty, bool preferred)
801
+ : ResolvedTyAndFlags(ty, preferred ? 2 : 0 ) {}
798
802
799
803
EquivalenceClass (const EquivalenceClass &) = delete ;
800
804
EquivalenceClass (EquivalenceClass &&) = delete ;
801
805
EquivalenceClass &operator =(const EquivalenceClass &) = delete ;
802
806
EquivalenceClass &operator =(EquivalenceClass &&) = delete ;
803
807
804
808
Type getResolvedType () const {
805
- return ResolvedTyAndIsAmbiguous .getPointer ();
809
+ return ResolvedTyAndFlags .getPointer ();
806
810
}
807
- void setResolvedType (Type ty);
811
+ void setResolvedType (Type ty, bool preferred );
808
812
809
813
bool isAmbiguous () const {
810
- return ResolvedTyAndIsAmbiguous .getInt ();
814
+ return (ResolvedTyAndFlags .getInt () & 1 ) != 0 ;
811
815
}
812
816
void setAmbiguous () {
813
- ResolvedTyAndIsAmbiguous = { nullptr , true } ;
817
+ ResolvedTyAndFlags. setPointerAndInt ( nullptr , 1 ) ;
814
818
}
819
+
820
+ bool isPreferred () const {
821
+ return (ResolvedTyAndFlags.getInt () & 2 ) != 0 ;
822
+ }
823
+ void setPreferred () {
824
+ assert (!isAmbiguous ());
825
+ ResolvedTyAndFlags.setInt (ResolvedTyAndFlags.getInt () | 2 );
826
+ }
827
+
828
+ void dump (llvm::raw_ostream &out) const ;
815
829
};
816
830
817
831
// / A type witness candidate for a name variable.
@@ -852,21 +866,22 @@ class TypeWitnessSystem final {
852
866
// /
853
867
// / \note This need not lead to the resolution of a type witness, e.g.
854
868
// / an associated type may be defaulted to another.
855
- void addTypeWitness (Identifier name, Type type);
869
+ void addTypeWitness (Identifier name, Type type, bool preferred );
856
870
857
871
// / Record a default type witness.
858
872
// /
859
873
// / \param defaultedAssocType The specific associated type declaration that
860
874
// / defines the given default type.
861
875
// /
862
876
// / \note This need not lead to the resolution of a type witness.
863
- void addDefaultTypeWitness (Type type, AssociatedTypeDecl *defaultedAssocType);
877
+ void addDefaultTypeWitness (Type type, AssociatedTypeDecl *defaultedAssocType,
878
+ bool preferred);
864
879
865
880
// / Record the given same-type requirement, if regarded of interest to
866
881
// / the system.
867
882
// /
868
883
// / \note This need not lead to the resolution of a type witness.
869
- void addSameTypeRequirement (const Requirement &req);
884
+ void addSameTypeRequirement (const Requirement &req, bool preferred );
870
885
871
886
void dump (llvm::raw_ostream &out,
872
887
const NormalProtocolConformance *conformance) const ;
@@ -898,7 +913,8 @@ class TypeWitnessSystem final {
898
913
899
914
// / Compare the given resolved types as targeting a single equivalence class,
900
915
// / in terms of the their relative impact on solving the system.
901
- static ResolvedTypeComparisonResult compareResolvedTypes (Type ty1, Type ty2);
916
+ static ResolvedTypeComparisonResult compareResolvedTypes (
917
+ Type ty1, bool preferred1, Type ty2, bool preferred2);
902
918
};
903
919
904
920
// / Captures the state needed to infer associated types.
@@ -2374,7 +2390,8 @@ void AssociatedTypeInference::collectAbstractTypeWitnesses(
2374
2390
2375
2391
if (gp->getName () == assocType->getName ()) {
2376
2392
system.addTypeWitness (assocType->getName (),
2377
- dc->mapTypeIntoContext (gp));
2393
+ dc->mapTypeIntoContext (gp),
2394
+ /* preferred=*/ true );
2378
2395
}
2379
2396
}
2380
2397
}
@@ -2394,10 +2411,14 @@ void AssociatedTypeInference::collectAbstractTypeWitnesses(
2394
2411
2395
2412
LLVM_DEBUG (llvm::dbgs () << " Collecting same-type requirements from "
2396
2413
<< conformedProto->getName () << " \n " );
2414
+
2415
+ // Prefer abstract witnesses from the protocol of the current conformance;
2416
+ // these are less likely to lead to request cycles.
2417
+ bool preferred = (conformedProto == conformance->getProtocol ());
2397
2418
for (const auto &req :
2398
2419
conformedProto->getRequirementSignature ().getRequirements ()) {
2399
2420
if (req.getKind () == RequirementKind::SameType)
2400
- system.addSameTypeRequirement (req);
2421
+ system.addSameTypeRequirement (req, preferred );
2401
2422
}
2402
2423
};
2403
2424
@@ -2423,8 +2444,11 @@ void AssociatedTypeInference::collectAbstractTypeWitnesses(
2423
2444
2424
2445
// If we find a default type definition, feed it to the system.
2425
2446
if (const auto &typeWitness = computeDefaultTypeWitness (assocType)) {
2447
+ bool preferred = (typeWitness->getDefaultedAssocType ()->getDeclContext ()
2448
+ == conformance->getProtocol ());
2426
2449
system.addDefaultTypeWitness (typeWitness->getType (),
2427
- typeWitness->getDefaultedAssocType ());
2450
+ typeWitness->getDefaultedAssocType (),
2451
+ preferred);
2428
2452
}
2429
2453
}
2430
2454
}
@@ -3926,11 +3950,24 @@ auto AssociatedTypeInference::solve()
3926
3950
return llvm::None;
3927
3951
}
3928
3952
3929
- void TypeWitnessSystem::EquivalenceClass::setResolvedType (Type ty) {
3953
+ void TypeWitnessSystem::EquivalenceClass::setResolvedType (Type ty, bool preferred ) {
3930
3954
assert (ty && " cannot resolve to a null type" );
3931
3955
assert (!isAmbiguous () && " must not set resolved type when ambiguous" );
3956
+ ResolvedTyAndFlags.setPointer (ty);
3957
+ if (preferred)
3958
+ setPreferred ();
3959
+ }
3932
3960
3933
- ResolvedTyAndIsAmbiguous.setPointer (ty);
3961
+ void TypeWitnessSystem::EquivalenceClass::dump (llvm::raw_ostream &out) const {
3962
+ if (auto resolvedType = getResolvedType ()) {
3963
+ out << resolvedType;
3964
+ if (isPreferred ())
3965
+ out << " (preferred)" ;
3966
+ } else if (isAmbiguous ()) {
3967
+ out << " (ambiguous)" ;
3968
+ } else {
3969
+ out << " (unresolved)" ;
3970
+ }
3934
3971
}
3935
3972
3936
3973
TypeWitnessSystem::TypeWitnessSystem (
@@ -3967,7 +4004,8 @@ TypeWitnessSystem::getDefaultedAssocType(Identifier name) const {
3967
4004
return this ->TypeWitnesses .lookup (name).DefaultedAssocType ;
3968
4005
}
3969
4006
3970
- void TypeWitnessSystem::addTypeWitness (Identifier name, Type type) {
4007
+ void TypeWitnessSystem::addTypeWitness (Identifier name, Type type,
4008
+ bool preferred) {
3971
4009
assert (this ->TypeWitnesses .count (name));
3972
4010
3973
4011
if (const auto *depTy = type->getAs <DependentMemberType>()) {
@@ -3999,11 +4037,13 @@ void TypeWitnessSystem::addTypeWitness(Identifier name, Type type) {
3999
4037
return ;
4000
4038
}
4001
4039
4002
- // If we already have a resolved type, keep going only if the new one is
4003
- // a better choice.
4004
4040
const Type currResolvedTy = tyWitness.EquivClass ->getResolvedType ();
4005
4041
if (currResolvedTy) {
4006
- switch (compareResolvedTypes (type, currResolvedTy)) {
4042
+ // If we already have a resolved type, keep going only if the new one is
4043
+ // a better choice.
4044
+ switch (compareResolvedTypes (type, preferred,
4045
+ tyWitness.EquivClass ->getResolvedType (),
4046
+ tyWitness.EquivClass ->isPreferred ())) {
4007
4047
case ResolvedTypeComparisonResult::Better:
4008
4048
break ;
4009
4049
case ResolvedTypeComparisonResult::EquivalentOrWorse:
@@ -4031,17 +4071,18 @@ void TypeWitnessSystem::addTypeWitness(Identifier name, Type type) {
4031
4071
}
4032
4072
4033
4073
if (tyWitness.EquivClass ) {
4034
- tyWitness.EquivClass ->setResolvedType (type);
4074
+ tyWitness.EquivClass ->setResolvedType (type, preferred );
4035
4075
} else {
4036
- auto *equivClass = new EquivalenceClass (type);
4076
+ auto *equivClass = new EquivalenceClass (type, preferred );
4037
4077
this ->EquivalenceClasses .insert (equivClass);
4038
4078
4039
4079
tyWitness.EquivClass = equivClass;
4040
4080
}
4041
4081
}
4042
4082
4043
4083
void TypeWitnessSystem::addDefaultTypeWitness (
4044
- Type type, AssociatedTypeDecl *defaultedAssocType) {
4084
+ Type type, AssociatedTypeDecl *defaultedAssocType,
4085
+ bool preferred) {
4045
4086
const auto name = defaultedAssocType->getName ();
4046
4087
assert (this ->TypeWitnesses .count (name));
4047
4088
@@ -4054,10 +4095,11 @@ void TypeWitnessSystem::addDefaultTypeWitness(
4054
4095
tyWitness.DefaultedAssocType = defaultedAssocType;
4055
4096
4056
4097
// Record the type witness.
4057
- addTypeWitness (name, type);
4098
+ addTypeWitness (name, type, preferred );
4058
4099
}
4059
4100
4060
- void TypeWitnessSystem::addSameTypeRequirement (const Requirement &req) {
4101
+ void TypeWitnessSystem::addSameTypeRequirement (const Requirement &req,
4102
+ bool preferred) {
4061
4103
assert (req.getKind () == RequirementKind::SameType);
4062
4104
4063
4105
auto *const depTy1 = req.getFirstType ()->getAs <DependentMemberType>();
@@ -4068,10 +4110,10 @@ void TypeWitnessSystem::addSameTypeRequirement(const Requirement &req) {
4068
4110
// the system.
4069
4111
if (depTy1 && depTy1->getBase ()->is <GenericTypeParamType>() &&
4070
4112
this ->TypeWitnesses .count (depTy1->getName ())) {
4071
- addTypeWitness (depTy1->getName (), req.getSecondType ());
4113
+ addTypeWitness (depTy1->getName (), req.getSecondType (), preferred );
4072
4114
} else if (depTy2 && depTy2->getBase ()->is <GenericTypeParamType>() &&
4073
4115
this ->TypeWitnesses .count (depTy2->getName ())) {
4074
- addTypeWitness (depTy2->getName (), req.getFirstType ());
4116
+ addTypeWitness (depTy2->getName (), req.getFirstType (), preferred );
4075
4117
}
4076
4118
}
4077
4119
@@ -4100,13 +4142,7 @@ void TypeWitnessSystem::dump(
4100
4142
4101
4143
const auto *eqClass = this ->TypeWitnesses .lookup (name).EquivClass ;
4102
4144
if (eqClass) {
4103
- if (eqClass->getResolvedType ()) {
4104
- out << eqClass->getResolvedType ();
4105
- } else if (eqClass->isAmbiguous ()) {
4106
- out << " (ambiguous)" ;
4107
- } else {
4108
- out << " (unresolved)" ;
4109
- }
4145
+ eqClass->dump (out);
4110
4146
} else {
4111
4147
out << " (unresolved)" ;
4112
4148
}
@@ -4143,7 +4179,7 @@ void TypeWitnessSystem::addEquivalence(Identifier name1, Identifier name2) {
4143
4179
tyWitness1.EquivClass = tyWitness2.EquivClass ;
4144
4180
} else {
4145
4181
// Neither has an associated equivalence class.
4146
- auto *equivClass = new EquivalenceClass (nullptr );
4182
+ auto *equivClass = new EquivalenceClass (nullptr , /* preferred= */ false );
4147
4183
this ->EquivalenceClasses .insert (equivClass);
4148
4184
4149
4185
tyWitness1.EquivClass = equivClass;
@@ -4154,16 +4190,20 @@ void TypeWitnessSystem::addEquivalence(Identifier name1, Identifier name2) {
4154
4190
void TypeWitnessSystem::mergeEquivalenceClasses (
4155
4191
EquivalenceClass *equivClass1, const EquivalenceClass *equivClass2) {
4156
4192
assert (equivClass1 && equivClass2);
4193
+
4157
4194
if (equivClass1 == equivClass2) {
4158
4195
return ;
4159
4196
}
4160
4197
4161
4198
// Merge the second equivalence class into the first.
4162
4199
if (equivClass1->getResolvedType () && equivClass2->getResolvedType ()) {
4163
4200
switch (compareResolvedTypes (equivClass2->getResolvedType (),
4164
- equivClass1->getResolvedType ())) {
4201
+ equivClass2->isPreferred (),
4202
+ equivClass1->getResolvedType (),
4203
+ equivClass1->isPreferred ())) {
4165
4204
case ResolvedTypeComparisonResult::Better:
4166
- equivClass1->setResolvedType (equivClass2->getResolvedType ());
4205
+ equivClass1->setResolvedType (equivClass2->getResolvedType (),
4206
+ equivClass2->isPreferred ());
4167
4207
break ;
4168
4208
case ResolvedTypeComparisonResult::EquivalentOrWorse:
4169
4209
break ;
@@ -4175,7 +4215,8 @@ void TypeWitnessSystem::mergeEquivalenceClasses(
4175
4215
// Ambiguity is retained.
4176
4216
} else if (equivClass2->getResolvedType ()) {
4177
4217
// Carry over the resolved type.
4178
- equivClass1->setResolvedType (equivClass2->getResolvedType ());
4218
+ equivClass1->setResolvedType (equivClass2->getResolvedType (),
4219
+ equivClass2->isPreferred ());
4179
4220
} else if (equivClass2->isAmbiguous ()) {
4180
4221
// Carry over ambiguity.
4181
4222
equivClass1->setAmbiguous ();
@@ -4194,12 +4235,20 @@ void TypeWitnessSystem::mergeEquivalenceClasses(
4194
4235
}
4195
4236
4196
4237
TypeWitnessSystem::ResolvedTypeComparisonResult
4197
- TypeWitnessSystem::compareResolvedTypes (Type ty1, Type ty2) {
4238
+ TypeWitnessSystem::compareResolvedTypes (Type ty1, bool preferred1,
4239
+ Type ty2, bool preferred2) {
4198
4240
assert (ty1 && ty2);
4199
4241
4200
- // Prefer shorter type parameters. This is just a heuristic and has no
4242
+ // Prefer type parameters from our current protocol, then break a tie by
4243
+ // applying the type parameter order. This is just a heuristic and has no
4201
4244
// theoretical basis at all.
4202
4245
if (ty1->isTypeParameter () && ty2->isTypeParameter ()) {
4246
+ if (preferred1 && !preferred2)
4247
+ return ResolvedTypeComparisonResult::Better;
4248
+
4249
+ if (preferred2 && !preferred1)
4250
+ return ResolvedTypeComparisonResult::EquivalentOrWorse;
4251
+
4203
4252
return compareDependentTypes (ty1, ty2) < 0
4204
4253
? ResolvedTypeComparisonResult::Better
4205
4254
: ResolvedTypeComparisonResult::EquivalentOrWorse;
0 commit comments