@@ -904,6 +904,73 @@ void ConstraintSystem::openGeneric(
904
904
replacements);
905
905
}
906
906
907
+ // / Bind type variables for archetypes that are determined from
908
+ // / context.
909
+ // /
910
+ // / For example, if we are opening a generic function type
911
+ // / nested inside another function, we must bind the outer
912
+ // / generic parameters to context archetypes, because the
913
+ // / nested function can "capture" these outer generic parameters.
914
+ // /
915
+ // / Another case where this comes up is if a generic type is
916
+ // / nested inside a function. We don't support codegen for this
917
+ // / yet, but again we need to bind any outer generic parameters
918
+ // / to context archetypes, because they're not free.
919
+ // /
920
+ // / A final case we have to handle, even though it is invalid, is
921
+ // / when a type is nested inside another protocol. We bind the
922
+ // / protocol type variable for the protocol Self to its archetype
923
+ // / in protocol context. This of course makes no sense, but we
924
+ // / can't leave the type variable dangling, because then we crash
925
+ // / later.
926
+ // /
927
+ // / If we ever do want to allow nominal types to be nested inside
928
+ // / protocols, the key is to set their declared type to a
929
+ // / NominalType whose parent is the 'Self' generic parameter, and
930
+ // / not the ProtocolType. Then, within a conforming type context,
931
+ // / we can 'reparent' the NominalType to that concrete type, and
932
+ // / resolve references to associated types inside that NominalType
933
+ // / relative to this concrete 'Self' type.
934
+ // /
935
+ // / Also, of course IRGen would have to know to store the 'Self'
936
+ // / metadata as an extra hidden generic parameter in the metadata
937
+ // / of such a type, etc.
938
+ static void bindArchetypesFromContext (
939
+ ConstraintSystem &cs,
940
+ DeclContext *outerDC,
941
+ ConstraintLocator *locatorPtr,
942
+ const llvm::DenseMap<CanType, TypeVariableType *> &replacements) {
943
+
944
+ bool inTypeContext = true ;
945
+ for (const auto *parentDC = outerDC;
946
+ !parentDC->isModuleScopeContext ();
947
+ parentDC = parentDC->getParent ()) {
948
+ if (!parentDC->isTypeContext ())
949
+ inTypeContext = false ;
950
+
951
+ if ((!inTypeContext && parentDC->isInnermostContextGeneric ()) ||
952
+ (parentDC->getAsProtocolOrProtocolExtensionContext () &&
953
+ parentDC != outerDC)) {
954
+ for (auto gpDecl : *parentDC->getGenericParamsOfContext ()) {
955
+ auto gp = gpDecl->getDeclaredType ();
956
+ auto *archetype = ArchetypeBuilder::mapTypeIntoContext (parentDC, gp)
957
+ ->castTo <ArchetypeType>();
958
+ auto found = replacements.find (gp->getCanonicalType ());
959
+
960
+ // When opening up an UnboundGenericType, we only pass in the
961
+ // innermost generic parameters as 'params' above -- outer
962
+ // parameters are not opened, so we must skip them here.
963
+ if (found != replacements.end ()) {
964
+ auto typeVar = found->second ;
965
+ cs.addConstraint (ConstraintKind::Bind, typeVar, archetype,
966
+ locatorPtr);
967
+ }
968
+ }
969
+ }
970
+ }
971
+
972
+ }
973
+
907
974
void ConstraintSystem::openGeneric (
908
975
DeclContext *innerDC,
909
976
DeclContext *outerDC,
@@ -914,8 +981,6 @@ void ConstraintSystem::openGeneric(
914
981
llvm::DenseMap<CanType, TypeVariableType *> &replacements) {
915
982
auto locatorPtr = getConstraintLocator (locator);
916
983
917
- unsigned minOpeningDepth = outerDC->getGenericTypeContextDepth ();
918
-
919
984
// Create the type variables for the generic parameters.
920
985
for (auto gp : params) {
921
986
auto *archetype = ArchetypeBuilder::mapTypeIntoContext (innerDC, gp)
@@ -926,12 +991,8 @@ void ConstraintSystem::openGeneric(
926
991
TVO_PrefersSubtypeBinding |
927
992
TVO_MustBeMaterializable);
928
993
replacements[gp->getCanonicalType ()] = typeVar;
929
-
930
- if (gp->getDepth () < minOpeningDepth)
931
- addConstraint (ConstraintKind::Bind, typeVar, archetype, locatorPtr);
932
994
}
933
995
934
-
935
996
GetTypeVariable getTypeVariable{*this , locator};
936
997
ReplaceDependentTypes replaceDependentTypes (*this , locator, replacements,
937
998
getTypeVariable);
@@ -941,6 +1002,7 @@ void ConstraintSystem::openGeneric(
941
1002
locatorPtr = getConstraintLocator (
942
1003
locator.withPathElement (ConstraintLocator::OpenedGeneric));
943
1004
1005
+ bindArchetypesFromContext (*this , outerDC, locatorPtr, replacements);
944
1006
945
1007
// Add the requirements as constraints.
946
1008
for (auto req : requirements) {
0 commit comments