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"
@@ -4886,14 +4887,93 @@ TypeConverter::checkFunctionForABIDifferences(SILModule &M,
48864887 return ABIDifference::CompatibleRepresentation;
48874888}
48884889
4890+ static void findCapturedEnvironments (
4891+ Type type,
4892+ SmallSetVector<GenericEnvironment *, 2 > &boxCapturedEnvs) {
4893+ type.visit ([&](Type t) {
4894+ if (auto *archetypeTy = t->getAs <LocalArchetypeType>()) {
4895+ boxCapturedEnvs.insert (archetypeTy->getGenericEnvironment ());
4896+ }
4897+ });
4898+ }
4899+
48894900CanSILBoxType
48904901TypeConverter::getInterfaceBoxTypeForCapture (ValueDecl *captured,
4891- CanType loweredInterfaceType,
4902+ CanType loweredContextType,
4903+ GenericSignature genericSig,
4904+ ArrayRef<GenericEnvironment *> capturedEnvs,
48924905 bool isMutable) {
4906+ auto boxType = getInterfaceBoxTypeForCapture (captured,
4907+ loweredContextType,
4908+ isMutable);
4909+
4910+ LLVM_DEBUG (llvm::dbgs () << " Generic signature of closure: "
4911+ << genericSig << " \n " ;);
4912+ LLVM_DEBUG (llvm::dbgs () << " Box type: "
4913+ << boxType << " \n " ;);
4914+
48934915 auto &C = M.getASTContext ();
4894- auto signature = getCanonicalSignatureOrNull (
4916+ auto baseGenericSig = getCanonicalSignatureOrNull (
48954917 captured->getDeclContext ()->getGenericSignatureOfContext ());
48964918
4919+ SmallSetVector<GenericEnvironment *, 2 > boxCapturedEnvs;
4920+ findCapturedEnvironments (loweredContextType, boxCapturedEnvs);
4921+
4922+ return cast<SILBoxType>(Type (boxType).subst (
4923+ [&](SubstitutableType *t) -> Type {
4924+ auto *paramTy = cast<GenericTypeParamType>(t);
4925+
4926+ // Depth of first captured local archetype in box generic signature.
4927+ unsigned depth = baseGenericSig.getNextDepth ();
4928+
4929+ // Is this a captured local archetype?
4930+ if (paramTy->getDepth () >= depth) {
4931+ // Get the environment.
4932+ auto *genericEnv = boxCapturedEnvs[paramTy->getDepth () - depth];
4933+
4934+ // Find this environment in the captured environments of our
4935+ // closure.
4936+ auto found = std::find (capturedEnvs.begin (), capturedEnvs.end (),
4937+ genericEnv);
4938+ assert (found != capturedEnvs.end ());
4939+ unsigned capturedEnvIndex = found - capturedEnvs.begin ();
4940+
4941+ // Remap the depth. This is necessary because the 'var' box might
4942+ // capture a subset of the captured environments of the closure.
4943+ return GenericTypeParamType::get (
4944+ /* isParameterPack=*/ false ,
4945+ genericSig.getNextDepth () - capturedEnvs.size () + capturedEnvIndex,
4946+ paramTy->getIndex (),
4947+ C);
4948+ }
4949+
4950+ return paramTy;
4951+ },
4952+ MakeAbstractConformanceForGenericType (),
4953+ SubstFlags::PreservePackExpansionLevel |
4954+ SubstFlags::AllowLoweredTypes)->getCanonicalType ());
4955+ }
4956+
4957+ CanSILBoxType
4958+ TypeConverter::getInterfaceBoxTypeForCapture (ValueDecl *captured,
4959+ CanType loweredContextType,
4960+ bool isMutable) {
4961+ auto &C = M.getASTContext ();
4962+ auto baseGenericSig = getCanonicalSignatureOrNull (
4963+ captured->getDeclContext ()->getGenericSignatureOfContext ());
4964+
4965+ SmallSetVector<GenericEnvironment *, 2 > boxCapturedEnvs;
4966+ findCapturedEnvironments (loweredContextType, boxCapturedEnvs);
4967+
4968+ MapLocalArchetypesOutOfContext mapOutOfContext (baseGenericSig,
4969+ boxCapturedEnvs.getArrayRef ());
4970+
4971+ auto loweredInterfaceType = loweredContextType.subst (
4972+ mapOutOfContext,
4973+ MakeAbstractConformanceForGenericType (),
4974+ SubstFlags::PreservePackExpansionLevel |
4975+ SubstFlags::AllowLoweredTypes)->getCanonicalType ();
4976+
48974977 // If the type is not dependent at all, we can form a concrete box layout.
48984978 // We don't need to capture the generic environment.
48994979 if (!loweredInterfaceType->hasTypeParameter ()) {
@@ -4902,64 +4982,44 @@ TypeConverter::getInterfaceBoxTypeForCapture(ValueDecl *captured,
49024982 /* captures generics*/ false );
49034983 return SILBoxType::get (C, layout, {});
49044984 }
4985+
4986+ auto boxGenericSig = buildGenericSignatureWithCapturedEnvironments (
4987+ M.getASTContext (), baseGenericSig,
4988+ boxCapturedEnvs.getArrayRef ()).getCanonicalSignature ();
49054989
49064990 // Otherwise, the layout needs to capture the generic environment of its
49074991 // originating scope.
49084992 // TODO: We could conceivably minimize the captured generic environment to
49094993 // only the parts used by the captured variable.
4910-
4911- auto layout = SILLayout::get (C, signature,
4994+ auto layout = SILLayout::get (C, boxGenericSig,
49124995 SILField (loweredInterfaceType, isMutable),
49134996 /* captures generics*/ false );
4914-
4915- // Instantiate the layout with identity substitutions.
4916- auto subMap = signature->getIdentitySubstitutionMap ();
49174997
4918- auto boxTy = SILBoxType::get (C, layout, subMap);
4919- #ifndef NDEBUG
4920- auto loweredContextType = loweredInterfaceType;
4921- auto contextBoxTy = boxTy;
4922- if (signature) {
4923- auto env = signature.getGenericEnvironment ();
4924- loweredContextType = env->mapTypeIntoContext (loweredContextType)
4925- ->getCanonicalType ();
4926- contextBoxTy = cast<SILBoxType>(
4927- env->mapTypeIntoContext (contextBoxTy)
4928- ->getCanonicalType ());
4929- }
4998+ // Instantiate the layout with identity substitutions.
4999+ auto subMap = boxGenericSig->getIdentitySubstitutionMap ();
49305000
4931- auto ty = getSILBoxFieldType (TypeExpansionContext::minimal (), contextBoxTy,
4932- *this , 0 );
4933- assert (contextBoxTy->getLayout ()->getFields ().size () == 1 &&
4934- ty.getRawASTType () == loweredContextType &&
4935- " box field type doesn't match capture!" );
4936- #endif
4937- return boxTy;
5001+ return SILBoxType::get (C, layout, subMap);
49385002}
49395003
49405004CanSILBoxType
49415005TypeConverter::getContextBoxTypeForCapture (ValueDecl *captured,
49425006 CanType loweredContextType,
49435007 GenericEnvironment *env,
49445008 bool isMutable) {
4945- CanType loweredInterfaceType = loweredContextType;
4946- if (env) {
4947- auto homeSig = captured->getDeclContext ()
4948- ->getGenericSignatureOfContext ();
4949- loweredInterfaceType =
4950- loweredInterfaceType->mapTypeOutOfContext ()
4951- ->getReducedType (homeSig);
4952- }
4953-
5009+ SmallSetVector<GenericEnvironment *, 2 > boxCapturedEnvs;
5010+ findCapturedEnvironments (loweredContextType, boxCapturedEnvs);
5011+
49545012 auto boxType = getInterfaceBoxTypeForCapture (captured,
4955- loweredInterfaceType ,
5013+ loweredContextType ,
49565014 isMutable);
4957- if (env)
4958- boxType = cast<SILBoxType>(
4959- env->mapTypeIntoContext (boxType)
4960- ->getCanonicalType ());
4961-
4962- return boxType;
5015+
5016+ MapIntoLocalArchetypeContext mapIntoContext (env, boxCapturedEnvs.getArrayRef ());
5017+
5018+ return cast<SILBoxType>(
5019+ Type (boxType).subst (mapIntoContext,
5020+ LookUpConformanceInModule (&M),
5021+ SubstFlags::PreservePackExpansionLevel |
5022+ SubstFlags::AllowLoweredTypes)->getCanonicalType ());
49635023}
49645024
49655025CanSILBoxType TypeConverter::getBoxTypeForEnumElement (
0 commit comments