Skip to content

Commit 78ef746

Browse files
committed
ASTPrinter: Fix printing variadic BoundGenericTypes
1 parent c883393 commit 78ef746

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
@@ -5234,12 +5234,45 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
52345234
Optional<llvm::DenseMap<const clang::Module *, ModuleDecl *>>
52355235
VisibleClangModules;
52365236

5237-
void printGenericArgs(ArrayRef<Type> Args) {
5238-
if (Args.empty())
5237+
void printGenericArgs(TypeArrayView<GenericTypeParamType> params,
5238+
ArrayRef<Type> args) {
5239+
assert(params.size() == args.size());
5240+
5241+
if (args.empty())
52395242
return;
52405243

5244+
// Unlike tuple elements and function type parameter lists, packs are not
5245+
// flattened in the arguments of a generic type, so we need to perform a
5246+
// transformation to print them in a form that will resolve back to the
5247+
// same type:
5248+
//
5249+
// VariadicType<Pack{T1, T2}> => VariadicType<T1, T2>
5250+
// VariadicType<T> => VariadicType<T...> where T is a type parameter pack
5251+
//
5252+
SmallVector<Type, 2> flatArgs;
5253+
for (unsigned i : indices(params)) {
5254+
auto param = params[i];
5255+
auto arg = args[i];
5256+
if (param->isParameterPack()) {
5257+
if (auto *packType = arg->getAs<PackType>()) {
5258+
flatArgs.append(packType->getElementTypes().begin(),
5259+
packType->getElementTypes().end());
5260+
} else {
5261+
assert(arg->is<PackArchetypeType>() ||
5262+
arg->is<TypeVariableType>() ||
5263+
arg->isParameterPack());
5264+
flatArgs.push_back(PackExpansionType::get(arg, arg));
5265+
}
5266+
} else {
5267+
assert(!arg->is<PackType>());
5268+
flatArgs.push_back(arg);
5269+
}
5270+
}
5271+
52415272
Printer << "<";
5242-
interleave(Args, [&](Type Arg) { visit(Arg); }, [&] { Printer << ", "; });
5273+
interleave(flatArgs,
5274+
[&](Type arg) { visit(arg); },
5275+
[&] { Printer << ", "; });
52435276
Printer << ">";
52445277
}
52455278

@@ -5578,7 +5611,13 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
55785611
}
55795612

55805613
printQualifiedType(T);
5581-
printGenericArgs(T->getDirectGenericArgs());
5614+
5615+
auto *typeAliasDecl = T->getDecl();
5616+
if (typeAliasDecl->isGeneric()) {
5617+
auto genericSig = typeAliasDecl->getGenericSignature();
5618+
printGenericArgs(genericSig.getInnermostGenericParams(),
5619+
T->getDirectGenericArgs());
5620+
}
55825621
}
55835622

55845623
void visitParenType(ParenType *T) {
@@ -5663,7 +5702,16 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
56635702
}
56645703
}
56655704
printQualifiedType(T);
5666-
printGenericArgs(T->getGenericArgs());
5705+
5706+
// It would be nicer to use genericSig.getInnermostGenericParams() here,
5707+
// but that triggers a request cycle if we're in the middle of computing
5708+
// the generic signature already.
5709+
SmallVector<Type, 2> paramTypes;
5710+
for (auto *paramDecl : T->getDecl()->getGenericParams()->getParams()) {
5711+
paramTypes.push_back(paramDecl->getDeclaredInterfaceType());
5712+
}
5713+
printGenericArgs(TypeArrayView<GenericTypeParamType>(paramTypes),
5714+
T->getGenericArgs());
56675715
}
56685716

56695717
void visitParentType(Type T) {
@@ -6477,6 +6525,10 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
64776525
return false;
64786526
};
64796527

6528+
auto *namingDecl = T->getDecl()->getNamingDecl();
6529+
auto genericSig = namingDecl->getInnermostDeclContext()
6530+
->getGenericSignatureOfContext();
6531+
64806532
switch (Options.OpaqueReturnTypePrinting) {
64816533
case PrintOptions::OpaqueReturnTypePrintingMode::WithOpaqueKeyword:
64826534
if (printNamedOpaque())
@@ -6494,8 +6546,6 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
64946546

64956547
// Opaque archetype substitutions are always canonical, so re-sugar the
64966548
// constraint type using the owning declaration's generic parameter names.
6497-
auto genericSig = T->getDecl()->getNamingDecl()->getInnermostDeclContext()
6498-
->getGenericSignatureOfContext();
64996549
if (genericSig)
65006550
constraint = genericSig->getSugaredType(constraint);
65016551

@@ -6522,22 +6572,22 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
65226572
// attribute to apply to, but the attribute alone references the opaque
65236573
// type.
65246574
Printer << ") __";
6525-
printGenericArgs(T->getSubstitutions().getReplacementTypes());
6575+
6576+
if (genericSig) {
6577+
printGenericArgs(genericSig.getGenericParams(),
6578+
T->getSubstitutions().getReplacementTypes());
6579+
}
65266580
return;
65276581
}
65286582
case PrintOptions::OpaqueReturnTypePrintingMode::Description: {
65296583
// TODO(opaque): present opaque types with user-facing syntax. we should
65306584
// probably print this as `some P` and record the fact that we printed that
65316585
// so that diagnostics can add followup notes.
6532-
Printer << "(return type of " << T->getDecl()->getNamingDecl()->printRef();
6586+
Printer << "(return type of " << namingDecl->printRef();
65336587
Printer << ')';
6534-
if (!T->getSubstitutions().empty()) {
6535-
Printer << '<';
6536-
auto replacements = T->getSubstitutions().getReplacementTypes();
6537-
llvm::interleave(
6538-
replacements.begin(), replacements.end(), [&](Type t) { visit(t); },
6539-
[&] { Printer << ", "; });
6540-
Printer << '>';
6588+
if (genericSig) {
6589+
printGenericArgs(genericSig.getGenericParams(),
6590+
T->getSubstitutions().getReplacementTypes());
65416591
}
65426592
return;
65436593
}

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)