From 1646085ba7705441bcf68b7854f530041d8af869 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 28 Jun 2023 16:00:34 -0400 Subject: [PATCH 1/3] AST: Replace SubstitutionMap::hasOpenedExistential() with SubstitutionMap::hasLocalArchetypes() and actually use it --- include/swift/AST/SubstitutionMap.h | 2 +- include/swift/SIL/SILCloner.h | 11 ++++------- lib/AST/SubstitutionMap.cpp | 4 ++-- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/include/swift/AST/SubstitutionMap.h b/include/swift/AST/SubstitutionMap.h index 1610d99d1f367..c536bd24ccd2c 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 de196c9befd4e..a599cafdfaa5b 100644 --- a/include/swift/SIL/SILCloner.h +++ b/include/swift/SIL/SILCloner.h @@ -192,15 +192,12 @@ 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()); } } diff --git a/lib/AST/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp index 4e2c64783b8de..663a916bea75c 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; From 61f4d6f65d4c47cfd448a0d36cf0015c7768c048 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Fri, 23 Jun 2023 23:26:38 -0400 Subject: [PATCH 2/3] SIL: Pass SubstFlags::PreservePackExpansionLevel in a few places Fixes rdar://problem/111219086. --- include/swift/SIL/SILCloner.h | 16 ++++++++++------ .../variadic_generics_sil_cloner.swift | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 test/SILOptimizer/variadic_generics_sil_cloner.swift diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h index a599cafdfaa5b..fb0e256adbac8 100644 --- a/include/swift/SIL/SILCloner.h +++ b/include/swift/SIL/SILCloner.h @@ -195,9 +195,9 @@ class SILCloner : protected SILInstructionVisitor { if (Subs.hasLocalArchetypes()) { // If we found a type containing a local archetype, substitute // open existentials throughout the substitution map. - Subs = Subs.subst(QueryTypeSubstitutionMapOrIdentity{ - LocalArchetypeSubs}, - MakeAbstractConformanceForGenericType()); + Subs = Subs.subst(QueryTypeSubstitutionMapOrIdentity{LocalArchetypeSubs}, + MakeAbstractConformanceForGenericType(), + SubstFlags::PreservePackExpansionLevel); } } @@ -220,7 +220,9 @@ class SILCloner : protected SILInstructionVisitor { return Ty.subst( Builder.getModule(), QueryTypeSubstitutionMapOrIdentity{LocalArchetypeSubs}, - MakeAbstractConformanceForGenericType()); + MakeAbstractConformanceForGenericType(), + CanGenericSignature(), + SubstFlags::PreservePackExpansionLevel); } SILType getOpType(SILType Ty) { Ty = getTypeInClonedContext(Ty); @@ -239,7 +241,8 @@ class SILCloner : protected SILInstructionVisitor { return ty.subst( QueryTypeSubstitutionMapOrIdentity{LocalArchetypeSubs}, - MakeAbstractConformanceForGenericType() + MakeAbstractConformanceForGenericType(), + SubstFlags::PreservePackExpansionLevel )->getCanonicalType(); } @@ -352,7 +355,8 @@ class SILCloner : protected SILInstructionVisitor { conformance.subst(ty, QueryTypeSubstitutionMapOrIdentity{ LocalArchetypeSubs}, - MakeAbstractConformanceForGenericType()); + MakeAbstractConformanceForGenericType(), + SubstFlags::PreservePackExpansionLevel); } return asImpl().remapConformance(getASTTypeInClonedContext(ty), diff --git a/test/SILOptimizer/variadic_generics_sil_cloner.swift b/test/SILOptimizer/variadic_generics_sil_cloner.swift new file mode 100644 index 0000000000000..2ac038a8911f6 --- /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' From 2146a5a8e703e03f24e74d1b831e334806255a31 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 28 Jun 2023 19:48:25 -0400 Subject: [PATCH 3/3] AST: Remove some usages of SubstFlags::PreservePackExpansionLevel --- include/swift/SIL/SILCloner.h | 12 ++++-------- lib/AST/ASTMangler.cpp | 11 ++++++----- lib/AST/RequirementEnvironment.cpp | 29 +++++++++++++++-------------- lib/AST/TypeSubstitution.cpp | 8 +++++++- 4 files changed, 32 insertions(+), 28 deletions(-) diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h index fb0e256adbac8..c1ff1d715bd50 100644 --- a/include/swift/SIL/SILCloner.h +++ b/include/swift/SIL/SILCloner.h @@ -196,8 +196,7 @@ class SILCloner : protected SILInstructionVisitor { // If we found a type containing a local archetype, substitute // open existentials throughout the substitution map. Subs = Subs.subst(QueryTypeSubstitutionMapOrIdentity{LocalArchetypeSubs}, - MakeAbstractConformanceForGenericType(), - SubstFlags::PreservePackExpansionLevel); + MakeAbstractConformanceForGenericType()); } } @@ -221,8 +220,7 @@ class SILCloner : protected SILInstructionVisitor { Builder.getModule(), QueryTypeSubstitutionMapOrIdentity{LocalArchetypeSubs}, MakeAbstractConformanceForGenericType(), - CanGenericSignature(), - SubstFlags::PreservePackExpansionLevel); + CanGenericSignature()); } SILType getOpType(SILType Ty) { Ty = getTypeInClonedContext(Ty); @@ -241,8 +239,7 @@ class SILCloner : protected SILInstructionVisitor { return ty.subst( QueryTypeSubstitutionMapOrIdentity{LocalArchetypeSubs}, - MakeAbstractConformanceForGenericType(), - SubstFlags::PreservePackExpansionLevel + MakeAbstractConformanceForGenericType() )->getCanonicalType(); } @@ -355,8 +352,7 @@ class SILCloner : protected SILInstructionVisitor { conformance.subst(ty, QueryTypeSubstitutionMapOrIdentity{ LocalArchetypeSubs}, - MakeAbstractConformanceForGenericType(), - SubstFlags::PreservePackExpansionLevel); + MakeAbstractConformanceForGenericType()); } return asImpl().remapConformance(getASTTypeInClonedContext(ty), diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index a0974f588ec4d..fe6dcac73a0ec 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 7fea90446c545..68199b37a865d 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/TypeSubstitution.cpp b/lib/AST/TypeSubstitution.cpp index f0e9d9000a990..c520acd8acee4 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; }