@@ -1816,24 +1816,57 @@ ASTContext::getConformance(Type conformingType,
1816
1816
// / that instead.
1817
1817
static ProtocolConformance *collapseSpecializedConformance (
1818
1818
Type type,
1819
- ProtocolConformance *conformance) {
1819
+ ProtocolConformance *conformance,
1820
+ SubstitutionList substitutions) {
1820
1821
while (true ) {
1821
- // If the conformance matches, return it.
1822
- if (conformance->getType ()->isEqual (type))
1823
- return conformance;
1824
-
1825
1822
switch (conformance->getKind ()) {
1826
- case ProtocolConformanceKind::Inherited :
1827
- conformance = cast<InheritedProtocolConformance >(conformance)
1828
- ->getInheritedConformance ();
1823
+ case ProtocolConformanceKind::Specialized :
1824
+ conformance = cast<SpecializedProtocolConformance >(conformance)
1825
+ ->getGenericConformance ();
1829
1826
break ;
1830
1827
1828
+ case ProtocolConformanceKind::Normal:
1829
+ case ProtocolConformanceKind::Inherited:
1830
+ // If the conformance matches, return it.
1831
+ if (conformance->getType ()->isEqual (type)) {
1832
+ for (auto substitution : substitutions)
1833
+ for (auto subConformance : substitution.getConformances ())
1834
+ if (!subConformance.isAbstract ())
1835
+ return nullptr ;
1836
+
1837
+ return conformance;
1838
+ }
1839
+
1840
+ return nullptr ;
1841
+ }
1842
+ }
1843
+ }
1844
+
1845
+ // / If one of the ancestor conformances already has a matching type, use
1846
+ // / that instead.
1847
+ static ProtocolConformance *collapseSpecializedConformance (
1848
+ Type type,
1849
+ ProtocolConformance *conformance,
1850
+ const SubstitutionMap &substitutions) {
1851
+ while (true ) {
1852
+ switch (conformance->getKind ()) {
1831
1853
case ProtocolConformanceKind::Specialized:
1832
1854
conformance = cast<SpecializedProtocolConformance>(conformance)
1833
1855
->getGenericConformance ();
1834
1856
break ;
1835
1857
1836
1858
case ProtocolConformanceKind::Normal:
1859
+ case ProtocolConformanceKind::Inherited:
1860
+ // If the conformance matches, return it.
1861
+ if (conformance->getType ()->isEqual (type)) {
1862
+ for (auto conformances : substitutions.getConformanceMap ())
1863
+ for (auto subConformance : conformances.second )
1864
+ if (!subConformance.isAbstract ())
1865
+ return nullptr ;
1866
+
1867
+ return conformance;
1868
+ }
1869
+
1837
1870
return nullptr ;
1838
1871
}
1839
1872
}
@@ -1848,7 +1881,8 @@ ASTContext::getSpecializedConformance(Type type,
1848
1881
// a prior conformance (e.g., mapping into and then out of a conformance),
1849
1882
// return the existing conformance.
1850
1883
if (!alreadyCheckedCollapsed) {
1851
- if (auto existing = collapseSpecializedConformance (type, generic)) {
1884
+ if (auto existing = collapseSpecializedConformance (type, generic,
1885
+ substitutions)) {
1852
1886
++NumCollapsedSpecializedProtocolConformances;
1853
1887
return existing;
1854
1888
}
@@ -1885,7 +1919,7 @@ ASTContext::getSpecializedConformance(Type type,
1885
1919
// If we are performing a substitution that would get us back to the
1886
1920
// a prior conformance (e.g., mapping into and then out of a conformance),
1887
1921
// return the existing conformance.
1888
- if (auto existing = collapseSpecializedConformance (type, generic)) {
1922
+ if (auto existing = collapseSpecializedConformance (type, generic, subMap )) {
1889
1923
++NumCollapsedSpecializedProtocolConformances;
1890
1924
return existing;
1891
1925
}
0 commit comments