Skip to content

Commit 480592a

Browse files
authored
Merge pull request #72847 from slavapestov/fix-rdar123645784
Fix two problems with opaque return types -vs- parameter packs
2 parents dfcf105 + 6d3229a commit 480592a

20 files changed

+285
-138
lines changed

docs/ABI/Mangling.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,7 @@ Property behaviors are implemented using private protocol conformances.
966966

967967
any-protocol-conformance ::= concrete-protocol-conformance
968968
any-protocol-conformance ::= dependent-protocol-conformance
969+
any-protocol-conformance ::= pack-protocol-conformance
969970

970971
any-protocol-conformance-list ::= any-protocol-conformance '_' any-protocol-conformance-list
971972
any-protocol-conformance-list ::= empty-list
@@ -980,6 +981,8 @@ Property behaviors are implemented using private protocol conformances.
980981
dependent-associated-conformance ::= type protocol
981982
dependent-protocol-conformance ::= dependent-protocol-conformance opaque-type 'HO'
982983

984+
pack-protocol-conformance ::= any-protocol-conformance-list 'HX'
985+
983986
A compact representation used to represent mangled protocol conformance witness
984987
arguments at runtime. The ``module`` is only specified for conformances that
985988
are "retroactive", meaning that the context in which the conformance is defined

