Skip to content

Commit de1b0f4

Browse files
authored
Merge pull request #72853 from slavapestov/fix-variadic-opaque-6.0
[6.0] Fix two bugs with opaque return types -vs- parameter packs
2 parents 25ceeb8 + 8f713a9 commit de1b0f4

File tree

14 files changed

+170
-15
lines changed

14 files changed

+170
-15
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: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,9 @@ class ASTMangler : public Mangler {
703703
void appendConcreteProtocolConformance(
704704
const ProtocolConformance *conformance,
705705
GenericSignature sig);
706+
void appendPackProtocolConformance(
707+
const PackConformance *conformance,
708+
GenericSignature sig);
706709
void appendDependentProtocolConformance(const ConformancePath &path,
707710
GenericSignature sig);
708711
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/AST/ASTMangler.cpp

Lines changed: 57 additions & 7 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"
@@ -1874,8 +1875,22 @@ static bool isRetroactiveConformance(const RootProtocolConformance *root) {
18741875
/// Determine whether the given protocol conformance contains a retroactive
18751876
/// protocol conformance anywhere in it.
18761877
static bool containsRetroactiveConformance(
1877-
const ProtocolConformance *conformance,
1878+
ProtocolConformanceRef conformanceRef,
18781879
ModuleDecl *module) {
1880+
if (!conformanceRef.isPack() && !conformanceRef.isConcrete())
1881+
return false;
1882+
1883+
if (conformanceRef.isPack()) {
1884+
for (auto patternConf : conformanceRef.getPack()->getPatternConformances()) {
1885+
if (containsRetroactiveConformance(patternConf, module))
1886+
return true;
1887+
}
1888+
1889+
return false;
1890+
}
1891+
1892+
auto *conformance = conformanceRef.getConcrete();
1893+
18791894
// If the root conformance is retroactive, it's retroactive.
18801895
const RootProtocolConformance *rootConformance =
18811896
conformance->getRootConformance();
@@ -1897,8 +1912,7 @@ static bool containsRetroactiveConformance(
18971912
// for indexing purposes.
18981913
continue;
18991914
}
1900-
if (conformance.isConcrete() &&
1901-
containsRetroactiveConformance(conformance.getConcrete(), module)) {
1915+
if (containsRetroactiveConformance(conformance, module)) {
19021916
return true;
19031917
}
19041918
}
@@ -1924,14 +1938,18 @@ void ASTMangler::appendRetroactiveConformances(SubstitutionMap subMap,
19241938
};
19251939

19261940
// Ignore abstract conformances.
1927-
if (!conformance.isConcrete())
1941+
if (!conformance.isConcrete() && !conformance.isPack())
19281942
continue;
19291943

19301944
// Skip non-retroactive conformances.
1931-
if (!containsRetroactiveConformance(conformance.getConcrete(), fromModule))
1945+
if (!containsRetroactiveConformance(conformance, fromModule))
19321946
continue;
19331947

1934-
appendConcreteProtocolConformance(conformance.getConcrete(), sig);
1948+
if (conformance.isConcrete())
1949+
appendConcreteProtocolConformance(conformance.getConcrete(), sig);
1950+
else
1951+
appendPackProtocolConformance(conformance.getPack(), sig);
1952+
19351953
appendOperator("g", Index(numProtocolRequirements));
19361954
}
19371955
}
@@ -4143,8 +4161,14 @@ void ASTMangler::appendAnyProtocolConformance(
41434161
appendDependentProtocolConformance(conformancePath, opaqueSignature);
41444162
appendType(conformingType, genericSig);
41454163
appendOperator("HO");
4146-
} else {
4164+
} else if (conformance.isConcrete()) {
41474165
appendConcreteProtocolConformance(conformance.getConcrete(), genericSig);
4166+
} else if (conformance.isPack()) {
4167+
appendPackProtocolConformance(conformance.getPack(), genericSig);
4168+
} else {
4169+
llvm::errs() << "Bad conformance in mangler: ";
4170+
conformance.dump(llvm::errs());
4171+
abort();
41484172
}
41494173
}
41504174

@@ -4199,6 +4223,32 @@ void ASTMangler::appendConcreteProtocolConformance(
41994223
appendOperator("HC");
42004224
}
42014225

