3232#include " swift/AST/SourceFile.h"
3333#include " swift/AST/TypeDifferenceVisitor.h"
3434#include " swift/AST/Types.h"
35+ #include " swift/Basic/LLVMExtras.h"
3536#include " swift/ClangImporter/ClangModule.h"
3637#include " swift/SIL/AbstractionPatternGenerators.h"
3738#include " swift/SIL/PrettyStackTrace.h"
@@ -4848,14 +4849,93 @@ TypeConverter::checkFunctionForABIDifferences(SILModule &M,
48484849 return ABIDifference::CompatibleRepresentation;
48494850}
48504851
4852+ static void findCapturedEnvironments (
4853+ Type type,
4854+ SmallSetVector<GenericEnvironment *, 2 > &boxCapturedEnvs) {
4855+ type.visit ([&](Type t) {
4856+ if (auto *archetypeTy = t->getAs <LocalArchetypeType>()) {
4857+ boxCapturedEnvs.insert (archetypeTy->getGenericEnvironment ());
4858+ }
4859+ });
4860+ }
4861+
48514862CanSILBoxType
48524863TypeConverter::getInterfaceBoxTypeForCapture (ValueDecl *captured,
4853- CanType loweredInterfaceType,
4864+ CanType loweredContextType,
4865+ GenericSignature genericSig,
4866+ ArrayRef<GenericEnvironment *> capturedEnvs,
48544867 bool isMutable) {
4868+ auto boxType = getInterfaceBoxTypeForCapture (captured,
4869+ loweredContextType,
4870+ isMutable);
4871+
4872+ LLVM_DEBUG (llvm::dbgs () << " Generic signature of closure: "
4873+ << genericSig << " \n " ;);
4874+ LLVM_DEBUG (llvm::dbgs () << " Box type: "
4875+ << boxType << " \n " ;);
4876+
48554877 auto &C = M.getASTContext ();
4856- auto signature = getCanonicalSignatureOrNull (
4878+ auto baseGenericSig = getCanonicalSignatureOrNull (
48574879 captured->getDeclContext ()->getGenericSignatureOfContext ());
48584880
4881+ SmallSetVector<GenericEnvironment *, 2 > boxCapturedEnvs;
4882+ findCapturedEnvironments (loweredContextType, boxCapturedEnvs);
4883+
4884+ return cast<SILBoxType>(Type (boxType).subst (
4885+ [&](SubstitutableType *t) -> Type {
4886+ auto *paramTy = cast<GenericTypeParamType>(t);
4887+
4888+ // Depth of first captured local archetype in box generic signature.
4889+ unsigned depth = baseGenericSig.getNextDepth ();
4890+
4891+ // Is this a captured local archetype?
4892+ if (paramTy->getDepth () >= depth) {
4893+ // Get the environment.
4894+ auto *genericEnv = boxCapturedEnvs[paramTy->getDepth () - depth];
4895+
4896+ // Find this environment in the captured environments of our
4897+ // closure.
4898+ auto found = std::find (capturedEnvs.begin (), capturedEnvs.end (),
4899+ genericEnv);
4900+ assert (found != capturedEnvs.end ());
4901+ unsigned capturedEnvIndex = found - capturedEnvs.begin ();
4902+
4903+ // Remap the depth. This is necessary because the 'var' box might
4904+ // capture a subset of the captured environments of the closure.
4905+ return GenericTypeParamType::get (
4906+ /* isParameterPack=*/ false ,
4907+ genericSig.getNextDepth () - capturedEnvs.size () + capturedEnvIndex,
4908+ paramTy->getIndex (),
4909+ C);
4910+ }
4911+
4912+ return paramTy;
4913+ },
4914+ MakeAbstractConformanceForGenericType (),
4915+ SubstFlags::PreservePackExpansionLevel |
4916+ SubstFlags::AllowLoweredTypes)->getCanonicalType ());
4917+ }
4918+
4919+ CanSILBoxType
4920+ TypeConverter::getInterfaceBoxTypeForCapture (ValueDecl *captured,
4921+ CanType loweredContextType,
4922+ bool isMutable) {
4923+ auto &C = M.getASTContext ();
4924+ auto baseGenericSig = getCanonicalSignatureOrNull (
4925+ captured->getDeclContext ()->getGenericSignatureOfContext ());
4926+
4927+ SmallSetVector<GenericEnvironment *, 2 > boxCapturedEnvs;
4928+ findCapturedEnvironments (loweredContextType, boxCapturedEnvs);
4929+
4930+ MapLocalArchetypesOutOfContext mapOutOfContext (baseGenericSig,
4931+ boxCapturedEnvs.getArrayRef ());
4932+
4933+ auto loweredInterfaceType = loweredContextType.subst (
4934+ mapOutOfContext,
4935+ MakeAbstractConformanceForGenericType (),
4936+ SubstFlags::PreservePackExpansionLevel |
4937+ SubstFlags::AllowLoweredTypes)->getCanonicalType ();
4938+
48594939 // If the type is not dependent at all, we can form a concrete box layout.
48604940 // We don't need to capture the generic environment.
48614941 if (!loweredInterfaceType->hasTypeParameter ()) {
@@ -4864,64 +4944,44 @@ TypeConverter::getInterfaceBoxTypeForCapture(ValueDecl *captured,
48644944 /* captures generics*/ false );
48654945 return SILBoxType::get (C, layout, {});
48664946 }
4947+
4948+ auto boxGenericSig = buildGenericSignatureWithCapturedEnvironments (
4949+ M.getASTContext (), baseGenericSig,
4950+ boxCapturedEnvs.getArrayRef ()).getCanonicalSignature ();
48674951
48684952 // Otherwise, the layout needs to capture the generic environment of its
48694953 // originating scope.
48704954 // TODO: We could conceivably minimize the captured generic environment to
48714955 // only the parts used by the captured variable.
4872-
4873- auto layout = SILLayout::get (C, signature,
4956+ auto layout = SILLayout::get (C, boxGenericSig,
48744957 SILField (loweredInterfaceType, isMutable),
48754958 /* captures generics*/ false );
4876-
4877- // Instantiate the layout with identity substitutions.
4878- auto subMap = signature->getIdentitySubstitutionMap ();
48794959
4880- auto boxTy = SILBoxType::get (C, layout, subMap);
4881- #ifndef NDEBUG
4882- auto loweredContextType = loweredInterfaceType;
4883- auto contextBoxTy = boxTy;
4884- if (signature) {
4885- auto env = signature.getGenericEnvironment ();
4886- loweredContextType = env->mapTypeIntoContext (loweredContextType)
4887- ->getCanonicalType ();
4888- contextBoxTy = cast<SILBoxType>(
4889- env->mapTypeIntoContext (contextBoxTy)
4890- ->getCanonicalType ());
4891- }
4960+ // Instantiate the layout with identity substitutions.
4961+ auto subMap = boxGenericSig->getIdentitySubstitutionMap ();
48924962
4893- auto ty = getSILBoxFieldType (TypeExpansionContext::minimal (), contextBoxTy,
4894- *this , 0 );
4895- assert (contextBoxTy->getLayout ()->getFields ().size () == 1 &&
4896- ty.getRawASTType () == loweredContextType &&
4897- " box field type doesn't match capture!" );
4898- #endif
4899- return boxTy;
4963+ return SILBoxType::get (C, layout, subMap);
49004964}
49014965
49024966CanSILBoxType
49034967TypeConverter::getContextBoxTypeForCapture (ValueDecl *captured,
49044968 CanType loweredContextType,
49054969 GenericEnvironment *env,
49064970 bool isMutable) {
4907- CanType loweredInterfaceType = loweredContextType;
4908- if (env) {
4909- auto homeSig = captured->getDeclContext ()
4910- ->getGenericSignatureOfContext ();
4911- loweredInterfaceType =
4912- loweredInterfaceType->mapTypeOutOfContext ()
4913- ->getReducedType (homeSig);
4914- }
4915-
4971+ SmallSetVector<GenericEnvironment *, 2 > boxCapturedEnvs;
4972+ findCapturedEnvironments (loweredContextType, boxCapturedEnvs);
4973+
49164974 auto boxType = getInterfaceBoxTypeForCapture (captured,
4917- loweredInterfaceType ,
4975+ loweredContextType ,
49184976 isMutable);
4919- if (env)
4920- boxType = cast<SILBoxType>(
4921- env->mapTypeIntoContext (boxType)
4922- ->getCanonicalType ());
4923-
4924- return boxType;
4977+
4978+ MapIntoLocalArchetypeContext mapIntoContext (env, boxCapturedEnvs.getArrayRef ());
4979+
4980+ return cast<SILBoxType>(
4981+ Type (boxType).subst (mapIntoContext,
4982+ LookUpConformanceInModule (&M),
4983+ SubstFlags::PreservePackExpansionLevel |
4984+ SubstFlags::AllowLoweredTypes)->getCanonicalType ());
49254985}
49264986
49274987CanSILBoxType TypeConverter::getBoxTypeForEnumElement (
0 commit comments