Skip to content

Commit c399640

Browse files
committed
ASTPrinter: Fix printing variadic BoundGenericTypes
1 parent 914e0c4 commit c399640

File tree

3 files changed

+92
-18
lines changed

3 files changed

+92
-18
lines changed

lib/AST/ASTPrinter.cpp

Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5282,12 +5282,45 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
52825282
Optional<llvm::DenseMap<const clang::Module *, ModuleDecl *>>
52835283
VisibleClangModules;
52845284

5285-
void printGenericArgs(ArrayRef<Type> Args) {
5286-
if (Args.empty())
5285+
void printGenericArgs(TypeArrayView<GenericTypeParamType> params,
5286+
ArrayRef<Type> args) {
5287+
assert(params.size() == args.size());
5288+
5289+
if (args.empty())
52875290
return;
52885291

5292+
// Unlike tuple elements and function type parameter lists, packs are not
5293+
// flattened in the arguments of a generic type, so we need to perform a
5294+
// transformation to print them in a form that will resolve back to the
5295+
// same type:
5296+
//
5297+
// VariadicType<Pack{T1, T2}> => VariadicType<T1, T2>
5298+
// VariadicType<T> => VariadicType<T...> where T is a type parameter pack
5299+
//
5300+
SmallVector<Type, 2> flatArgs;
5301+
for (unsigned i : indices(params)) {
5302+
auto param = params[i];
5303+
auto arg = args[i];
5304+
if (param->isParameterPack()) {
5305+
if (auto *packType = arg->getAs<PackType>()) {
5306+
flatArgs.append(packType->getElementTypes().begin(),
5307+
packType->getElementTypes().end());
5308+
} else {
5309+
assert(arg->is<PackArchetypeType>() ||
5310+
arg->is<TypeVariableType>() ||
5311+
arg->isParameterPack());
5312+
flatArgs.push_back(PackExpansionType::get(arg, arg));
5313+
}
5314+
} else {
5315+
assert(!arg->is<PackType>());
5316+
flatArgs.push_back(arg);
5317+
}
5318+
}
5319+
52895320
Printer << "<";
5290-
interleave(Args, [&](Type Arg) { visit(Arg); }, [&] { Printer << ", "; });
5321+
interleave(flatArgs,
5322+
[&](Type arg) { visit(arg); },
5323+
[&] { Printer << ", "; });
52915324
Printer << ">";
52925325
}
52935326

@@ -5626,7 +5659,13 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
56265659
}
56275660

56285661
printQualifiedType(T);
5629-
printGenericArgs(T->getDirectGenericArgs());
5662+
5663+
auto *typeAliasDecl = T->getDecl();
5664+
if (typeAliasDecl->isGeneric()) {
5665+
auto genericSig = typeAliasDecl->getGenericSignature();
5666+
printGenericArgs(genericSig.getInnermostGenericParams(),
5667+
T->getDirectGenericArgs());
5668+
}
56305669
}
56315670

56325671
void visitParenType(ParenType *T) {
@@ -5711,7 +5750,16 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
57115750
}
57125751
}
57135752
printQualifiedType(T);
5714-
printGenericArgs(T->getGenericArgs());
5753+
5754+
// It would be nicer to use genericSig.getInnermostGenericParams() here,
5755+
// but that triggers a request cycle if we're in the middle of computing
5756+
// the generic signature already.
5757+
SmallVector<Type, 2> paramTypes;
5758+
for (auto *paramDecl : T->getDecl()->getGenericParams()->getParams()) {
5759+
paramTypes.push_back(paramDecl->getDeclaredInterfaceType());
5760+
}
5761+
printGenericArgs(TypeArrayView<GenericTypeParamType>(paramTypes),
5762+
T->getGenericArgs());
57155763
}
57165764

57175765
void visitParentType(Type T) {
@@ -6525,6 +6573,10 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
65256573
return false;
65266574
};
65276575