include/swift/AST/ASTMangler.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -443,8 +443,7 @@ class ASTMangler : public Mangler {
443443
/// Append any retroactive conformances.
444444
void appendRetroactiveConformances(Type type, GenericSignature sig);
445445
void appendRetroactiveConformances(SubstitutionMap subMap,
446-
GenericSignature sig,
447-
ModuleDecl *fromModule);
446+
GenericSignature sig);
448447
void appendImplFunctionType(SILFunctionType *fn, GenericSignature sig,
449448
const ValueDecl *forDecl = nullptr);
450449
void appendOpaqueTypeArchetype(ArchetypeType *archetype,
@@ -703,6 +702,9 @@ class ASTMangler : public Mangler {
703702
void appendConcreteProtocolConformance(
704703
const ProtocolConformance *conformance,
705704
GenericSignature sig);
705+
void appendPackProtocolConformance(
706+
const PackConformance *conformance,
707+
GenericSignature sig);
706708
void appendDependentProtocolConformance(const ConformancePath &path,
707709
GenericSignature sig);
708710
void appendOpParamForLayoutConstraint(LayoutConstraint Layout);

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ NODE(ClangType)
5151
CONTEXT_NODE(Class)
5252
NODE(ClassMetadataBaseOffset)
5353
NODE(ConcreteProtocolConformance)
54+
NODE(PackProtocolConformance)
5455
NODE(ConformanceAttachedMacroExpansion)
5556
CONTEXT_NODE(Constructor)
5657
NODE(CoroutineContinuationPrototype)

include/swift/Demangling/Demangler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,7 @@ class Demangler : public NodeFactory {
587587
NodePointer demangleRetroactiveProtocolConformanceRef();
588588
NodePointer popAnyProtocolConformance();
589589
NodePointer demangleConcreteProtocolConformance();
590+
NodePointer demanglePackProtocolConformance();
590591
NodePointer popDependentProtocolConformance();
591592
NodePointer demangleDependentProtocolConformanceRoot();
592593
NodePointer demangleDependentProtocolConformanceInherited();

lib/APIDigester/ModuleAnalyzerNodes.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1633,7 +1633,9 @@ SwiftDeclCollector::constructTypeNode(Type T, TypeInitInfo Info) {
16331633
ReplaceOpaqueTypesWithUnderlyingTypes replacer(
16341634
/*inContext=*/nullptr, ResilienceExpansion::Maximal,
16351635
/*isWholeModuleContext=*/false);
1636-
T = T.subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes)
1636+
T = T.subst(replacer, replacer,
1637+
SubstFlags::SubstituteOpaqueArchetypes |
1638+
SubstFlags::PreservePackExpansionLevel)
16371639
->getCanonicalType();
16381640
}
16391641
}

lib/AST/ASTMangler.cpp

Lines changed: 96 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "swift/AST/MacroDiscriminatorContext.h"
2929
#include "swift/AST/Module.h"
3030
#include "swift/AST/Ownership.h"
31+
#include "swift/AST/PackConformance.h"
3132
#include "swift/AST/ParameterList.h"
3233
#include "swift/AST/PrettyStackTrace.h"
3334
#include "swift/AST/ProtocolConformance.h"
@@ -1871,20 +1872,11 @@ static bool isRetroactiveConformance(const RootProtocolConformance *root) {
18711872
return conformance->isRetroactive();
18721873
}
18731874

1874-
/// Determine whether the given protocol conformance contains a retroactive
1875-
/// protocol conformance anywhere in it.
1876-
static bool containsRetroactiveConformance(
1877-
const ProtocolConformance *conformance,
1878-
ModuleDecl *module) {
1879-
// If the root conformance is retroactive, it's retroactive.
1880-
const RootProtocolConformance *rootConformance =
1881-
conformance->getRootConformance();
1882-
if (isRetroactiveConformance(rootConformance) &&
1883-
conformanceHasIdentity(rootConformance))
1884-
return true;
1875+
template<typename Fn>
1876+
static bool forEachConditionalConformance(const ProtocolConformance *conformance,
1877+
Fn fn) {
1878+
auto *rootConformance = conformance->getRootConformance();
18851879

1886-
// If the conformance is conditional and any of the substitutions used to
1887-
// satisfy the conditions are retroactive, it's retroactive.
18881880
auto subMap = conformance->getSubstitutionMap();
18891881
for (auto requirement : rootConformance->getConditionalRequirements()) {
18901882
if (requirement.getKind() != RequirementKind::Conformance)
@@ -1897,18 +1889,49 @@ static bool containsRetroactiveConformance(
18971889
// for indexing purposes.
18981890
continue;
18991891
}
1900-
if (conformance.isConcrete() &&
1901-
containsRetroactiveConformance(conformance.getConcrete(), module)) {
1892+
1893+
if (fn(requirement.getFirstType().subst(subMap), conformance))
19021894
return true;
1903-
}
19041895
}
19051896

19061897
return false;
19071898
}
19081899

1900+
/// Determine whether the given protocol conformance contains a retroactive
1901+
/// protocol conformance anywhere in it.
1902+
static bool containsRetroactiveConformance(
1903+
ProtocolConformanceRef conformanceRef) {
1904+
if (!conformanceRef.isPack() && !conformanceRef.isConcrete())
1905+
return false;
1906+
1907+
if (conformanceRef.isPack()) {
1908+
for (auto patternConf : conformanceRef.getPack()->getPatternConformances()) {
1909+
if (containsRetroactiveConformance(patternConf))
1910+
return true;
1911+
}
1912+
1913+
return false;
1914+
}
1915+
1916+
auto *conformance = conformanceRef.getConcrete();
1917+
1918+
// If the root conformance is retroactive, it's retroactive.
1919+
const RootProtocolConformance *rootConformance =
1920+
conformance->getRootConformance();
1921+
if (isRetroactiveConformance(rootConformance) &&
1922+
conformanceHasIdentity(rootConformance))
1923+
return true;
1924+
1925+
// If the conformance is conditional and any of the substitutions used to
1926+
// satisfy the conditions are retroactive, it's retroactive.
1927+
return forEachConditionalConformance(conformance,
1928+
[&](Type substType, ProtocolConformanceRef substConf) -> bool {
1929+
return containsRetroactiveConformance(substConf);
1930+
});
1931+
}
1932+
19091933
void ASTMangler::appendRetroactiveConformances(SubstitutionMap subMap,
1910-
GenericSignature sig,
1911-
ModuleDecl *fromModule) {
1934+
GenericSignature sig) {
19121935
if (subMap.empty()) return;
19131936

19141937
unsigned numProtocolRequirements = 0;
@@ -1924,14 +1947,18 @@ void ASTMangler::appendRetroactiveConformances(SubstitutionMap subMap,
19241947
};
19251948

19261949
// Ignore abstract conformances.
1927-
if (!conformance.isConcrete())
1950+
if (!conformance.isConcrete() && !conformance.isPack())
19281951
continue;
19291952

19301953
// Skip non-retroactive conformances.
1931-
if (!containsRetroactiveConformance(conformance.getConcrete(), fromModule))
1954+
if (!containsRetroactiveConformance(conformance))
19321955
continue;
19331956

1934-
appendConcreteProtocolConformance(conformance.getConcrete(), sig);
1957+
if (conformance.isConcrete())
1958+
appendConcreteProtocolConformance(conformance.getConcrete(), sig);
1959+
else
1960+
appendPackProtocolConformance(conformance.getPack(), sig);
1961+
19351962
appendOperator("g", Index(numProtocolRequirements));
19361963
}
19371964
}
@@ -1954,7 +1981,7 @@ void ASTMangler::appendRetroactiveConformances(Type type, GenericSignature sig)
19541981
subMap = type->getContextSubstitutionMap(module, nominal);
19551982
}
19561983

