Skip to content

Commit f061dff

Browse files
committed
[ModuleInterface] Don't print typealiases that match generic params
These are synthesized to satisfy associated type requirements, but they're not needed in source, and they look like self-referential definitions (`typealias X = X`).
1 parent d6c8ca0 commit f061dff

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

lib/AST/ASTPrinter.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,19 +72,39 @@ PrintOptions PrintOptions::printTextualInterfaceFile() {
7272
result.FullyQualifiedTypes = true;
7373
result.SkipImports = true;
7474

75-
class UsableFromInlineOnly : public ShouldPrintChecker {
75+
class ShouldPrintForTextualInterface : public ShouldPrintChecker {
7676
bool shouldPrint(const Decl *D, const PrintOptions &options) override {
77+
// Skip anything that isn't 'public' or '@usableFromInline'.
7778
if (auto *VD = dyn_cast<ValueDecl>(D)) {
7879
AccessScope accessScope =
7980
VD->getFormalAccessScope(/*useDC*/nullptr,
8081
/*treatUsableFromInlineAsPublic*/true);
8182
if (!accessScope.isPublic())
8283
return false;
8384
}
85+
86+
// Skip typealiases that just redeclare generic parameters.
87+
if (auto *alias = dyn_cast<TypeAliasDecl>(D)) {
88+
if (alias->isImplicit()) {
89+
const Decl *parent =
90+
D->getDeclContext()->getAsDeclOrDeclExtensionContext();
91+
if (auto *genericCtx = parent->getAsGenericContext()) {
92+
bool matchesGenericParam =
93+
llvm::any_of(genericCtx->getInnermostGenericParamTypes(),
94+
[alias](const GenericTypeParamType *param) {
95+
return param->getName() == alias->getName();
96+
});
97+
if (matchesGenericParam)
98+
return false;
99+
}
100+
}
101+
}
102+
84103
return ShouldPrintChecker::shouldPrint(D, options);
85104
}
86105
};
87-
result.CurrentPrintabilityChecker = std::make_shared<UsableFromInlineOnly>();
106+
result.CurrentPrintabilityChecker =
107+
std::make_shared<ShouldPrintForTextualInterface>();
88108

89109
// FIXME: We don't really need 'public' on everything; we could just change
90110
// the default to 'public' and mark the 'internal' things.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-swift-frontend -emit-interface-path %t.swiftinterface -emit-module -o /dev/null %s
2+
// RUN: %FileCheck %s < %t.swiftinterface
3+
// RUN: %FileCheck -check-prefix NEGATIVE %s < %t.swiftinterface
4+
5+
// CHECK-LABEL: public protocol SimpleProto {
6+
public protocol SimpleProto {
7+
// CHECK: associatedtype Element
8+
associatedtype Element
9+
// CHECK: associatedtype Inferred
10+
associatedtype Inferred
11+
func inference(_: Inferred)
12+
} // CHECK: {{^}$}}
13+
14+
// CHECK-LABEL: public struct SimplImpl<Element> : SimpleProto {
15+
public struct SimplImpl<Element>: SimpleProto {
16+
// NEGATIVE-NOT: typealias Element =
17+
// CHECK: public func inference(_: Int){{$}}
18+
public func inference(_: Int) {}
19+
// CHECK: public typealias Inferred = Swift.Int
20+
} // CHECK: {{^}$}}

0 commit comments

Comments
 (0)