From 58f9a8fa2badfa928571e4b6ede8e9f0fbcb766d Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 6 Sep 2016 17:54:36 -0700 Subject: [PATCH] SILGen: Use the canonical representative when lowering capture types Currently, ArchetypeBuilder::mapTypeOutOfContext() does not pick the canonical representative from a same-type equivalence class. While it should be fixed to do that, for now let's make a targeted fix to explicitly canonicalize capture types with respect to a generic signature when lowering capture types. --- lib/SIL/SILFunctionType.cpp | 23 ++++++++++++++--------- test/SILGen/generic_closures.swift | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp index da2c1ccb825a1..92e1de5b266e1 100644 --- a/lib/SIL/SILFunctionType.cpp +++ b/lib/SIL/SILFunctionType.cpp @@ -737,6 +737,12 @@ static CanSILFunctionType getSILFunctionType(SILModule &M, // from the function to which the argument is attached. if (constant && !constant->isDefaultArgGenerator()) if (auto function = constant->getAnyFunctionRef()) { + auto getCanonicalType = [&](Type t) -> CanType { + if (genericSig) + return genericSig->getCanonicalTypeInContext(t, *M.getSwiftModule()); + return t->getCanonicalType(); + }; + auto &Types = M.Types; auto loweredCaptures = Types.getLoweredLocalCaptures(*function); @@ -745,22 +751,21 @@ static CanSILFunctionType getSILFunctionType(SILModule &M, ParameterConvention convention = ParameterConvention::Direct_Unowned; auto selfMetatype = MetatypeType::get( loweredCaptures.getDynamicSelfType()->getSelfType(), - MetatypeRepresentation::Thick) - ->getCanonicalType(); - SILParameterInfo param(selfMetatype, convention); + MetatypeRepresentation::Thick); + auto canSelfMetatype = getCanonicalType(selfMetatype); + SILParameterInfo param(canSelfMetatype, convention); inputs.push_back(param); continue; } auto *VD = capture.getDecl(); - auto type = VD->getType()->getCanonicalType(); - - type = ArchetypeBuilder::mapTypeOutOfContext( - function->getAsDeclContext(), type)->getCanonicalType(); - + auto type = ArchetypeBuilder::mapTypeOutOfContext( + function->getAsDeclContext(), VD->getType()); + auto canType = getCanonicalType(type); + auto &loweredTL = Types.getTypeLowering( - AbstractionPattern(genericSig, type), type); + AbstractionPattern(genericSig, canType), canType); auto loweredTy = loweredTL.getLoweredType(); switch (Types.getDeclCaptureKind(capture)) { case CaptureKind::None: diff --git a/test/SILGen/generic_closures.swift b/test/SILGen/generic_closures.swift index 7fe82fde0df39..0fb75c6a306de 100644 --- a/test/SILGen/generic_closures.swift +++ b/test/SILGen/generic_closures.swift @@ -294,3 +294,21 @@ func mixed_generic_nongeneric_nesting(t: T) { // CHECK-LABEL: sil shared @_TFF16generic_closures32mixed_generic_nongeneric_nestingurFT1tx_T_L_5outerurFT_T_ : $@convention(thin) () -> () // CHECK-LABEL: sil shared @_TFFF16generic_closures32mixed_generic_nongeneric_nestingurFT1tx_T_L_5outerurFT_T_L_6middleu__rFT1uqd___T_ : $@convention(thin) (@in U) -> () // CHECK-LABEL: sil shared @_TFFFF16generic_closures32mixed_generic_nongeneric_nestingurFT1tx_T_L_5outerurFT_T_L_6middleu__rFT1uqd___T_L_5inneru__rfT_qd__ : $@convention(thin) (@owned @box U) -> @out U + +protocol Doge { + associatedtype Nose : NoseProtocol +} + +protocol NoseProtocol { + associatedtype Squeegee +} + +protocol Doggo {} + +struct DogSnacks {} + +func capture_same_type_representative(slobber: Roo) + where Roo == Daisy.Nose.Squeegee { + var s = DogSnacks() + _ = { _ = s } +}