@@ -938,8 +938,12 @@ LazyResolver *ArchetypeBuilder::getLazyResolver() const {
938
938
return Context.getLazyResolver ();
939
939
}
940
940
941
- auto ArchetypeBuilder::resolveArchetype (Type type) -> PotentialArchetype * {
941
+ auto ArchetypeBuilder::resolveArchetype (Type type, PotentialArchetype *basePA)
942
+ -> PotentialArchetype * {
942
943
if (auto genericParam = type->getAs <GenericTypeParamType>()) {
944
+ if (basePA)
945
+ return basePA;
946
+
943
947
unsigned index = GenericParamKey (genericParam).findIndexIn (
944
948
Impl->GenericParams );
945
949
if (index < Impl->GenericParams .size ())
@@ -949,7 +953,7 @@ auto ArchetypeBuilder::resolveArchetype(Type type) -> PotentialArchetype * {
949
953
}
950
954
951
955
if (auto dependentMember = type->getAs <DependentMemberType>()) {
952
- auto base = resolveArchetype (dependentMember->getBase ());
956
+ auto base = resolveArchetype (dependentMember->getBase (), basePA );
953
957
if (!base)
954
958
return nullptr ;
955
959
@@ -1010,52 +1014,66 @@ bool ArchetypeBuilder::addConformanceRequirement(PotentialArchetype *PAT,
1010
1014
if (!T->addConformance (Proto, /* updateExistingSource=*/ true , Source, *this ))
1011
1015
return false ;
1012
1016
1013
- // Conformances to inherit protocols are explicit in a protocol requirement
1014
- // signature, but inferred from this conformance otherwise.
1015
- auto InnerKind =
1016
- Source.getKind () == RequirementSource::ProtocolRequirementSignatureSelf
1017
- ? RequirementSource::Explicit
1018
- : RequirementSource::Redundant;
1019
- RequirementSource InnerSource (InnerKind, Source.getLoc ());
1020
-
1021
1017
bool inserted = Visited.insert (Proto).second ;
1022
1018
assert (inserted);
1023
1019
(void ) inserted;
1024
1020
1025
- // Add all of the inherited protocol requirements, recursively.
1026
- if (auto resolver = getLazyResolver ())
1027
- resolver->resolveInheritedProtocols (Proto);
1028
- for (auto InheritedProto : Proto->getInheritedProtocols (getLazyResolver ())) {
1029
- if (Visited.count (InheritedProto))
1030
- continue ;
1031
- if (addConformanceRequirement (T, InheritedProto, InnerSource, Visited))
1032
- return true ;
1033
- }
1021
+ // Requirements introduced by the main protocol are explicit in a protocol
1022
+ // requirement signature, but inferred from this conformance otherwise.
1023
+ auto Kind =
1024
+ Source.getKind () == RequirementSource::ProtocolRequirementSignatureSelf
1025
+ ? RequirementSource::Explicit
1026
+ : RequirementSource::Protocol;
1034
1027
1035
- // Add requirements for each of the associated types.
1036
- // FIXME: This should use the generic signature, not walk the members.
1037
- for (auto Member : Proto->getMembers ()) {
1038
- if (auto AssocType = dyn_cast<AssociatedTypeDecl>(Member)) {
1039
- // Add requirements placed directly on this associated type.
1040
- auto AssocPA = T->getNestedType (AssocType, *this );
1041
- // Requirements introduced by the main protocol are explicit in a protocol
1042
- // requirement signature, but inferred from this conformance otherwise.
1043
- auto Kind = Source.getKind () ==
1044
- RequirementSource::ProtocolRequirementSignatureSelf
1045
- ? RequirementSource::Explicit
1046
- : RequirementSource::Protocol;
1047
-
1048
- if (AssocPA != T) {
1049
- if (addAbstractTypeParamRequirements (AssocType, AssocPA, Kind, Visited))
1050
- return true ;
1051
- }
1028
+ // Use the requirement signature to avoid rewalking the entire protocol. This
1029
+ // cannot compute the requirement signature directly, because that may be
1030
+ // infinitely recursive: this code is also used to construct it.
1031
+ if (Proto->isRequirementSignatureComputed ()) {
1032
+ auto reqSig = Proto->getRequirementSignature ();
1052
1033
1053
- continue ;
1034
+ for (auto req : reqSig->getRequirements ()) {
1035
+ RequirementSource InnerSource (Kind, Source.getLoc ());
1036
+ addRequirement (req, InnerSource, T, Visited);
1037
+ }
1038
+ } else {
1039
+ // Conformances to inherit protocols are explicit in a protocol requirement
1040
+ // signature, but inferred from this conformance otherwise.
1041
+ auto InnerKind =
1042
+ Source.getKind () == RequirementSource::ProtocolRequirementSignatureSelf
1043
+ ? RequirementSource::Explicit
1044
+ : RequirementSource::Redundant;
1045
+ RequirementSource InnerSource (InnerKind, Source.getLoc ());
1046
+ // Add all of the inherited protocol requirements, recursively.
1047
+ if (auto resolver = getLazyResolver ())
1048
+ resolver->resolveInheritedProtocols (Proto);
1049
+
1050
+ for (auto InheritedProto :
1051
+ Proto->getInheritedProtocols (getLazyResolver ())) {
1052
+ if (Visited.count (InheritedProto))
1053
+ continue ;
1054
+ if (addConformanceRequirement (T, InheritedProto, InnerSource, Visited))
1055
+ return true ;
1054
1056
}
1055
1057
1056
- // FIXME: Requirement declarations.
1058
+ // Add requirements for each of the associated types.
1059
+ for (auto Member : Proto->getMembers ()) {
1060
+ if (auto AssocType = dyn_cast<AssociatedTypeDecl>(Member)) {
1061
+ // Add requirements placed directly on this associated type.
1062
+ auto AssocPA = T->getNestedType (AssocType, *this );
1063
+
1064
+ if (AssocPA != T) {
1065
+ if (addAbstractTypeParamRequirements (AssocType, AssocPA, Kind,
1066
+ Visited))
1067
+ return true ;
1068
+ }
1069
+
1070
+ continue ;
1071
+ }
1072
+
1073
+ // FIXME: Requirement declarations.
1074
+ }
1057
1075
}
1058
-
1076
+
1059
1077
Visited.erase (Proto);
1060
1078
return false ;
1061
1079
}
@@ -1397,13 +1415,14 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
1397
1415
1398
1416
return false ;
1399
1417
}
1400
-
1418
+
1401
1419
bool ArchetypeBuilder::addSameTypeRequirement (Type Reqt1, Type Reqt2,
1402
- RequirementSource Source) {
1420
+ RequirementSource Source,
1421
+ PotentialArchetype *basePA) {
1403
1422
// Find the potential archetypes.
1404
- PotentialArchetype *T1 = resolveArchetype (Reqt1);
1405
- PotentialArchetype *T2 = resolveArchetype (Reqt2);
1406
-
1423
+ PotentialArchetype *T1 = resolveArchetype (Reqt1, basePA );
1424
+ PotentialArchetype *T2 = resolveArchetype (Reqt2, basePA );
1425
+
1407
1426
// Require that at least one side of the requirement be a potential archetype.
1408
1427
if (!T1 && !T2) {
1409
1428
Diags.diagnose (Source.getLoc (), diag::requires_no_same_type_archetype);
@@ -1609,9 +1628,17 @@ bool ArchetypeBuilder::addRequirement(const RequirementRepr &Req) {
1609
1628
1610
1629
void ArchetypeBuilder::addRequirement (const Requirement &req,
1611
1630
RequirementSource source) {
1631
+ llvm::SmallPtrSet<ProtocolDecl *, 8 > Visited;
1632
+ addRequirement (req, source, nullptr , Visited);
1633
+ }
1634
+
1635
+ void ArchetypeBuilder::addRequirement (
1636
+ const Requirement &req, RequirementSource source,
1637
+ PotentialArchetype *basePA,
1638
+ llvm::SmallPtrSetImpl<ProtocolDecl *> &Visited) {
1612
1639
switch (req.getKind ()) {
1613
1640
case RequirementKind::Superclass: {
1614
- PotentialArchetype *pa = resolveArchetype (req.getFirstType ());
1641
+ PotentialArchetype *pa = resolveArchetype (req.getFirstType (), basePA );
1615
1642
if (!pa) return ;
1616
1643
1617
1644
assert (req.getSecondType ()->getClassOrBoundGenericClass ());
@@ -1620,30 +1647,31 @@ void ArchetypeBuilder::addRequirement(const Requirement &req,
1620
1647
}
1621
1648
1622
1649
case RequirementKind::Layout: {
1623
- PotentialArchetype *pa = resolveArchetype (req.getFirstType ());
1650
+ PotentialArchetype *pa = resolveArchetype (req.getFirstType (), basePA );
1624
1651
if (!pa) return ;
1625
1652
1626
1653
(void )addLayoutRequirement (pa, req.getLayoutConstraint (), source);
1627
1654
return ;
1628
1655
}
1629
1656
1630
1657
case RequirementKind::Conformance: {
1631
- PotentialArchetype *pa = resolveArchetype (req.getFirstType ());
1658
+ PotentialArchetype *pa = resolveArchetype (req.getFirstType (), basePA );
1632
1659
if (!pa) return ;
1633
1660
1634
1661
SmallVector<ProtocolDecl *, 4 > conformsTo;
1635
1662
(void )req.getSecondType ()->isExistentialType (conformsTo);
1636
1663
1637
1664
// Add each of the protocols.
1638
1665
for (auto proto : conformsTo) {
1639
- (void )addConformanceRequirement (pa, proto, source);
1666
+ (void )addConformanceRequirement (pa, proto, source, Visited );
1640
1667
}
1641
1668
1642
1669
return ;
1643
1670
}
1644
1671
1645
1672
case RequirementKind::SameType:
1646
- addSameTypeRequirement (req.getFirstType (), req.getSecondType (), source);
1673
+ addSameTypeRequirement (req.getFirstType (), req.getSecondType (), source,
1674
+ basePA);
1647
1675
return ;
1648
1676
}
1649
1677
0 commit comments