1957-
appendRetroactiveConformances(subMap, sig, module);
1984+
appendRetroactiveConformances(subMap, sig);
19581985
}
19591986

19601987
void ASTMangler::appendSymbolicExtendedExistentialType(
@@ -1977,11 +2004,7 @@ void ASTMangler::appendSymbolicExtendedExistentialType(
19772004
for (auto argType : genInfo.Generalization.getReplacementTypes())
19782005
appendType(argType, sig, forDecl);
19792006

1980-
// What module should be used here? The existential isn't anchored
1981-
// to any given module; we should just treat conformances as
1982-
// retroactive if they're "objectively" retroactive.
1983-
appendRetroactiveConformances(genInfo.Generalization, sig,
1984-
/*from module*/ nullptr);
2007+
appendRetroactiveConformances(genInfo.Generalization, sig);
19852008
}
19862009

19872010
appendOperator("Xj");
@@ -2172,7 +2195,7 @@ void ASTMangler::appendImplFunctionType(SILFunctionType *fn,
21722195
}
21732196
if (auto subs = fn->getInvocationSubstitutions()) {
21742197
appendFlatGenericArgs(subs, sig, forDecl);
2175-
appendRetroactiveConformances(subs, sig, Mod);
2198+
appendRetroactiveConformances(subs, sig);
21762199
}
21772200
if (auto subs = fn->getPatternSubstitutions()) {
21782201
appendGenericSignature(subs.getGenericSignature());
@@ -2181,7 +2204,7 @@ void ASTMangler::appendImplFunctionType(SILFunctionType *fn,
21812204
? fn->getInvocationGenericSignature()
21822205
: outerGenericSig;
21832206
appendFlatGenericArgs(subs, sig, forDecl);
2184-
appendRetroactiveConformances(subs, sig, Mod);
2207+
appendRetroactiveConformances(subs, sig);
21852208
}
21862209

21872210
OpArgs.push_back('_');
@@ -2217,7 +2240,7 @@ void ASTMangler::appendOpaqueTypeArchetype(ArchetypeType *archetype,
22172240
appendOpaqueDeclName(opaqueDecl);
22182241
bool isFirstArgList = true;
22192242
appendBoundGenericArgs(opaqueDecl, sig, subs, isFirstArgList, forDecl);
2220-
appendRetroactiveConformances(subs, sig, opaqueDecl->getParentModule());
2243+
appendRetroactiveConformances(subs, sig);
22212244

22222245
appendOperator("Qo", Index(genericParam->getIndex()));
22232246
} else {
@@ -4141,62 +4164,73 @@ void ASTMangler::appendAnyProtocolConformance(
41414164
appendDependentProtocolConformance(conformancePath, opaqueSignature);
41424165
appendType(conformingType, genericSig);
41434166
appendOperator("HO");
4144-
} else {
4167+
} else if (conformance.isConcrete()) {
41454168
appendConcreteProtocolConformance(conformance.getConcrete(), genericSig);
4169+
} else if (conformance.isPack()) {
4170+
appendPackProtocolConformance(conformance.getPack(), genericSig);
4171+
} else {
4172+
llvm::errs() << "Bad conformance in mangler: ";
4173+
conformance.dump(llvm::errs());
4174+
abort();
41464175
}
41474176
}
41484177

41494178
void ASTMangler::appendConcreteProtocolConformance(
41504179
const ProtocolConformance *conformance,
41514180
GenericSignature sig) {
4152-
auto module = conformance->getDeclContext()->getParentModule();
4153-
41544181
// Conforming type.
41554182
Type conformingType = conformance->getType();
41564183
if (conformingType->hasArchetype())
41574184
conformingType = conformingType->mapTypeOutOfContext();
4158-
appendType(conformingType->getCanonicalType(), sig);
4185+
appendType(conformingType->getReducedType(sig), sig);
41594186

41604187
// Protocol conformance reference.
41614188
appendProtocolConformanceRef(conformance->getRootConformance());
41624189

41634190
// Conditional conformance requirements.
41644191
bool firstRequirement = true;
4165-
for (const auto &conditionalReq : conformance->getConditionalRequirements()) {
4166-
switch (conditionalReq.getKind()) {
4167-
case RequirementKind::SameShape:
4168-
llvm_unreachable("Same-shape requirement not supported here");
4169-
case RequirementKind::Layout:
4170-
case RequirementKind::SameType:
4171-
case RequirementKind::Superclass:
4172-
continue;
4173-
4174-
case RequirementKind::Conformance: {
4175-
auto type = conditionalReq.getFirstType();
4176-
if (type->hasArchetype())
4177-
type = type->mapTypeOutOfContext();
4178-
CanType canType = type->getReducedType(sig);
4179-
auto proto = conditionalReq.getProtocolDecl();
4180-
4181-
ProtocolConformanceRef conformance;
4182-
4183-
if (canType->isTypeParameter() || canType->is<OpaqueTypeArchetypeType>()){
4184-
conformance = ProtocolConformanceRef(proto);
4185-
} else {
4186-
conformance = module->lookupConformance(canType, proto);
4187-
}
4188-
appendAnyProtocolConformance(sig, canType, conformance);
4192+
forEachConditionalConformance(conformance,
4193+
[&](Type substType, ProtocolConformanceRef substConf) -> bool {
4194+
if (substType->hasArchetype())
4195+
substType = substType->mapTypeOutOfContext();
4196+
CanType canType = substType->getReducedType(sig);
4197+
appendAnyProtocolConformance(sig, canType, substConf);
41894198
appendListSeparator(firstRequirement);
4190-
break;
4191-
}
4192-
}
4193-
}
4199+
return false;
4200+
});
4201+
41944202
if (firstRequirement)
41954203
appendOperator("y");
41964204

41974205
appendOperator("HC");
41984206
}
41994207

4208+
void ASTMangler::appendPackProtocolConformance(
4209+
const PackConformance *conformance,
4210+
GenericSignature sig) {
4211+
auto conformingType = conformance->getType();
4212+
auto patternConformances = conformance->getPatternConformances();
4213+
assert(conformingType->getNumElements() == patternConformances.size());
4214+
4215+
if (conformingType->getNumElements() == 0) {
4216+
appendOperator("y");
4217+
} else {
4218+
bool firstField = true;
4219+
for (unsigned i = 0, e = conformingType->getNumElements(); i < e; ++i) {
4220+
auto type = conformingType->getElementType(i);
4221+
auto conf = patternConformances[i];
4222+
4223+
if (auto *expansionTy = type->getAs<PackExpansionType>())
4224+
type = expansionTy->getPatternType();
4225+
4226+
appendAnyProtocolConformance(sig, type->getCanonicalType(), conf);
4227+
appendListSeparator(firstField);
4228+
}
4229+
}
4230+
4231+
appendOperator("HX");
4232+
}
4233+
42004234
void ASTMangler::appendOpParamForLayoutConstraint(LayoutConstraint layout) {
42014235
assert(layout);
42024236
switch (layout->getKind()) {

lib/AST/Type.cpp

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4464,11 +4464,8 @@ case TypeKind::Id:
44644464
auto sig = opaque->getDecl()->getGenericSignature();
44654465
auto newSubMap =
44664466
SubstitutionMap::get(sig,
4467-
[&](SubstitutableType *t) -> Type {
4468-
auto index = sig->getGenericParamOrdinal(cast<GenericTypeParamType>(t));
4469-
return newSubs[index];
4470-
},
4471-
LookUpConformanceInModule(opaque->getDecl()->getModuleContext()));
4467+
QueryReplacementTypeArray{sig, newSubs},
4468+
LookUpConformanceInModule(opaque->getDecl()->getModuleContext()));
44724469
return OpaqueTypeArchetypeType::get(opaque->getDecl(),
44734470
opaque->getInterfaceType(),
44744471
newSubMap);
@@ -5363,23 +5360,6 @@ Type TypeBase::openAnyExistentialType(OpenedArchetypeType *&opened,
53635360
return opened;
53645361
}
53655362

5366-
CanType swift::substOpaqueTypesWithUnderlyingTypes(CanType ty,
5367-
TypeExpansionContext context,
5368-
bool allowLoweredTypes) {
5369-
if (!context.shouldLookThroughOpaqueTypeArchetypes() ||
5370-
!ty->hasOpaqueArchetype())
5371-
return ty;
5372-
5373-
ReplaceOpaqueTypesWithUnderlyingTypes replacer(
5374-
context.getContext(), context.getResilienceExpansion(),
5375-
context.isWholeModuleContext());
5376-
SubstOptions flags = SubstFlags::SubstituteOpaqueArchetypes;
5377-
if (allowLoweredTypes)
5378-
flags =
5379-
SubstFlags::SubstituteOpaqueArchetypes | SubstFlags::AllowLoweredTypes;
5380-
return ty.subst(replacer, replacer, flags)->getCanonicalType();
5381-
}
5382-
53835363
AnyFunctionType *AnyFunctionType::getWithoutDifferentiability() const {
53845364
SmallVector<Param, 8> newParams;
53855365
for (auto &param : getParams()) {

0 commit comments

Comments
 (0)