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"
@@ -4848,14 +4849,93 @@ TypeConverter::checkFunctionForABIDifferences(SILModule &M,
4848
4849
return ABIDifference::CompatibleRepresentation;
4849
4850
}
4850
4851
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
+
4851
4862
CanSILBoxType
4852
4863
TypeConverter::getInterfaceBoxTypeForCapture (ValueDecl *captured,
4853
- CanType loweredInterfaceType,
4864
+ CanType loweredContextType,
4865
+ GenericSignature genericSig,
4866
+ ArrayRef<GenericEnvironment *> capturedEnvs,
4854
4867
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
+
4855
4877
auto &C = M.getASTContext ();
4856
- auto signature = getCanonicalSignatureOrNull (
4878
+ auto baseGenericSig = getCanonicalSignatureOrNull (
4857
4879
captured->getDeclContext ()->getGenericSignatureOfContext ());
4858
4880
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
+
4859
4939
// If the type is not dependent at all, we can form a concrete box layout.
4860
4940
// We don't need to capture the generic environment.
4861
4941
if (!loweredInterfaceType->hasTypeParameter ()) {
@@ -4864,64 +4944,44 @@ TypeConverter::getInterfaceBoxTypeForCapture(ValueDecl *captured,
4864
4944
/* captures generics*/ false );
4865
4945
return SILBoxType::get (C, layout, {});
4866
4946
}
4947
+
4948
+ auto boxGenericSig = buildGenericSignatureWithCapturedEnvironments (
4949
+ M.getASTContext (), baseGenericSig,
4950
+ boxCapturedEnvs.getArrayRef ()).getCanonicalSignature ();
4867
4951
4868
4952
// Otherwise, the layout needs to capture the generic environment of its
4869
4953
// originating scope.
4870
4954
// TODO: We could conceivably minimize the captured generic environment to
4871
4955
// only the parts used by the captured variable.
4872
-
4873
- auto layout = SILLayout::get (C, signature,
4956
+ auto layout = SILLayout::get (C, boxGenericSig,
4874
4957
SILField (loweredInterfaceType, isMutable),
4875
4958
/* captures generics*/ false );
4876
-
4877
- // Instantiate the layout with identity substitutions.
4878
- auto subMap = signature->getIdentitySubstitutionMap ();
4879
4959
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 ();
4892
4962
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);
4900
4964
}
4901
4965
4902
4966
CanSILBoxType
4903
4967
TypeConverter::getContextBoxTypeForCapture (ValueDecl *captured,
4904
4968
CanType loweredContextType,
4905
4969
GenericEnvironment *env,
4906
4970
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
+
4916
4974
auto boxType = getInterfaceBoxTypeForCapture (captured,
4917
- loweredInterfaceType ,
4975
+ loweredContextType ,
4918
4976
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 ());
4925
4985
}
4926
4986
4927
4987
CanSILBoxType TypeConverter::getBoxTypeForEnumElement (
0 commit comments