6576+
auto *namingDecl = T->getDecl()->getNamingDecl();
6577+
auto genericSig = namingDecl->getInnermostDeclContext()
6578+
->getGenericSignatureOfContext();
6579+
65286580
switch (Options.OpaqueReturnTypePrinting) {
65296581
case PrintOptions::OpaqueReturnTypePrintingMode::WithOpaqueKeyword:
65306582
if (printNamedOpaque())
@@ -6542,8 +6594,6 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
65426594

65436595
// Opaque archetype substitutions are always canonical, so re-sugar the
65446596
// constraint type using the owning declaration's generic parameter names.
6545-
auto genericSig = T->getDecl()->getNamingDecl()->getInnermostDeclContext()
6546-
->getGenericSignatureOfContext();
65476597
if (genericSig)
65486598
constraint = genericSig->getSugaredType(constraint);
65496599

@@ -6570,22 +6620,22 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
65706620
// attribute to apply to, but the attribute alone references the opaque
65716621
// type.
65726622
Printer << ") __";
6573-
printGenericArgs(T->getSubstitutions().getReplacementTypes());
6623+
6624+
if (genericSig) {
6625+
printGenericArgs(genericSig.getGenericParams(),
6626+
T->getSubstitutions().getReplacementTypes());
6627+
}
65746628
return;
65756629
}
65766630
case PrintOptions::OpaqueReturnTypePrintingMode::Description: {
65776631
// TODO(opaque): present opaque types with user-facing syntax. we should
65786632
// probably print this as `some P` and record the fact that we printed that
65796633
// so that diagnostics can add followup notes.
6580-
Printer << "(return type of " << T->getDecl()->getNamingDecl()->printRef();
6634+
Printer << "(return type of " << namingDecl->printRef();
65816635
Printer << ')';
6582-
if (!T->getSubstitutions().empty()) {
6583-
Printer << '<';
6584-
auto replacements = T->getSubstitutions().getReplacementTypes();
6585-
llvm::interleave(
6586-
replacements.begin(), replacements.end(), [&](Type t) { visit(t); },
6587-
[&] { Printer << ", "; });
6588-
Printer << '>';
6636+
if (genericSig) {
6637+
printGenericArgs(genericSig.getGenericParams(),
6638+
T->getSubstitutions().getReplacementTypes());
65896639
}
65906640
return;
65916641
}

test/ModuleInterface/pack_expansion_type.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,29 @@ public func variadicFunction<T..., U...>(t: T..., u: U...) -> ((T, U)...) {}
1212
public struct VariadicType<T...> {
1313
// CHECK: public func variadicMethod<U...>(t: T..., u: U...) -> ((T, U)...) where ((T, U)...) : Any
1414
public func variadicMethod<U...>(t: T..., u: U...) -> ((T, U)...) {}
15+
16+
// CHECK: public func returnsSelf() -> PackExpansionType.VariadicType<T...>
17+
public func returnsSelf() -> Self {}
1518
}
1619
// CHECK: }
20+
21+
// CHECK: public func returnsVariadicType() -> PackExpansionType.VariadicType<>
22+
public func returnsVariadicType() -> VariadicType< > {}
23+
24+
// CHECK: public func returnsVariadicType() -> PackExpansionType.VariadicType<Swift.Int, Swift.String, Swift.Float>
25+
public func returnsVariadicType() -> VariadicType<Int, String, Float> {}
26+
27+
// CHECK: public func returnsVariadicType<T...>() -> PackExpansionType.VariadicType<T...>
28+
public func returnsVariadicType<T...>() -> VariadicType<T... > {}
29+
30+
// CHECK: public typealias VariadicAlias<T...> = PackExpansionType.VariadicType<Swift.Array<T>...>
31+
public typealias VariadicAlias<T...> = VariadicType<Array<T>... >
32+
33+
// CHECK: public func returnsVariadicAlias() -> PackExpansionType.VariadicAlias<>
34+
public func returnsVariadicAlias() -> VariadicAlias< > {}
35+
36+
// CHECK: public func returnsVariadicAlias() -> PackExpansionType.VariadicAlias<Swift.Int, Swift.String, Swift.Float>
37+
public func returnsVariadicAlias() -> VariadicAlias<Int, String, Float> {}
38+
39+
// CHECK: public func returnsVariadicAlias<T...>() -> PackExpansionType.VariadicAlias<T...>
40+
public func returnsVariadicAlias<T...>() -> VariadicAlias<T... > {}

test/SILGen/pack_expansion_type.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
public func variadicFunction<T..., U...>(t: T..., u: U...) -> ((T, U)...) {}
99

1010
public struct VariadicType<T...> {
11-
// CHECK-LABEL: sil [ossa] @$s19pack_expansion_type12VariadicTypeV14variadicMethod1t1ux_qd__txQp_txxQp_qd__qd__Qptqd__RhzlF : $@convention(method) <T...><U... where ((T, U)...) : Any> (@in_guaranteed T..., @in_guaranteed U..., VariadicType<T>) -> @out (T, U)... {
12-
// CHECK: bb0(%0 : $*(T, U)..., %1 : $*T..., %2 : $*U..., %3 : $VariadicType<T>):
11+
// CHECK-LABEL: sil [ossa] @$s19pack_expansion_type12VariadicTypeV14variadicMethod1t1ux_qd__txQp_txxQp_qd__qd__Qptqd__RhzlF : $@convention(method) <T...><U... where ((T, U)...) : Any> (@in_guaranteed T..., @in_guaranteed U..., VariadicType<T...>) -> @out (T, U)... {
12+
// CHECK: bb0(%0 : $*(T, U)..., %1 : $*T..., %2 : $*U..., %3 : $VariadicType<T...>):
1313
public func variadicMethod<U...>(t: T..., u: U...) -> ((T, U)...) {}
1414
}

0 commit comments

Comments
 (0)