Skip to content

Commit 79b5ea0

Browse files
authoredFeb 28, 2017
[PrintAsObjC] Handle generic parameters in extensions. (#7818)
Most of the time, "generics" means "cannot be exposed to Objective-C" and certainly "cannot be exposed in the generated header", but there is one exception: imported Objective-C parameterized types, and their extensions. We were previously dropping this on the floor and printing `Foo</* BarType */>` in the generated header, which is nonsense. https://bugs.swift.org/browse/SR-3480
1 parent 9163017 commit 79b5ea0

File tree

3 files changed

+67
-5
lines changed

3 files changed

+67
-5
lines changed
 

‎lib/PrintAsObjC/PrintAsObjC.cpp

+49-4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "swift/AST/AST.h"
1616
#include "swift/AST/ASTVisitor.h"
1717
#include "swift/AST/ForeignErrorConvention.h"
18+
#include "swift/AST/GenericEnvironment.h"
1819
#include "swift/AST/NameLookup.h"
1920
#include "swift/AST/PrettyStackTrace.h"
2021
#include "swift/AST/ProtocolConformance.h"
@@ -172,6 +173,23 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
172173
ASTVisitor::visit(const_cast<Decl *>(D));
173174
}
174175

176+
void maybePrintObjCGenericParameters(const ClassDecl *importedClass) {
177+
auto *clangDecl = importedClass->getClangDecl();
178+
auto *objcClass = dyn_cast_or_null<clang::ObjCInterfaceDecl>(clangDecl);
179+
if (!objcClass)
180+
return;
181+
if (!objcClass->getTypeParamList())
182+
return;
183+
assert(objcClass->getTypeParamList()->size() != 0);
184+
os << "<";
185+
interleave(*objcClass->getTypeParamList(),
186+
[this](const clang::ObjCTypeParamDecl *param) {
187+
os << param->getName();
188+
},
189+
[this] { os << ", "; });
190+
os << ">";
191+
}
192+
175193
void printAdHocCategory(iterator_range<const ValueDecl * const *> members) {
176194
assert(members.begin() != members.end());
177195

@@ -182,8 +200,10 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
182200
baseClass = extendedTy->getClassOrBoundGenericClass();
183201
}
184202

185-
os << "@interface " << getNameForObjC(baseClass)
186-
<< " (SWIFT_EXTENSION(" << origDC->getParentModule()->getName() << "))\n";
203+
os << "@interface " << getNameForObjC(baseClass);
204+
maybePrintObjCGenericParameters(baseClass);
205+
os << " (SWIFT_EXTENSION(" << origDC->getParentModule()->getName()
206+
<< "))\n";
187207
printMembers</*allowDelayed*/true>(members);
188208
os << "@end\n\n";
189209
}
@@ -312,8 +332,9 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
312332
void visitExtensionDecl(ExtensionDecl *ED) {
313333
auto baseClass = ED->getExtendedType()->getClassOrBoundGenericClass();
314334

315-
os << "@interface " << getNameForObjC(baseClass)
316-
<< " (SWIFT_EXTENSION(" << ED->getModuleContext()->getName() << "))";
335+
os << "@interface " << getNameForObjC(baseClass);
336+
maybePrintObjCGenericParameters(baseClass);
337+
os << " (SWIFT_EXTENSION(" << ED->getModuleContext()->getName() << "))";
317338
printProtocols(ED->getLocalProtocols(ConformanceLookupKind::OnlyExplicit));
318339
os << "\n";
319340
printMembers(ED->getMembers());
@@ -1574,6 +1595,30 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
15741595
visitType(MT, optionalKind);
15751596
}
15761597
}
1598+
1599+
void visitGenericTypeParamType(GenericTypeParamType *type,
1600+
Optional<OptionalTypeKind> optionalKind) {
1601+
const GenericTypeParamDecl *decl = type->getDecl();
1602+
assert(decl && "can't print canonicalized GenericTypeParamType");
1603+
1604+
if (auto *extension = dyn_cast<ExtensionDecl>(decl->getDeclContext())) {
1605+
const ClassDecl *extendedClass =
1606+
extension->getAsClassOrClassExtensionContext();
1607+
assert(extendedClass->isGeneric());
1608+
assert(extension->getGenericParams()->size() ==
1609+
extendedClass->getGenericParams()->size() &&
1610+
"extensions with custom generic parameters?");
1611+
assert(extension->getGenericSignature()->getCanonicalSignature() ==
1612+
extendedClass->getGenericSignature()->getCanonicalSignature() &&
1613+
"constrained extensions or custom generic parameters?");
1614+
type = extendedClass->getGenericEnvironment()->getSugaredType(type);
1615+
decl = type->getDecl();
1616+
}
1617+
1618+
assert(decl->getClangDecl() && "can only handle imported ObjC generics");
1619+
os << cast<clang::ObjCTypeParamDecl>(decl->getClangDecl())->getName();
1620+
printNullability(optionalKind);
1621+
}
15771622

15781623
void printFunctionType(FunctionType *FT, char pointerSigil,
15791624
Optional<OptionalTypeKind> optionalKind) {

‎test/Inputs/clang-importer-sdk/usr/include/objc_generics.h

+3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ void takeGenericClass(__nullable GenericClass<NSString *> *thing);
6767

6868
@end
6969

70+
@interface PettableOverextendedMetaphor: NSObject <Pettable>
71+
@end
72+
7073
@protocol Fungible
7174
@end
7275

‎test/PrintAsObjC/extensions.swift

+15-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ extension CGColor {
8484
func anyOldMethod() {}
8585
}
8686

87-
// CHECK-LABEL: @interface GenericClass (SWIFT_EXTENSION(extensions))
87+
// CHECK-LABEL: @interface GenericClass<T> (SWIFT_EXTENSION(extensions))
8888
// CHECK-NEXT: - (void)bar;
8989
// CHECK-NEXT: @end
9090
extension GenericClass {
@@ -115,3 +115,17 @@ extension NSString {
115115
class func fromColor(_ color: NSColor) -> NSString? { return nil; }
116116
}
117117

118+
// CHECK-LABEL: @interface PettableContainer<T> (SWIFT_EXTENSION(extensions))
119+
// CHECK-NEXT: - (PettableContainer<T> * _Nonnull)duplicate SWIFT_WARN_UNUSED_RESULT;
120+
// CHECK-NEXT: - (PettableContainer<T> * _Nonnull)duplicate2 SWIFT_WARN_UNUSED_RESULT;
121+
// CHECK-NEXT: - (PettableContainer<PettableOverextendedMetaphor *> * _Nonnull)duplicate3 SWIFT_WARN_UNUSED_RESULT;
122+
// CHECK-NEXT: - (T _Nonnull)extract SWIFT_WARN_UNUSED_RESULT;
123+
// CHECK-NEXT: - (T _Nullable)extract2 SWIFT_WARN_UNUSED_RESULT;
124+
// CHECK-NEXT: @end
125+
extension PettableContainer {
126+
func duplicate() -> PettableContainer { fatalError() }
127+
func duplicate2() -> PettableContainer<T> { fatalError() }
128+
func duplicate3() -> PettableContainer<PettableOverextendedMetaphor> { fatalError() }
129+
func extract() -> T { fatalError() }
130+
func extract2() -> T? { fatalError() }
131+
}

0 commit comments

Comments
 (0)
Please sign in to comment.