32
32
#include " swift/AST/SourceFile.h"
33
33
#include " swift/AST/TypeDifferenceVisitor.h"
34
34
#include " swift/AST/Types.h"
35
+ #include " swift/Basic/LLVMExtras.h"
35
36
#include " swift/ClangImporter/ClangModule.h"
36
37
#include " swift/SIL/AbstractionPatternGenerators.h"
37
38
#include " swift/SIL/PrettyStackTrace.h"
@@ -4886,14 +4887,93 @@ TypeConverter::checkFunctionForABIDifferences(SILModule &M,
4886
4887
return ABIDifference::CompatibleRepresentation;
4887
4888
}
4888
4889
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
+
4889
4900
CanSILBoxType
4890
4901
TypeConverter::getInterfaceBoxTypeForCapture (ValueDecl *captured,
4891
- CanType loweredInterfaceType,
4902
+ CanType loweredContextType,
4903
+ GenericSignature genericSig,
4904
+ ArrayRef<GenericEnvironment *> capturedEnvs,
4892
4905
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
+
4893
4915
auto &C = M.getASTContext ();
4894
- auto signature = getCanonicalSignatureOrNull (
4916
+ auto baseGenericSig = getCanonicalSignatureOrNull (
4895
4917
captured->getDeclContext ()->getGenericSignatureOfContext ());
4896
4918
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
+
4897
4977
// If the type is not dependent at all, we can form a concrete box layout.
4898
4978
// We don't need to capture the generic environment.
4899
4979
if (!loweredInterfaceType->hasTypeParameter ()) {
@@ -4902,64 +4982,44 @@ TypeConverter::getInterfaceBoxTypeForCapture(ValueDecl *captured,
4902
4982
/* captures generics*/ false );
4903
4983
return SILBoxType::get (C, layout, {});
4904
4984
}
4985
+
4986
+ auto boxGenericSig = buildGenericSignatureWithCapturedEnvironments (
4987
+ M.getASTContext (), baseGenericSig,
4988
+ boxCapturedEnvs.getArrayRef ()).getCanonicalSignature ();
4905
4989
4906
4990
// Otherwise, the layout needs to capture the generic environment of its
4907
4991
// originating scope.
4908
4992
// TODO: We could conceivably minimize the captured generic environment to
4909
4993
// only the parts used by the captured variable.
4910
-
4911
- auto layout = SILLayout::get (C, signature,
4994
+ auto layout = SILLayout::get (C, boxGenericSig,
4912
4995
SILField (loweredInterfaceType, isMutable),
4913
4996
/* captures generics*/ false );
4914
-
4915
- // Instantiate the layout with identity substitutions.
4916
- auto subMap = signature->getIdentitySubstitutionMap ();
4917
4997
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 ();
4930
5000
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);
4938
5002
}
4939
5003
4940
5004
CanSILBoxType
4941
5005
TypeConverter::getContextBoxTypeForCapture (ValueDecl *captured,
4942
5006
CanType loweredContextType,
4943
5007
GenericEnvironment *env,
4944
5008
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
+
4954
5012
auto boxType = getInterfaceBoxTypeForCapture (captured,
4955
- loweredInterfaceType ,
5013
+ loweredContextType ,
4956
5014
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 ());
4963
5023
}
4964
5024
4965
5025
CanSILBoxType TypeConverter::getBoxTypeForEnumElement (
0 commit comments