Skip to content

Commit 1ecf062

Browse files
authored
Merge pull request #33556 from brentdax/how-forward-of-you
[PrintAsObjC] Forward-declare bridged types
2 parents 316475c + a60aad8 commit 1ecf062

File tree

4 files changed

+49
-0
lines changed

4 files changed

+49
-0
lines changed

lib/PrintAsObjC/DeclAndTypePrinter.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,7 @@ class DeclAndTypePrinter::Implementation
13391339
return true;
13401340
}
13411341

1342+
public:
13421343
/// If \p nominal is bridged to an Objective-C class (via a conformance to
13431344
/// _ObjectiveCBridgeable), return that class.
13441345
///
@@ -1369,6 +1370,7 @@ class DeclAndTypePrinter::Implementation
13691370
return objcType->getClassOrBoundGenericClass();
13701371
}
13711372

1373+
private:
13721374
/// If the nominal type is bridged to Objective-C (via a conformance
13731375
/// to _ObjectiveCBridgeable), print the bridged type.
13741376
void printObjCBridgeableType(const NominalTypeDecl *swiftNominal,
@@ -2067,6 +2069,14 @@ bool DeclAndTypePrinter::isEmptyExtensionDecl(const ExtensionDecl *ED) {
20672069
return getImpl().isEmptyExtensionDecl(ED);
20682070
}
20692071

2072+
const TypeDecl *DeclAndTypePrinter::getObjCTypeDecl(const TypeDecl* TD) {
2073+
if (auto *nominal = dyn_cast<NominalTypeDecl>(TD))
2074+
if (auto *bridged = getImpl().getObjCBridgedClass(nominal))
2075+
return bridged;
2076+
2077+
return TD;
2078+
}
2079+
20702080
StringRef
20712081
DeclAndTypePrinter::maybeGetOSObjectBaseName(const clang::NamedDecl *decl) {
20722082
StringRef name = decl->getName();

lib/PrintAsObjC/DeclAndTypePrinter.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ class DeclAndTypePrinter {
7373
/// Is \p ED empty of members and protocol conformances to include?
7474
bool isEmptyExtensionDecl(const ExtensionDecl *ED);
7575

76+
/// Returns the type that will be printed by PrintAsObjC for a parameter or
77+
/// result type resolved to this declaration.
78+
///
79+
/// \warning This handles \c _ObjectiveCBridgeable types, but it doesn't
80+
/// currently know about other aspects of PrintAsObjC behavior, like known
81+
/// types.
82+
const TypeDecl *getObjCTypeDecl(const TypeDecl* TD);
83+
7684
/// Prints a category declaring the given members.
7785
///
7886
/// All members must have the same parent type. The list must not be empty.

lib/PrintAsObjC/ModuleContentsWriter.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "swift/AST/ExistentialLayout.h"
1818
#include "swift/AST/Module.h"
19+
#include "swift/AST/PrettyStackTrace.h"
1920
#include "swift/AST/ProtocolConformance.h"
2021
#include "swift/AST/SwiftNameTranslation.h"
2122
#include "swift/AST/TypeDeclFinder.h"
@@ -235,6 +236,8 @@ class ModuleWriter {
235236
}
236237

237238
bool forwardDeclareMemberTypes(DeclRange members, const Decl *container) {
239+
PrettyStackTraceDecl
240+
entry("printing forward declarations needed by members of", container);
238241
switch (container->getKind()) {
239242
case DeclKind::Class:
240243
case DeclKind::Protocol:
@@ -247,6 +250,7 @@ class ModuleWriter {
247250
bool hadAnyDelayedMembers = false;
248251
SmallVector<ValueDecl *, 4> nestedTypes;
249252
for (auto member : members) {
253+
PrettyStackTraceDecl loopEntry("printing for member", member);
250254
auto VD = dyn_cast<ValueDecl>(member);
251255
if (!VD || !printer.shouldInclude(VD))
252256
continue;
@@ -269,9 +273,14 @@ class ModuleWriter {
269273
ReferencedTypeFinder::walk(VD->getInterfaceType(),
270274
[&](ReferencedTypeFinder &finder,
271275
const TypeDecl *TD) {
276+
PrettyStackTraceDecl
277+
entry("walking its interface type, currently at", TD);
272278
if (TD == container)
273279
return;
274280

281+
// Bridge, if necessary.
282+
TD = printer.getObjCTypeDecl(TD);
283+
275284
if (finder.needsDefinition() && isa<NominalTypeDecl>(TD)) {
276285
// We can delay individual members of classes; do so if necessary.
277286
if (isa<ClassDecl>(container)) {

test/PrintAsObjC/classes.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,26 @@ import SingleGenericClass
4949
// CHECK-NEXT: @end
5050
@objc class B1 : A1 {}
5151

52+
// Used in BridgedTypes test case
53+
struct Notification: _ObjectiveCBridgeable {
54+
func _bridgeToObjectiveC() -> NSNotification { fatalError() }
55+
static func _forceBridgeFromObjectiveC(
56+
_ source: NSNotification,
57+
result: inout Self?
58+
) { fatalError() }
59+
@discardableResult
60+
static func _conditionallyBridgeFromObjectiveC(
61+
_ source: NSNotification,
62+
result: inout Self?
63+
) -> Bool { fatalError() }
64+
@_effects(readonly)
65+
static func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectiveCType?)
66+
-> Self { fatalError() }
67+
}
68+
5269
// CHECK-LABEL: @interface BridgedTypes
5370
// CHECK-NEXT: - (NSDictionary * _Nonnull)dictBridge:(NSDictionary * _Nonnull)x SWIFT_WARN_UNUSED_RESULT;
71+
// CHECK-NEXT: - (NSNotification * _Nonnull)noteBridge:(NSNotification * _Nonnull)x SWIFT_WARN_UNUSED_RESULT;
5472
// CHECK-NEXT: - (NSSet * _Nonnull)setBridge:(NSSet * _Nonnull)x SWIFT_WARN_UNUSED_RESULT;
5573
// CHECK-NEXT: init
5674
// CHECK-NEXT: @end
@@ -59,6 +77,10 @@ import SingleGenericClass
5977
return x
6078
}
6179

80+
@objc func noteBridge(_ x: Notification) -> Notification {
81+
return x
82+
}
83+
6284
@objc func setBridge(_ x: Set<NSObject>) -> Set<NSObject> {
6385
return x
6486
}

0 commit comments

Comments
 (0)