4226+
void ASTMangler::appendPackProtocolConformance(
4227+
const PackConformance *conformance,
4228+
GenericSignature sig) {
4229+
auto conformingType = conformance->getType();
4230+
auto patternConformances = conformance->getPatternConformances();
4231+
assert(conformingType->getNumElements() == patternConformances.size());
4232+
4233+
if (conformingType->getNumElements() == 0) {
4234+
appendOperator("y");
4235+
} else {
4236+
bool firstField = true;
4237+
for (unsigned i = 0, e = conformingType->getNumElements(); i < e; ++i) {
4238+
auto type = conformingType->getElementType(i);
4239+
auto conf = patternConformances[i];
4240+
4241+
if (auto *expansionTy = type->getAs<PackExpansionType>())
4242+
type = expansionTy->getPatternType();
4243+
4244+
appendAnyProtocolConformance(sig, type->getCanonicalType(), conf);
4245+
appendListSeparator(firstField);
4246+
}
4247+
}
4248+
4249+
appendOperator("HX");
4250+
}
4251+
42024252
void ASTMangler::appendOpParamForLayoutConstraint(LayoutConstraint layout) {
42034253
assert(layout);
42044254
switch (layout->getKind()) {

lib/AST/Type.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5364,10 +5364,10 @@ CanType swift::substOpaqueTypesWithUnderlyingTypes(CanType ty,
53645364
ReplaceOpaqueTypesWithUnderlyingTypes replacer(
53655365
context.getContext(), context.getResilienceExpansion(),
53665366
context.isWholeModuleContext());
5367-
SubstOptions flags = SubstFlags::SubstituteOpaqueArchetypes;
5367+
SubstOptions flags = (SubstFlags::SubstituteOpaqueArchetypes |
5368+
SubstFlags::PreservePackExpansionLevel);
53685369
if (allowLoweredTypes)
5369-
flags =
5370-
SubstFlags::SubstituteOpaqueArchetypes | SubstFlags::AllowLoweredTypes;
5370+
flags |= SubstFlags::AllowLoweredTypes;
53715371
return ty.subst(replacer, replacer, flags)->getCanonicalType();
53725372
}
53735373

lib/Demangling/Demangler.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,7 @@ NodePointer Demangler::demangleOperator() {
996996
case 'p':
997997
return createWithChild(
998998
Node::Kind::ProtocolConformanceRefInProtocolModule, popProtocol());
999+
case 'X': return demanglePackProtocolConformance();
9991000

10001001
// Runtime records (type/protocol/conformance/function)
10011002
case 'c':
@@ -1847,6 +1848,7 @@ NodePointer Demangler::popAnyProtocolConformance() {
18471848
return popNode([](Node::Kind kind) {
18481849
switch (kind) {
18491850
case Node::Kind::ConcreteProtocolConformance:
1851+
case Node::Kind::PackProtocolConformance:
18501852
case Node::Kind::DependentProtocolConformanceRoot:
18511853
case Node::Kind::DependentProtocolConformanceInherited:
18521854
case Node::Kind::DependentProtocolConformanceAssociated:
@@ -1884,6 +1886,13 @@ NodePointer Demangler::demangleConcreteProtocolConformance() {
18841886
type, conformanceRef, conditionalConformanceList);
18851887
}
18861888

1889+
NodePointer Demangler::demanglePackProtocolConformance() {
1890+
NodePointer patternConformanceList = popAnyProtocolConformanceList();
1891+
1892+
return createWithChild(Node::Kind::PackProtocolConformance,
1893+
patternConformanceList);
1894+
}
1895+
18871896
NodePointer Demangler::popDependentProtocolConformance() {
18881897
return popNode([](Node::Kind kind) {
18891898
switch (kind) {

lib/Demangling/NodePrinter.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ class NodePrinter {
596596
case Node::Kind::AnonymousContext:
597597
case Node::Kind::AnyProtocolConformanceList:
598598
case Node::Kind::ConcreteProtocolConformance:
599+
case Node::Kind::PackProtocolConformance:
599600
case Node::Kind::DependentAssociatedConformance:
600601
case Node::Kind::DependentProtocolConformanceAssociated:
601602
case Node::Kind::DependentProtocolConformanceInherited:
@@ -3106,12 +3107,31 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
31063107
printChildren(Node, depth);
31073108
return nullptr;
31083109
case Node::Kind::AnyProtocolConformanceList:
3109-
printChildren(Node, depth);
3110+
if (Node->getNumChildren() > 0) {
3111+
Printer << "(";
3112+
for (unsigned i = 0; i < Node->getNumChildren(); ++i) {
3113+
if (i > 0)
3114+
Printer << ", ";
3115+
print(Node->getChild(i), depth + 1);
3116+
}
3117+
Printer << ")";
3118+
}
31103119
return nullptr;
31113120
case Node::Kind::ConcreteProtocolConformance:
31123121
Printer << "concrete protocol conformance ";
31133122
if (Node->hasIndex())
31143123
Printer << "#" << Node->getIndex() << " ";
3124+
print(Node->getChild(0), depth + 1);
3125+
Printer << " to ";
3126+
print(Node->getChild(1), depth + 1);
3127+
if (Node->getNumChildren() > 2 &&
3128+
Node->getChild(2)->getNumChildren() > 0) {
3129+
Printer << " with conditional requirements: ";
3130+
print(Node->getChild(2), depth + 1);
3131+
}
3132+
return nullptr;
3133+
case Node::Kind::PackProtocolConformance:
3134+
Printer << "pack protocol conformance ";
31153135
printChildren(Node, depth);
31163136
return nullptr;
31173137
case Node::Kind::DependentAssociatedConformance:
@@ -3122,18 +3142,21 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
31223142
Printer << "dependent associated protocol conformance ";
31233143
printOptionalIndex(Node->getChild(2));
31243144
print(Node->getChild(0), depth + 1);
3145+
Printer << " to ";
31253146
print(Node->getChild(1), depth + 1);
31263147
return nullptr;
31273148
case Node::Kind::DependentProtocolConformanceInherited:
31283149
Printer << "dependent inherited protocol conformance ";
31293150
printOptionalIndex(Node->getChild(2));
31303151
print(Node->getChild(0), depth + 1);
3152+
Printer << " to ";
31313153
print(Node->getChild(1), depth + 1);
31323154
return nullptr;
31333155
case Node::Kind::DependentProtocolConformanceRoot:
31343156
Printer << "dependent root protocol conformance ";
31353157
printOptionalIndex(Node->getChild(2));
31363158
print(Node->getChild(0), depth + 1);
3159+
Printer << " to ";
31373160
print(Node->getChild(1), depth + 1);
31383161
return nullptr;
31393162
case Node::Kind::ProtocolConformanceRefInTypeModule:

lib/Demangling/OldRemangler.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,12 @@ ManglingError Remangler::mangleConcreteProtocolConformance(Node *node,
517517
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
518518
}
519519

520+
ManglingError Remangler::manglePackProtocolConformance(Node *node,
521+
unsigned depth) {
522+
// Pack conformances aren't in the old mangling
523+
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
524+
}
525+
520526
ManglingError Remangler::mangleAnyProtocolConformanceList(Node *node,
521527
unsigned depth) {
522528
// Conformance lists aren't in the old mangling

lib/Demangling/Remangler.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2614,6 +2614,14 @@ ManglingError Remangler::mangleConcreteProtocolConformance(Node *node,
26142614
return ManglingError::Success;
26152615
}
26162616

2617+
ManglingError Remangler::manglePackProtocolConformance(Node *node,
2618+
unsigned depth) {
2619+
RETURN_IF_ERROR(
2620+
mangleAnyProtocolConformanceList(node->getChild(0), depth + 1));
2621+
Buffer << "HX";
2622+
return ManglingError::Success;
2623+
}
2624+
26172625
ManglingError
26182626
Remangler::mangleDependentProtocolConformanceRoot(Node *node, unsigned depth) {
26192627
RETURN_IF_ERROR(mangleType(node->getChild(0), depth + 1));
@@ -2663,6 +2671,8 @@ ManglingError Remangler::mangleAnyProtocolConformance(Node *node,
26632671
switch (node->getKind()) {
26642672
case Node::Kind::ConcreteProtocolConformance:
26652673
return mangleConcreteProtocolConformance(node, depth + 1);
2674+
case Node::Kind::PackProtocolConformance:
2675+
return manglePackProtocolConformance(node, depth + 1);
26662676
case Node::Kind::DependentProtocolConformanceRoot:
26672677
return mangleDependentProtocolConformanceRoot(node, depth + 1);
26682678
case Node::Kind::DependentProtocolConformanceInherited:

test/Demangle/Inputs/manglings.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,3 +472,4 @@ $sSRyxG15Synchronization19AtomicRepresentableABRi_zrlMc ---> protocol conformanc
472472
$sSRyxG15Synchronization19AtomicRepresentableABRi0_zrlMc ---> protocol conformance descriptor for < where A: ~Swift.Escapable> Swift.UnsafeBufferPointer<A> : Synchronization.AtomicRepresentable in Synchronization
473473
$sSRyxG15Synchronization19AtomicRepresentableABRi1_zrlMc ---> protocol conformance descriptor for < where A: ~Swift.<bit 2>> Swift.UnsafeBufferPointer<A> : Synchronization.AtomicRepresentable in Synchronization
474474

475+
$s23variadic_generic_opaque2G2VyAA2S1V_AA2S2VQPGAA1PHPAeA1QHPyHC_AgaJHPyHCHX_HC ---> concrete protocol conformance variadic_generic_opaque.G2<Pack{variadic_generic_opaque.S1, variadic_generic_opaque.S2}> to protocol conformance ref (type's module) variadic_generic_opaque.P with conditional requirements: (pack protocol conformance (concrete protocol conformance variadic_generic_opaque.S1 to protocol conformance ref (type's module) variadic_generic_opaque.Q, concrete protocol conformance variadic_generic_opaque.S2 to protocol conformance ref (type's module) variadic_generic_opaque.Q))
Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,42 @@
1-
// RUN: %target-swift-frontend -emit-ir %s -disable-availability-checking
2-
3-
// FIXME: Add more tests
1+
// RUN: %target-swift-frontend -emit-ir %s -disable-availability-checking | %FileCheck %s
42

53
public protocol P {}
64

75
public struct G<each T>: P {}
86

9-
public func returnsG<each T>(_ t: repeat each T) -> some P {
7+
public func concreteG<each T>(_ t: repeat each T) -> some P {
8+
return G<repeat each T>()
9+
}
10+
11+
public func abstractG<T>(_ t: T) -> some P {
12+
return G<T>()
13+
}
14+
15+
public func variadicG<each T>(_ t: repeat each T) -> some P {
1016
return G<repeat each T>()
1117
}
18+
19+
// Opaque return type is witnessed by a conditional conformance
20+
protocol Q {}
21+
22+
struct S1: Q {}
23+
struct S2: Q {}
24+
25+
struct G2<each T> {}
26+
extension G2: P where repeat each T: Q {}
27+
28+
func concreteG2() -> some P {
29+
G2<S1, S2>()
30+
}
31+
32+
func abstractG2<T: Q>(_: T) -> some P {
33+
G2<S1, T>()
34+
}
35+
36+
func variadicG2<each T: Q>(_: repeat each T) -> some P {
37+
G2<repeat each T>()
38+
}
39+
40+
// CHECK: define private ptr @"get_witness_table 23variadic_generic_opaque2G2VyAA2S1V_AA2S2VQPGAA1PHPAeA1QHPyHC_AgaJHPyHCHX_HC"
41+
// CHECK: define private ptr @"get_witness_table 23variadic_generic_opaque1QRzlAA2G2VyAA2S1V_xQPGAA1PHPAfaBHPyHC_xAaBHD1_HX_HC"
42+
// CHECK: define private ptr @"get_witness_table Rvz23variadic_generic_opaque1QRzlAA2G2VyxxQp_QPGAA1PHPxAaBHD1__HX_HC"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public protocol P {
2+
func f()
3+
}
4+
5+
public struct G<each T>: P {
6+
public func f() {}
7+
}
8+
9+
public func callee<each T>(_: repeat each T) -> some P {
10+
G<repeat each T>()
11+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/variadic_generic_opaque_multifile_other.swift -disable-availability-checking
2+
// RUN: %target-swift-frontend -emit-silgen %s %S/Inputs/variadic_generic_opaque_multifile_other.swift -disable-availability-checking
3+
4+
public func caller() {
5+
callee(1, 2, 3).f()
6+
}

0 commit comments

Comments
 (0)