15
15
#include " swift/AST/AST.h"
16
16
#include " swift/AST/ASTVisitor.h"
17
17
#include " swift/AST/ForeignErrorConvention.h"
18
+ #include " swift/AST/NameLookup.h"
18
19
#include " swift/AST/PrettyStackTrace.h"
19
20
#include " swift/AST/TypeVisitor.h"
20
21
#include " swift/AST/Comment.h"
37
38
38
39
using namespace swift ;
39
40
40
- static bool isNSObject (ASTContext &ctx, Type type) {
41
+ static bool isNSObjectOrAnyHashable (ASTContext &ctx, Type type) {
41
42
if (auto classDecl = type->getClassOrBoundGenericClass ()) {
42
43
return classDecl->getName ()
43
44
== ctx.getSwiftId (KnownFoundationEntity::NSObject) &&
44
45
classDecl->getModuleContext ()->getName () == ctx.Id_ObjectiveC ;
45
46
}
47
+ if (auto nomDecl = type->getAnyNominal ()) {
48
+ return nomDecl->getName () == ctx.getIdentifier (" AnyHashable" ) &&
49
+ nomDecl->getModuleContext () == ctx.getStdlibModule ();
50
+ }
46
51
47
52
return false ;
48
53
}
49
54
55
+ static bool isAnyObjectOrAny (Type type) {
56
+ return type->isAnyObject () || type->isAny ();
57
+ }
58
+
50
59
// / Returns true if \p name matches a keyword in any Clang language mode.
51
60
static bool isClangKeyword (Identifier name) {
52
61
static const llvm::StringSet<> keywords = []{
@@ -125,6 +134,8 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
125
134
Accessibility minRequiredAccess;
126
135
bool protocolMembersOptional = false ;
127
136
137
+ Optional<Type> NSCopyingType;
138
+
128
139
friend ASTVisitor<ObjCPrinter>;
129
140
friend TypeVisitor<ObjCPrinter>;
130
141
@@ -859,6 +870,8 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
859
870
auto &ctx = swiftNominal->getASTContext ();
860
871
assert (objcClass);
861
872
873
+ Type rewrittenArgsBuf[2 ];
874
+
862
875
// Detect when the type arguments correspond to the unspecialized
863
876
// type, and clear them out. There is some type-specific hackery
864
877
// here for:
@@ -867,13 +880,38 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
867
880
// NSDictionary<NSObject *, id> --> NSDictionary
868
881
// NSSet<id> --> NSSet
869
882
if (!typeArgs.empty () &&
870
- (!hasGenericObjCType (objcClass) ||
871
- (swiftNominal == ctx.getArrayDecl () && typeArgs[0 ]->isAnyObject ()) ||
872
- (swiftNominal == ctx.getDictionaryDecl () &&
873
- isNSObject (ctx, typeArgs[0 ]) && typeArgs[1 ]->isAnyObject ()) ||
874
- (swiftNominal == ctx.getSetDecl () && isNSObject (ctx, typeArgs[0 ])))) {
883
+ (!hasGenericObjCType (objcClass)
884
+ || (swiftNominal == ctx.getArrayDecl () &&
885
+ isAnyObjectOrAny (typeArgs[0 ]))
886
+ || (swiftNominal == ctx.getDictionaryDecl () &&
887
+ isNSObjectOrAnyHashable (ctx, typeArgs[0 ]) &&
888
+ isAnyObjectOrAny (typeArgs[1 ]))
889
+ || (swiftNominal == ctx.getSetDecl () &&
890
+ isNSObjectOrAnyHashable (ctx, typeArgs[0 ])))) {
875
891
typeArgs = {};
876
892
}
893
+
894
+ // Use the proper upper id<NSCopying> bound for Dictionaries with
895
+ // upper-bounded keys.
896
+ else if (swiftNominal == ctx.getDictionaryDecl () &&
897
+ isNSObjectOrAnyHashable (ctx, typeArgs[0 ])) {
898
+ if (Module *M = ctx.getLoadedModule (ctx.Id_Foundation )) {
899
+ if (!NSCopyingType) {
900
+ UnqualifiedLookup lookup (ctx.getIdentifier (" NSCopying" ), M, nullptr );
901
+ auto type = lookup.getSingleTypeResult ();
902
+ if (type && isa<ProtocolDecl>(type)) {
903
+ NSCopyingType = type->getDeclaredType ();
904
+ } else {
905
+ NSCopyingType = Type ();
906
+ }
907
+ }
908
+ if (*NSCopyingType) {
909
+ rewrittenArgsBuf[0 ] = *NSCopyingType;
910
+ rewrittenArgsBuf[1 ] = typeArgs[1 ];
911
+ typeArgs = rewrittenArgsBuf;
912
+ }
913
+ }
914
+ }
877
915
878
916
// Print the class type.
879
917
SmallString<32 > objcNameScratch;
@@ -1119,12 +1157,17 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
1119
1157
// Use the type as bridged to Objective-C unless the element type is itself
1120
1158
// an imported type or a collection.
1121
1159
const StructDecl *SD = ty->getStructOrBoundGenericStruct ();
1122
- if (SD != ctx.getArrayDecl () &&
1160
+ if (ty->isAny ()) {
1161
+ ty = ctx.getProtocol (KnownProtocolKind::AnyObject)
1162
+ ->getDeclaredType ();
1163
+ } else if (SD != ctx.getArrayDecl () &&
1123
1164
SD != ctx.getDictionaryDecl () &&
1124
1165
SD != ctx.getSetDecl () &&
1125
1166
!isSwiftNewtype (SD)) {
1126
1167
ty = *ctx.getBridgedToObjC (&M, ty, /* resolver*/ nullptr );
1127
1168
}
1169
+
1170
+ assert (ty && " unknown bridged type" );
1128
1171
1129
1172
print (ty, None);
1130
1173
}
0 commit comments