Skip to content

Commit 65969f1

Browse files
committed
ASTPrinter: Fix printing variadic BoundGenericTypes
1 parent 41406d6 commit 65969f1

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

@@ -5572,7 +5605,13 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
55725605
}
55735606

55745607
printQualifiedType(T);
5575-
printGenericArgs(T->getDirectGenericArgs());
5608+
5609+
auto *typeAliasDecl = T->getDecl();
5610+
if (typeAliasDecl->isGeneric()) {
5611+
auto genericSig = typeAliasDecl->getGenericSignature();
5612+
printGenericArgs(genericSig.getInnermostGenericParams(),
5613+
T->getDirectGenericArgs());
5614+
}
55765615
}
55775616

55785617
void visitParenType(ParenType *T) {
@@ -5657,7 +5696,16 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
56575696
}
56585697
}
56595698
printQualifiedType(T);
5660-
printGenericArgs(T->getGenericArgs());
5699+
5700+
// It would be nicer to use genericSig.getInnermostGenericParams() here,
5701+
// but that triggers a request cycle if we're in the middle of computing
5702+
// the generic signature already.
5703+
SmallVector<Type, 2> paramTypes;
5704+
for (auto *paramDecl : T->getDecl()->getGenericParams()->getParams()) {
5705+
paramTypes.push_back(paramDecl->getDeclaredInterfaceType());
5706+
}
5707+
printGenericArgs(TypeArrayView<GenericTypeParamType>(paramTypes),
5708+
T->getGenericArgs());
56615709
}
56625710

56635711
void visitParentType(Type T) {
@@ -6472,6 +6520,10 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
64726520
return false;
64736521
};
64746522

6523+
auto *namingDecl = T->getDecl()->getNamingDecl();
6524+
auto genericSig = namingDecl->getInnermostDeclContext()
6525+
->getGenericSignatureOfContext();
6526+
64756527
switch (Options.OpaqueReturnTypePrinting) {
64766528
case PrintOptions::OpaqueReturnTypePrintingMode::WithOpaqueKeyword:
64776529
if (printNamedOpaque())
@@ -6489,8 +6541,6 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
64896541

64906542
// Opaque archetype substitutions are always canonical, so re-sugar the
64916543
// constraint type using the owning declaration's generic parameter names.
6492-
auto genericSig = T->getDecl()->getNamingDecl()->getInnermostDeclContext()
6493-
->getGenericSignatureOfContext();
64946544
if (genericSig)
64956545
constraint = genericSig->getSugaredType(constraint);
64966546

@@ -6517,22 +6567,22 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
65176567
// attribute to apply to, but the attribute alone references the opaque
65186568
// type.
65196569
Printer << ") __";
6520-
printGenericArgs(T->getSubstitutions().getReplacementTypes());
6570+
6571+
if (genericSig) {
6572+
printGenericArgs(genericSig.getGenericParams(),
6573+
T->getSubstitutions().getReplacementTypes());
6574+
}
65216575
return;
65226576
}
65236577
case PrintOptions::OpaqueReturnTypePrintingMode::Description: {
65246578
// TODO(opaque): present opaque types with user-facing syntax. we should
65256579
// probably print this as `some P` and record the fact that we printed that
65266580
// so that diagnostics can add followup notes.
6527-
Printer << "(return type of " << T->getDecl()->getNamingDecl()->printRef();
6581+
Printer << "(return type of " << namingDecl->printRef();
65286582
Printer << ')';
6529-
if (!T->getSubstitutions().empty()) {
6530-
Printer << '<';
6531-
auto replacements = T->getSubstitutions().getReplacementTypes();
6532-
llvm::interleave(
6533-
replacements.begin(), replacements.end(), [&](Type t) { visit(t); },
6534-
[&] { Printer << ", "; });
6535-
Printer << '>';
6583+
if (genericSig) {
6584+
printGenericArgs(genericSig.getGenericParams(),
6585+
T->getSubstitutions().getReplacementTypes());
65366586
}
65376587
return;
65386588
}

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)