14
14
//
15
15
// ===----------------------------------------------------------------------===//
16
16
17
+ #define DEBUG_TYPE " ast-types"
18
+
17
19
#include " swift/AST/Types.h"
18
20
#include " ForeignRepresentationInfo.h"
19
21
#include " swift/AST/ASTContext.h"
39
41
#include " llvm/ADT/SmallString.h"
40
42
#include " llvm/ADT/STLExtras.h"
41
43
#include " llvm/Support/Compiler.h"
44
+ #include " llvm/Support/Debug.h"
42
45
#include " llvm/Support/raw_ostream.h"
43
46
#include < algorithm>
44
47
#include < functional>
@@ -1829,6 +1832,15 @@ class IsBindableVisitor
1829
1832
assert (origType->getAnyNominal () == decl
1830
1833
&& substType->getAnyNominal () == decl);
1831
1834
1835
+ LLVM_DEBUG (llvm::dbgs () << " \n ---\n Testing bindability of:\n " ;
1836
+ origType->print (llvm::dbgs ());
1837
+ llvm::dbgs () << " \n to subst type:\n " ;
1838
+ substType->print (llvm::dbgs ());
1839
+ if (upperBound) {
1840
+ llvm::dbgs () << " \n with upper bound archetype:\n " ;
1841
+ upperBound->print (llvm::dbgs ());
1842
+ });
1843
+
1832
1844
auto *moduleDecl = decl->getParentModule ();
1833
1845
auto origSubMap = origType->getContextSubstitutionMap (
1834
1846
moduleDecl, decl, decl->getGenericEnvironment ());
@@ -1841,7 +1853,125 @@ class IsBindableVisitor
1841
1853
llvm::DenseMap<Type, Type> newParamsMap;
1842
1854
bool didChange = false ;
1843
1855
1844
- for (auto gpTy : genericSig.getGenericParams ()) {
1856
+ // The upper bounds for the nominal type's arguments may depend on the
1857
+ // upper bounds imposed on the nominal type itself, if conditional
1858
+ // conformances are involved. For instance, if we're looking at:
1859
+ //
1860
+ // protocol P {}
1861
+ // struct A<T: P> {}
1862
+ // struct B<U> {}
1863
+ // extension B: P where U: P {}
1864
+ //
1865
+ // and visiting `A<B<V>>`, then `B<V>` has an upper bound of `_: P` because
1866
+ // of A's generic type constraint. In order to stay within this upper bound,
1867
+ // `V` must also have `_: P` as its upper bound, in order to satisfy the
1868
+ // constraint on `B<V>`. To handle this correctly, ingest requirements
1869
+ // from any extension declarations providing conformances required by the
1870
+ // upper bound.
1871
+ auto upperBoundGenericSig = genericSig;
1872
+ auto upperBoundSubstMap = substSubMap;
1873
+
1874
+ LLVM_DEBUG (llvm::dbgs () << " \n Nominal type generic signature:\n " ;
1875
+ upperBoundGenericSig.print (llvm::dbgs ());
1876
+ upperBoundSubstMap.dump (llvm::dbgs ()));
1877
+
1878
+ if (upperBound && !upperBound->getConformsTo ().empty ()) {
1879
+ // Start with the set of requirements from the nominal type.
1880
+ SmallVector<Requirement, 4 > addedRequirements;
1881
+
1882
+ llvm::DenseMap<std::pair<CanType, ProtocolDecl*>, ProtocolConformanceRef> addedConformances;
1883
+
1884
+ for (auto proto : upperBound->getConformsTo ()) {
1885
+ // Find the DeclContext providing the conformance for the type.
1886
+ auto nomConformance = moduleDecl->lookupConformance (substType, proto);
1887
+ if (!nomConformance)
1888
+ return CanType ();
1889
+ if (nomConformance.isAbstract ())
1890
+ continue ;
1891
+ auto conformanceContext = nomConformance.getConcrete ()->getDeclContext ();
1892
+
1893
+ LLVM_DEBUG (llvm::dbgs () << " \n Found extension conformance for "
1894
+ << proto->getName ()
1895
+ << " in context:\n " ;
1896
+ conformanceContext->printContext (llvm::dbgs ()));
1897
+
1898
+ auto conformanceSig = conformanceContext->getGenericSignatureOfContext ();
1899
+ // TODO: Conformance on generalized generic extensions could conceivably
1900
+ // have totally different generic signatures.
1901
+ assert (conformanceSig.getGenericParams ().size ()
1902
+ == genericSig.getGenericParams ().size ()
1903
+ && " generalized generic extension not handled properly" );
1904
+
1905
+ // Collect requirements from the conformance not satisfied by the
1906
+ // original declaration.
1907
+ for (auto reqt : conformanceSig->requirementsNotSatisfiedBy (genericSig)) {
1908
+ LLVM_DEBUG (llvm::dbgs () << " \n - adds requirement\n " ;
1909
+ reqt.dump (llvm::dbgs ()));
1910
+
1911
+ addedRequirements.push_back (reqt);
1912
+
1913
+ // Collect the matching conformance for the substituted type.
1914
+ // TODO: Look this up using the upperBoundSubstConformances
1915
+ if (reqt.getKind () == RequirementKind::Conformance) {
1916
+ auto proto = reqt.getSecondType ()->castTo <ProtocolType>()->getDecl ();
1917
+ auto substTy = reqt.getFirstType ().subst (substSubMap);
1918
+ ProtocolConformanceRef substConformance;
1919
+ if (substTy->isTypeParameter ()) {
1920
+ substConformance = ProtocolConformanceRef (proto);
1921
+ } else {
1922
+ substConformance = moduleDecl->lookupConformance (substTy, proto);
1923
+ }
1924
+
1925
+ LLVM_DEBUG (llvm::dbgs () << " \n ` adds conformance for subst type\n " ;
1926
+ substTy->print (llvm::dbgs ());
1927
+ substConformance.dump (llvm::dbgs ()));
1928
+
1929
+ auto key = std::make_pair (reqt.getFirstType ()->getCanonicalType (),
1930
+ proto);
1931
+
1932
+ addedConformances.insert ({key, substConformance});
1933
+ }
1934
+ }
1935
+ }
1936
+
1937
+ // Build the generic signature with the additional collected requirements.
1938
+ if (!addedRequirements.empty ()) {
1939
+ upperBoundGenericSig = evaluateOrDefault (
1940
+ decl->getASTContext ().evaluator ,
1941
+ AbstractGenericSignatureRequest{
1942
+ upperBoundGenericSig.getPointer (),
1943
+ /* genericParams=*/ { },
1944
+ std::move (addedRequirements)},
1945
+ nullptr );
1946
+ upperBoundSubstMap = SubstitutionMap::get (upperBoundGenericSig,
1947
+ [&](SubstitutableType *t) -> Type {
1948
+ // Type substitutions remain the same as the original substitution
1949
+ // map.
1950
+ return Type (t).subst (substSubMap);
1951
+ },
1952
+ [&](CanType dependentType,
1953
+ Type conformingReplacementType,
1954
+ ProtocolDecl *conformedProtocol) -> ProtocolConformanceRef {
1955
+ // Check whether we added this conformance.
1956
+ auto added = addedConformances.find ({dependentType,
1957
+ conformedProtocol});
1958
+ if (added != addedConformances.end ()) {
1959
+ return added->second ;
1960
+ }
1961
+ // Otherwise, use the conformance from the original map.
1962
+
1963
+ return substSubMap.lookupConformance (dependentType, conformedProtocol);
1964
+ });
1965
+
1966
+ LLVM_DEBUG (llvm::dbgs () << " \n Generic signature with conditional reqts:\n " ;
1967
+ upperBoundGenericSig.print (llvm::dbgs ());
1968
+ upperBoundSubstMap.dump (llvm::dbgs ()));
1969
+ }
1970
+ }
1971
+
1972
+ auto upperBoundGenericEnv = upperBoundGenericSig.getGenericEnvironment ();
1973
+
1974
+ for (auto gpTy : upperBoundGenericSig.getGenericParams ()) {
1845
1975
auto gp = gpTy->getCanonicalType ();
1846
1976
1847
1977
auto orig = gp.subst (origSubMap)->getCanonicalType ();
@@ -1855,13 +1985,14 @@ class IsBindableVisitor
1855
1985
// requirements on the type parameters due to conditional conformances.
1856
1986
// These are currently not considered, leading to invalid generic signatures
1857
1987
// built during SILGen.
1858
- auto paramUpperBound = decl->mapTypeIntoContext (gp)
1859
- ->getAs <ArchetypeType>();
1988
+ auto paramUpperBound =
1989
+ GenericEnvironment::mapTypeIntoContext (upperBoundGenericEnv, gp)
1990
+ ->getAs <ArchetypeType>();
1860
1991
SmallVector<ProtocolConformanceRef, 4 > paramSubstConformances;
1861
1992
if (paramUpperBound) {
1862
1993
for (auto proto : paramUpperBound->getConformsTo ()) {
1863
- auto conformance = substSubMap .lookupConformance (gp->getCanonicalType (),
1864
- proto);
1994
+ auto conformance = upperBoundSubstMap .lookupConformance (gp->getCanonicalType (),
1995
+ proto);
1865
1996
if (!conformance)
1866
1997
return CanType ();
1867
1998
paramSubstConformances.push_back (conformance);
0 commit comments