diff --git a/include/swift/AST/SubstitutionMap.h b/include/swift/AST/SubstitutionMap.h index 1610d99d1f36..c536bd24ccd2 100644 --- a/include/swift/AST/SubstitutionMap.h +++ b/include/swift/AST/SubstitutionMap.h @@ -168,7 +168,7 @@ class SubstitutionMap { /// Query whether any replacement types in the map contain an opened /// existential. - bool hasOpenedExistential() const; + bool hasLocalArchetypes() const; /// Query whether any replacement types in the map contain dynamic Self. bool hasDynamicSelf() const; diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h index de196c9befd4..c1ff1d715bd5 100644 --- a/include/swift/SIL/SILCloner.h +++ b/include/swift/SIL/SILCloner.h @@ -192,15 +192,11 @@ class SILCloner : protected SILInstructionVisitor { // If we have local archetypes to substitute, check whether that's // relevant to this particular substitution. if (!LocalArchetypeSubs.empty()) { - for (auto ty : Subs.getReplacementTypes()) { + if (Subs.hasLocalArchetypes()) { // If we found a type containing a local archetype, substitute // open existentials throughout the substitution map. - if (ty->hasLocalArchetype()) { - Subs = Subs.subst(QueryTypeSubstitutionMapOrIdentity{ - LocalArchetypeSubs}, - MakeAbstractConformanceForGenericType()); - break; - } + Subs = Subs.subst(QueryTypeSubstitutionMapOrIdentity{LocalArchetypeSubs}, + MakeAbstractConformanceForGenericType()); } } @@ -223,7 +219,8 @@ class SILCloner : protected SILInstructionVisitor { return Ty.subst( Builder.getModule(), QueryTypeSubstitutionMapOrIdentity{LocalArchetypeSubs}, - MakeAbstractConformanceForGenericType()); + MakeAbstractConformanceForGenericType(), + CanGenericSignature()); } SILType getOpType(SILType Ty) { Ty = getTypeInClonedContext(Ty); diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index a0974f588ec4..fe6dcac73a0e 100644 --- a/lib/AST/ASTMangler.cpp +++ b/lib/AST/ASTMangler.cpp @@ -653,13 +653,14 @@ std::string ASTMangler::mangleAutoDiffGeneratedDeclaration( static Type getTypeForDWARFMangling(Type t) { return t.subst( [](SubstitutableType *t) -> Type { - if (isa(t)) - return t->getCanonicalType(); - return t; + if (isa(t) && + cast(t)->isParameterPack()) { + return PackType::getSingletonPackExpansion(t->getCanonicalType()); + } + return t->getCanonicalType(); }, MakeAbstractConformanceForGenericType(), - SubstFlags::AllowLoweredTypes | - SubstFlags::PreservePackExpansionLevel); + SubstFlags::AllowLoweredTypes); } std::string ASTMangler::mangleTypeForDebugger(Type Ty, GenericSignature sig) { diff --git a/lib/AST/RequirementEnvironment.cpp b/lib/AST/RequirementEnvironment.cpp index 7fea90446c54..68199b37a865 100644 --- a/lib/AST/RequirementEnvironment.cpp +++ b/lib/AST/RequirementEnvironment.cpp @@ -43,6 +43,13 @@ RequirementEnvironment::RequirementEnvironment( auto concreteType = conformanceDC->getSelfInterfaceType(); auto conformanceSig = conformanceDC->getGenericSignatureOfContext(); + auto conformanceToWitnessThunkGenericParamFn = [&](GenericTypeParamType *genericParam) + -> GenericTypeParamType * { + return GenericTypeParamType::get(genericParam->isParameterPack(), + genericParam->getDepth() + (covariantSelf ? 1 : 0), + genericParam->getIndex(), ctx); + }; + // This is a substitution function from the generic parameters of the // conforming type to the witness thunk environment. // @@ -53,25 +60,20 @@ RequirementEnvironment::RequirementEnvironment( // This is a raw function rather than a substitution map because we need to // keep generic parameters as generic, even if the conformanceSig (the best // way to create the substitution map) equates them to concrete types. - auto conformanceToWitnessThunkTypeFn = [&](SubstitutableType *type) { + auto conformanceToWitnessThunkTypeFn = [&](SubstitutableType *type) -> Type { auto *genericParam = cast(type); - if (covariantSelf) { - return GenericTypeParamType::get(genericParam->isParameterPack(), - genericParam->getDepth() + 1, - genericParam->getIndex(), ctx); - } + auto t = conformanceToWitnessThunkGenericParamFn(genericParam); + if (t->isParameterPack()) + return PackType::getSingletonPackExpansion(t); - return GenericTypeParamType::get(genericParam->isParameterPack(), - genericParam->getDepth(), - genericParam->getIndex(), ctx); + return t; }; auto conformanceToWitnessThunkConformanceFn = MakeAbstractConformanceForGenericType(); auto substConcreteType = concreteType.subst( conformanceToWitnessThunkTypeFn, - conformanceToWitnessThunkConformanceFn, - SubstFlags::PreservePackExpansionLevel); + conformanceToWitnessThunkConformanceFn); // Calculate the depth at which the requirement's generic parameters // appear in the witness thunk signature. @@ -168,9 +170,8 @@ RequirementEnvironment::RequirementEnvironment( // Now, add all generic parameters from the conforming type. if (conformanceSig) { for (auto param : conformanceSig.getGenericParams()) { - auto substParam = Type(param).subst(conformanceToWitnessThunkTypeFn, - conformanceToWitnessThunkConformanceFn); - genericParamTypes.push_back(substParam->castTo()); + auto substParam = conformanceToWitnessThunkGenericParamFn(param); + genericParamTypes.push_back(substParam); } } diff --git a/lib/AST/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp index 4e2c64783b8d..663a916bea75 100644 --- a/lib/AST/SubstitutionMap.cpp +++ b/lib/AST/SubstitutionMap.cpp @@ -132,9 +132,9 @@ bool SubstitutionMap::hasArchetypes() const { return false; } -bool SubstitutionMap::hasOpenedExistential() const { +bool SubstitutionMap::hasLocalArchetypes() const { for (Type replacementTy : getReplacementTypesBuffer()) { - if (replacementTy && replacementTy->hasOpenedExistential()) + if (replacementTy && replacementTy->hasLocalArchetype()) return true; } return false; diff --git a/lib/AST/TypeSubstitution.cpp b/lib/AST/TypeSubstitution.cpp index f0e9d9000a99..c520acd8acee 100644 --- a/lib/AST/TypeSubstitution.cpp +++ b/lib/AST/TypeSubstitution.cpp @@ -55,7 +55,13 @@ QueryTypeSubstitutionMapOrIdentity::operator()(SubstitutableType *type) const { auto known = substitutions.find(key); if (known != substitutions.end() && known->second) return known->second; - + + if (isa(type) || + (isa(type) && + cast(type)->isParameterPack())) { + return PackType::getSingletonPackExpansion(type); + } + return type; } diff --git a/test/SILOptimizer/variadic_generics_sil_cloner.swift b/test/SILOptimizer/variadic_generics_sil_cloner.swift new file mode 100644 index 000000000000..2ac038a8911f --- /dev/null +++ b/test/SILOptimizer/variadic_generics_sil_cloner.swift @@ -0,0 +1,18 @@ +// RUN: %target-swift-frontend -emit-sil -O %s | %FileCheck %s + +@_optimize(none) +public func callee(_: T, _: repeat each X) {} + +@_transparent +public func caller(_ x: repeat each X) { + repeat callee(each x, repeat each x) +} + +public func outerCaller(_ x: repeat each X) { + caller(repeat each x) +} + +// CHECK-LABEL: sil @$s28variadic_generics_sil_cloner11outerCalleryyxxQpRvzlF : $@convention(thin) (@pack_guaranteed Pack{repeat each X}) -> () { +// CHECK: [[CALLEE:%.*]] = function_ref @$s28variadic_generics_sil_cloner6calleeyyx_q_q_QptRv_r0_lF : $@convention(thin) <τ_0_0, each τ_0_1> (@in_guaranteed τ_0_0, @pack_guaranteed Pack{repeat each τ_0_1}) -> () +// CHECK: apply [[CALLEE]]<@pack_element("{{.*}}") each X, Pack{repeat each X}>( +// CHECK: // end sil function '$s28variadic_generics_sil_cloner11outerCalleryyxxQpRvzlF'