@@ -1689,13 +1689,11 @@ static bool isSelfDerived(Type selfTy, Type t) {
1689
1689
// / requirement's type to get the type of the witness.
1690
1690
static CanAnyFunctionType
1691
1691
substSelfTypeIntoProtocolRequirementType (SILModule &M,
1692
+ GenericEnvironment *reqtEnv,
1692
1693
CanGenericFunctionType reqtTy,
1693
- ProtocolConformance *conformance) {
1694
- if (conformance == nullptr ) {
1695
- // Default witness thunks just get the requirement type without
1696
- // substituting Self.
1697
- return reqtTy;
1698
- }
1694
+ ProtocolConformance *conformance,
1695
+ GenericEnvironment *&genericEnv,
1696
+ SubstitutionMap &thunkSubs) {
1699
1697
1700
1698
auto &C = M.getASTContext ();
1701
1699
@@ -1775,67 +1773,51 @@ substSelfTypeIntoProtocolRequirementType(SILModule &M,
1775
1773
auto input = reqtTy->getInput ().subst (subs)->getCanonicalType ();
1776
1774
auto result = reqtTy->getResult ().subst (subs)->getCanonicalType ();
1777
1775
1776
+ CanAnyFunctionType reqtSubstTy;
1777
+
1778
1778
// The result might be fully concrete, if the witness had no generic
1779
1779
// signature, and the requirement had no additional generic parameters
1780
1780
// beyond `Self`.
1781
1781
if (!allParams.empty ()) {
1782
1782
builder.finalize (SourceLoc ());
1783
1783
1784
1784
auto *sig = builder.getGenericSignature ();
1785
+ genericEnv = builder.getGenericEnvironment ();
1786
+
1787
+ // Outer generic parameters come from the generic context of
1788
+ // the conformance (which might not be the same as the generic
1789
+ // context of the witness, if the witness is defined in a
1790
+ // superclass, concrete extension or protocol extension).
1791
+ if (auto *outerEnv = conformance->getGenericEnvironment ()) {
1792
+ for (auto pair : outerEnv->getArchetypeToInterfaceMap ()) {
1793
+ auto archetypeTy = pair.first ->getCanonicalType ();
1794
+ auto substTy = pair.second ;
1795
+ auto contextTy = ArchetypeBuilder::mapTypeIntoContext (
1796
+ M.getSwiftModule (), genericEnv, substTy);
1797
+ thunkSubs.addSubstitution (archetypeTy, contextTy);
1798
+ }
1799
+ }
1785
1800
1786
- return cast<GenericFunctionType>(
1801
+ reqtSubstTy = cast<GenericFunctionType>(
1787
1802
GenericFunctionType::get (sig, input, result, reqtTy->getExtInfo ())
1788
1803
->getCanonicalType ());
1789
- }
1790
-
1791
- return CanFunctionType::get (input, result, reqtTy->getExtInfo ());
1792
- }
1793
-
1794
- static GenericEnvironment *
1795
- getSubstitutedGenericEnvironment (SILModule &M,
1796
- GenericEnvironment *reqtEnv,
1797
- CanGenericSignature witnessSig,
1798
- ProtocolConformance *conformance) {
1799
- if (conformance == nullptr ) {
1800
- // Default witness thunks just use the context archetypes of the requirement.
1801
- return reqtEnv;
1802
- }
1803
-
1804
- SmallVector<GenericTypeParamType *, 4 > genericParamTypes;
1805
- TypeSubstitutionMap witnessContextParams;
1806
-
1807
- auto selfTy = conformance->getProtocol ()->getSelfInterfaceType ()
1808
- ->getCanonicalType ();
1804
+ } else {
1805
+ genericEnv = nullptr ;
1809
1806
1810
- // Outer generic parameters come from the generic context of
1811
- // the conformance (which might not be the same as the generic
1812
- // context of the witness, if the witness is defined in a
1813
- // superclass, concrete extension or protocol extension).
1814
- if (auto *outerEnv = conformance->getGenericEnvironment ()) {
1815
- witnessContextParams = outerEnv->getInterfaceToArchetypeMap ();
1816
- for (auto *paramTy : outerEnv->getGenericParams ())
1817
- genericParamTypes.push_back (paramTy);
1807
+ reqtSubstTy = CanFunctionType::get (input, result, reqtTy->getExtInfo ());
1818
1808
}
1819
1809
1820
- for (auto *paramTy : reqtEnv->getGenericParams ().slice (1 ))
1821
- genericParamTypes.push_back (paramTy);
1822
-
1823
1810
// Inner generic parameters come from the requirement and
1824
1811
// also map to the archetypes of the requirement.
1825
- for (auto pair : reqtEnv->getInterfaceToArchetypeMap ()) {
1826
- // Skip the 'Self' parameter and friends.
1827
- if (isSelfDerived (selfTy, pair.first ))
1828
- continue ;
1829
-
1830
- auto result = witnessContextParams.insert (pair);
1831
- assert (result.second );
1812
+ for (auto pair : reqtEnv->getArchetypeToInterfaceMap ()) {
1813
+ auto archetypeTy = pair.first ->getCanonicalType ();
1814
+ auto substTy = pair.second .subst (subs);
1815
+ auto contextTy = ArchetypeBuilder::mapTypeIntoContext (
1816
+ M.getSwiftModule (), genericEnv, substTy);
1817
+ thunkSubs.addSubstitution (archetypeTy, contextTy);
1832
1818
}
1833
1819
1834
- if (!witnessContextParams.empty ())
1835
- return GenericEnvironment::get (M.getASTContext (), genericParamTypes,
1836
- witnessContextParams);
1837
-
1838
- return nullptr ;
1820
+ return reqtSubstTy;
1839
1821
}
1840
1822
1841
1823
SILFunction *
@@ -1846,7 +1828,6 @@ SILGenModule::emitProtocolWitness(ProtocolConformance *conformance,
1846
1828
IsFreeFunctionWitness_t isFree,
1847
1829
ArrayRef<Substitution> witnessSubs) {
1848
1830
auto requirementInfo = Types.getConstantInfo (requirement);
1849
- auto witnessInfo = Types.getConstantInfo (witness);
1850
1831
unsigned witnessUncurryLevel = witness.uncurryLevel ;
1851
1832
1852
1833
// If the witness is a free function, consider the self argument
@@ -1860,11 +1841,37 @@ SILGenModule::emitProtocolWitness(ProtocolConformance *conformance,
1860
1841
assert (requirement.uncurryLevel == witnessUncurryLevel &&
1861
1842
" uncurry level of requirement and witness do not match" );
1862
1843
1844
+ GenericEnvironment *genericEnv = nullptr ;
1845
+
1863
1846
// Work out the lowered function type of the SIL witness thunk.
1864
1847
auto reqtOrigTy
1865
1848
= cast<GenericFunctionType>(requirementInfo.LoweredInterfaceType );
1866
- auto reqtSubstTy
1867
- = substSelfTypeIntoProtocolRequirementType (M, reqtOrigTy, conformance);
1849
+ CanAnyFunctionType reqtSubstTy;
1850
+ if (conformance == nullptr ) {
1851
+ reqtSubstTy = reqtOrigTy;
1852
+ genericEnv = requirementInfo.GenericEnv ;
1853
+ } else {
1854
+ SubstitutionMap thunkSubs;
1855
+ reqtSubstTy
1856
+ = substSelfTypeIntoProtocolRequirementType (M, requirementInfo.GenericEnv ,
1857
+ reqtOrigTy, conformance,
1858
+ genericEnv, thunkSubs);
1859
+
1860
+ // Remap witness substitutions to use the correct archetypes.
1861
+ // Sema produces witness substitutions using a mix of archetypes
1862
+ // from the requirement and the witness. To solve downstream
1863
+ // issues in the SIL optimizer, we build all-new archetypes
1864
+ // using the correct generic signature here.
1865
+ //
1866
+ // FIXME: Once Sema records witness substitutions in terms of
1867
+ // interface types, this code as well as the code that builds
1868
+ // thunkSubs in substSelfTypeIntoProtocolRequirementType() can
1869
+ // be removed.
1870
+ auto newWitnessSubs = getASTContext ().AllocateCopy (witnessSubs);
1871
+ for (unsigned i = 0 , e = witnessSubs.size (); i < e; i++)
1872
+ newWitnessSubs[i] = witnessSubs[i].subst (M.getSwiftModule (), thunkSubs);
1873
+ witnessSubs = newWitnessSubs;
1874
+ }
1868
1875
1869
1876
// Lower the witness thunk type with the requirement's abstraction level.
1870
1877
auto witnessSILFnType = getNativeSILFunctionType (M,
@@ -1900,16 +1907,6 @@ SILGenModule::emitProtocolWitness(ProtocolConformance *conformance,
1900
1907
nameBuffer = mangler.finalize ();
1901
1908
}
1902
1909
1903
- CanGenericSignature witnessSig;
1904
- if (auto gft = dyn_cast<GenericFunctionType>(
1905
- witnessInfo.LoweredInterfaceType ))
1906
- witnessSig = gft.getGenericSignature ();
1907
-
1908
- // Collect the generic environment for the witness.
1909
- GenericEnvironment *requirementEnv = requirementInfo.GenericEnv ;
1910
- GenericEnvironment *witnessEnv = getSubstitutedGenericEnvironment (
1911
- M, requirementEnv, witnessSig, conformance);
1912
-
1913
1910
// If the thunked-to function is set to be always inlined, do the
1914
1911
// same with the witness, on the theory that the user wants all
1915
1912
// calls removed if possible, e.g. when we're able to devirtualize
@@ -1928,7 +1925,7 @@ SILGenModule::emitProtocolWitness(ProtocolConformance *conformance,
1928
1925
1929
1926
auto *f = M.createFunction (
1930
1927
linkage, nameBuffer, witnessSILFnType,
1931
- witnessEnv , SILLocation (witness.getDecl ()),
1928
+ genericEnv , SILLocation (witness.getDecl ()),
1932
1929
IsNotBare, IsTransparent, isFragile, IsThunk,
1933
1930
SILFunction::NotRelevant, InlineStrategy);
1934
1931
@@ -1942,16 +1939,15 @@ SILGenModule::emitProtocolWitness(ProtocolConformance *conformance,
1942
1939
1943
1940
// If the witness is a free function, there is no Self type.
1944
1941
if (!isFree) {
1945
- // If we are emitting a witness thunk for a concrete conformance, Self is
1946
- // just the conforming type.
1947
1942
if (conformance) {
1948
- selfType = conformance->getType ();
1949
-
1950
- // For default implementations, Self is the protocol archetype.
1943
+ selfType = conformance->getInterfaceType ();
1951
1944
} else {
1952
1945
auto *proto = cast<ProtocolDecl>(requirement.getDecl ()->getDeclContext ());
1953
- selfType = proto->getSelfTypeInContext ();
1946
+ selfType = proto->getSelfInterfaceType ();
1954
1947
}
1948
+
1949
+ selfType = ArchetypeBuilder::mapTypeIntoContext (
1950
+ M.getSwiftModule (), genericEnv, selfType);
1955
1951
}
1956
1952
1957
1953
SILGenFunction gen (*this , *f);
0 commit comments