Skip to content

Commit 87cbb7d

Browse files
committed
AST: New way of printing @_opaqueReturnTypeOf when parameter packs are involved
This is the ASTPrinter change to go with the Sema change. We now print @_opaqueReturnTypeOf using the new nested syntax when parameter packs are involved. Fixes rdar://problem/151171381.
1 parent af78807 commit 87cbb7d

File tree

2 files changed

+152
-3
lines changed

2 files changed

+152
-3
lines changed

lib/AST/ASTPrinter.cpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7515,10 +7515,37 @@ class TypePrinter : public TypeVisitor<TypePrinter, void, NonRecursivePrintOptio
75157515
Printer << ") __";
75167516

75177517
if (genericSig) {
7518-
printGenericArgs(decl->getASTContext(),
7519-
genericSig.getGenericParams(),
7520-
T->getSubstitutions().getReplacementTypes());
7518+
auto &ctx = decl->getASTContext();
7519+
auto params = genericSig.getGenericParams();
7520+
auto args = T->getSubstitutions().getReplacementTypes();
7521+
7522+
// Use the new "nested" syntax if there is at least one parameter pack,
7523+
// because that case didn't round trip at all before anyway. Otherwise,
7524+
// use the old "flat" syntax, even when the owner declaration is in a
7525+
// nested generic context, because we want the generated swiftinterface
7526+
// to continue to work on old compilers.
7527+
if (genericSig->hasParameterPack()) {
7528+
bool first = true;
7529+
7530+
while (!params.empty()) {
7531+
if (!first) { Printer << ".__"; }
7532+
first = false;
7533+
7534+
unsigned end = 1;
7535+
unsigned depth = params.front()->getDepth();
7536+
while (end < params.size() && params[end]->getDepth() == depth) {
7537+
++end;
7538+
}
7539+
7540+
printGenericArgs(ctx, params.take_front(end), args.take_front(end));
7541+
params = params.slice(end);
7542+
args = args.slice(end);
7543+
}
7544+
} else {
7545+
printGenericArgs(ctx, params, args);
7546+
}
75217547
}
7548+
75227549
return;
75237550
}
75247551
case PrintOptions::OpaqueReturnTypePrintingMode::Description: {
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-emit-module-interface(%t/VariadicOpaqueResultTypes.swiftinterface) %s -module-name VariadicOpaqueResultTypes -target %target-swift-5.9-abi-triple
3+
// RUN: %target-swift-typecheck-module-from-interface(%t/VariadicOpaqueResultTypes.swiftinterface) -module-name VariadicOpaqueResultTypes
4+
// RUN: %FileCheck %s < %t/VariadicOpaqueResultTypes.swiftinterface
5+
6+
7+
///
8+
/// First, make sure pack expansions can appear in the generic argument list of an opaque return type.
9+
///
10+
11+
public struct I1<each T>: IteratorProtocol {
12+
public mutating func next() -> (some Any)? { return 3 }
13+
}
14+
15+
// CHECK: public struct I1<each T> : Swift.IteratorProtocol {
16+
// CHECK: public mutating func next() -> (some Any)?
17+
// CHECK: public typealias Element = @_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes2I1V4nextQrSgyF", 0) __<repeat each T>
18+
// CHECK: }
19+
20+
21+
public struct S1<each T>: Sequence {
22+
public func makeIterator() -> some IteratorProtocol {
23+
return I1<repeat each T>()
24+
}
25+
}
26+
27+
// CHECK: public struct S1<each T> : Swift.Sequence {
28+
// CHECK: public func makeIterator() -> some Swift.IteratorProtocol
29+
// CHECK: public typealias Element = (@_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes2S1V12makeIteratorQryF", 0) __<repeat each T>).Element
30+
// CHECK: public typealias Iterator = @_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes2S1V12makeIteratorQryF", 0) __<repeat each T>
31+
// CHECK: }
32+
33+
34+
public struct Scalar<T> {
35+
public struct I2<U>: IteratorProtocol {
36+
public mutating func next() -> (some Any)? { return 3 }
37+
}
38+
}
39+
40+
41+
///
42+
/// Now, test nested types. The next example uses the old "flat" syntax, because parameter packs are not involved.
43+
///
44+
45+
46+
// CHECK: public struct Scalar<T> {
47+
// CHECK: public struct I2<U> : Swift.IteratorProtocol {
48+
// CHECK: public mutating func next() -> (some Any)?
49+
// CHECK: public typealias Element = @_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes6ScalarV2I2V4nextQrSgyF", 0) __<T, U>
50+
// CHECK: }
51+
// CHECK: }
52+
53+
54+
public struct S2: Sequence {
55+
public func makeIterator() -> Scalar<Int>.I2<Bool> {
56+
return .init()
57+
}
58+
}
59+
60+
// CHECK: public struct S2 : Swift.Sequence {
61+
// CHECK: public func makeIterator() -> VariadicOpaqueResultTypes.Scalar<Swift.Int>.I2<Swift.Bool>
62+
// CHECK: public typealias Element = @_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes6ScalarV2I2V4nextQrSgyF", 0) __<Swift.Int, Swift.Bool>
63+
// CHECK: public typealias Iterator = VariadicOpaqueResultTypes.Scalar<Swift.Int>.I2<Swift.Bool>
64+
// CHECK: }
65+
66+
67+
///
68+
/// The remaining examples use the new nested syntax.
69+
///
70+
71+
// CHECK: public struct Variadic<each T> {
72+
public struct Variadic<each T> {
73+
public struct I3<each U>: IteratorProtocol {
74+
public mutating func next() -> (some Any)? { return 3 }
75+
}
76+
77+
// CHECK: public struct I3<each U> : Swift.IteratorProtocol {
78+
// CHECK: public mutating func next() -> (some Any)?
79+
// CHECK: public typealias Element = @_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes0A0V2I3V4nextQrSgyF", 0) __<repeat each T>.__<repeat each U>
80+
// CHECK: }
81+
82+
public struct Middle {
83+
public struct Inner<each U> {
84+
public struct I4: IteratorProtocol {
85+
public mutating func next() -> (some Any)? { return 3 }
86+
}
87+
}
88+
}
89+
90+
// CHECK: public struct Middle {
91+
// CHECK: public struct Inner<each U> {
92+
// CHECK: public struct I4 : Swift.IteratorProtocol {
93+
// CHECK: public mutating func next() -> (some Any)?
94+
// CHECK: public typealias Element = @_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes0A0V6MiddleV5InnerV2I4V4nextQrSgyF", 0) __<repeat each T>.__<repeat each U>
95+
// CHECK: }
96+
// CHECK: }
97+
// CHECK: }
98+
}
99+
// CHECK: }
100+
101+
// CHECK: public struct S3 : Swift.Sequence {
102+
// CHECK: public func makeIterator() -> VariadicOpaqueResultTypes.Variadic<Swift.Int, Swift.Bool>.I3<Swift.Float, Swift.Double>
103+
// CHECK: public typealias Element = @_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes0A0V2I3V4nextQrSgyF", 0) __<Swift.Int, Swift.Bool>.__<Swift.Float, Swift.Double>
104+
// CHECK: public typealias Iterator = VariadicOpaqueResultTypes.Variadic<Swift.Int, Swift.Bool>.I3<Swift.Float, Swift.Double>
105+
// CHECK: }
106+
public struct S3: Sequence {
107+
public func makeIterator() -> Variadic<Int, Bool>.I3<Float, Double> {
108+
return .init()
109+
}
110+
}
111+
112+
// CHECK: public struct S4 : Swift.Sequence {
113+
// CHECK: public func makeIterator() -> VariadicOpaqueResultTypes.Variadic<Swift.Int, Swift.Bool>.Middle.Inner<Swift.Float, Swift.Double>.I4
114+
// CHECK: public typealias Element = @_opaqueReturnTypeOf("$s25VariadicOpaqueResultTypes0A0V6MiddleV5InnerV2I4V4nextQrSgyF", 0) __<Swift.Int, Swift.Bool>.__<Swift.Float, Swift.Double>
115+
// CHECK: public typealias Iterator = VariadicOpaqueResultTypes.Variadic<Swift.Int, Swift.Bool>.Middle.Inner<Swift.Float, Swift.Double>.I4
116+
// CHECK: }
117+
public struct S4: Sequence {
118+
public func makeIterator() -> Variadic<Int, Bool>.Middle.Inner<Float, Double>.I4 {
119+
return .init()
120+
}
121+
}
122+

0 commit comments

Comments
 (0)