@@ -63,17 +63,9 @@ namespace {
63
63
// / The source type is 'Boolean'.
64
64
Boolean,
65
65
66
- // / The source type is 'NSString'.
67
- NSString,
68
-
69
- // / The source type is 'NSArray'.
70
- NSArray,
71
-
72
- // / The source type is 'NSDictionary'.
73
- NSDictionary,
74
-
75
- // / The source type is 'NSSet'.
76
- NSSet,
66
+ // / The source type an Objective-C class type bridged to a Swift
67
+ // / type.
68
+ ObjCBridged,
77
69
78
70
// / The source type is 'NSUInteger'.
79
71
NSUInteger,
@@ -100,52 +92,21 @@ namespace {
100
92
101
93
ImportHintKind Kind;
102
94
103
- // Type arguments, if provided .
104
- Type TypeArgs[ 2 ] ;
95
+ // / The type to which the imported type is bridged .
96
+ Type BridgedType ;
105
97
106
98
// / Allow conversion from an import hint to an import hint kind,
107
99
// / which is useful for switches and comparisons.
108
100
operator ImportHintKind () const { return Kind; }
109
101
110
- // / Determine the number of type arguments we expect.
111
- static unsigned getNumTypeArgs (ImportHintKind kind) {
112
- switch (kind) {
113
- case None:
114
- case Void:
115
- case BOOL:
116
- case Boolean:
117
- case NSString:
118
- case NSUInteger:
119
- case ObjCPointer:
120
- case CFPointer:
121
- case Reference:
122
- case Block:
123
- case CFunctionPointer:
124
- case CustomNullablePointer:
125
- return 0 ;
126
-
127
- case NSArray:
128
- case NSSet:
129
- return 1 ;
130
-
131
- case NSDictionary:
132
- return 2 ;
133
- }
134
- }
135
-
136
102
ImportHint (ImportHintKind kind) : Kind(kind) {
137
- assert (getNumTypeArgs (kind) == 0 && " Wrong number of arguments" );
103
+ assert (kind != ObjCBridged &&
104
+ " Bridged entry point requires a bridged type" );
138
105
}
139
106
140
- ImportHint (ImportHintKind kind, Type typeArg1) : Kind(kind) {
141
- assert (getNumTypeArgs (kind) == 1 && " Wrong number of arguments" );
142
- TypeArgs[0 ] = typeArg1;
143
- }
144
-
145
- ImportHint (ImportHintKind kind, Type typeArg1, Type typeArg2) : Kind(kind) {
146
- assert (getNumTypeArgs (kind) == 2 && " Wrong number of arguments" );
147
- TypeArgs[0 ] = typeArg1;
148
- TypeArgs[1 ] = typeArg2;
107
+ ImportHint (ImportHintKind kind, Type bridgedType)
108
+ : Kind(kind), BridgedType(bridgedType) {
109
+ assert (kind == ImportHint::ObjCBridged && " Wrong kind for bridged type" );
149
110
}
150
111
};
151
112
@@ -162,10 +123,7 @@ namespace {
162
123
163
124
case ImportHint::Block:
164
125
case ImportHint::CFPointer:
165
- case ImportHint::NSArray:
166
- case ImportHint::NSDictionary:
167
- case ImportHint::NSSet:
168
- case ImportHint::NSString:
126
+ case ImportHint::ObjCBridged:
169
127
case ImportHint::ObjCPointer:
170
128
case ImportHint::CFunctionPointer:
171
129
case ImportHint::CustomNullablePointer:
@@ -724,76 +682,91 @@ namespace {
724
682
}
725
683
}
726
684
727
- if (imported->hasName () &&
728
- imported->getName ()
729
- == Impl.SwiftContext .getSwiftId (KnownFoundationEntity::NSString)){
730
- return { importedType, ImportHint::NSString };
731
- }
732
-
733
- if (imported->hasName () &&
734
- imported->getName ()
735
- == Impl.SwiftContext .getSwiftId (KnownFoundationEntity::NSArray)) {
736
- // If we have type arguments, import them.
685
+ // Determine whether this Objective-C class type is bridged to
686
+ // a Swift type.
687
+ NominalTypeDecl *bridgedTypeDecl = nullptr ;
688
+ StringRef objcClassName = objcClass->getName ();
689
+ if (objcClassName == " NSString" )
690
+ bridgedTypeDecl = Impl.SwiftContext .getStringDecl ();
691
+ else if (objcClassName == " NSArray" )
692
+ bridgedTypeDecl = Impl.SwiftContext .getArrayDecl ();
693
+ else if (objcClassName == " NSDictionary" )
694
+ bridgedTypeDecl = Impl.SwiftContext .getDictionaryDecl ();
695
+ else if (objcClassName == " NSSet" )
696
+ bridgedTypeDecl = Impl.SwiftContext .getSetDecl ();
697
+
698
+ Type bridgedType;
699
+ if (bridgedTypeDecl)
700
+ bridgedType = bridgedTypeDecl->getDeclaredType ();
701
+
702
+ if (bridgedType) {
703
+ // Gather the type arguments.
704
+ SmallVector<Type, 2 > importedTypeArgs;
737
705
ArrayRef<clang::QualType> typeArgs = type->getTypeArgs ();
738
- if (typeArgs.size () == 1 ) {
739
- Type elementType = Impl.importType (typeArgs[0 ],
740
- ImportTypeKind::BridgedValue,
741
- AllowNSUIntegerAsInt,
742
- CanFullyBridgeTypes,
743
- OTK_None);
744
- return { importedType,
745
- ImportHint (ImportHint::NSArray, elementType) };
706
+ SmallVector<clang::QualType, 2 > typeArgsScratch;
707
+
708
+ // If we have an unspecialized form of a parameterized
709
+ // Objective-C class type, fill in the defaults.
710
+ if (typeArgs.empty ()) {
711
+ if (auto objcGenericParams = objcClass->getTypeParamList ()) {
712
+ objcGenericParams->gatherDefaultTypeArgs (typeArgsScratch);
713
+ typeArgs = typeArgsScratch;
714
+ }
746
715
}
747
716
748
- return { importedType, ImportHint (ImportHint::NSArray, Type ()) };
749
- }
750
-
751
- if (imported->hasName () &&
752
- imported->getName ()
753
- == Impl.SwiftContext .getSwiftId (
754
- KnownFoundationEntity::NSDictionary)) {
755
- // If we have type arguments, import them.
756
- ArrayRef<clang::QualType> typeArgs = type->getTypeArgs ();
757
- if (typeArgs.size () == 2 ) {
758
- Type keyType = Impl.importType (typeArgs[0 ],
759
- ImportTypeKind::BridgedValue,
760
- AllowNSUIntegerAsInt,
761
- CanFullyBridgeTypes,
762
- OTK_None);
763
- Type objectType = Impl.importType (typeArgs[1 ],
764
- ImportTypeKind::BridgedValue,
765
- AllowNSUIntegerAsInt,
766
- CanFullyBridgeTypes,
767
- OTK_None);
768
- if (keyType.isNull () != objectType.isNull ()) {
769
- keyType = nullptr ;
770
- objectType = nullptr ;
717
+ // Convert the type arguments.
718
+ for (auto typeArg : typeArgs) {
719
+ Type importedTypeArg = Impl.importType (typeArg,
720
+ ImportTypeKind::BridgedValue,
721
+ AllowNSUIntegerAsInt,
722
+ CanFullyBridgeTypes,
723
+ OTK_None);
724
+ if (!importedTypeArg) {
725
+ importedTypeArgs.clear ();
726
+ break ;
771
727
}
772
728
773
- return { importedType,
774
- ImportHint (ImportHint::NSDictionary,
775
- keyType, objectType) };
729
+ importedTypeArgs.push_back (importedTypeArg);
776
730
}
777
- return { importedType,
778
- ImportHint (ImportHint::NSDictionary, Type (), Type ()) };
779
- }
780
731
781
- if (imported->hasName () &&
782
- imported->getName ()
783
- == Impl.SwiftContext .getSwiftId (KnownFoundationEntity::NSSet)) {
784
- // If we have type arguments, import them.
785
- ArrayRef<clang::QualType> typeArgs = type->getTypeArgs ();
786
- if (typeArgs.size () == 1 ) {
787
- Type elementType = Impl.importType (typeArgs[0 ],
788
- ImportTypeKind::BridgedValue,
789
- AllowNSUIntegerAsInt,
790
- CanFullyBridgeTypes,
791
- OTK_None);
792
- return { importedType,
793
- ImportHint (ImportHint::NSSet, elementType) };
732
+ // If we have an unbound generic bridged type, get the arguments.
733
+ if (auto unboundType = bridgedType->getAs <UnboundGenericType>()) {
734
+ auto unboundDecl = unboundType->getDecl ();
735
+ auto bridgedSig = unboundDecl->getGenericSignature ();
736
+ assert (bridgedSig && " Bridged signature" );
737
+ unsigned numExpectedTypeArgs = bridgedSig->getGenericParams ().size ();
738
+ if (importedTypeArgs.size () != numExpectedTypeArgs)
739
+ return Type ();
740
+
741
+ // The first type argument for Dictionary or Set needs
742
+ // to be NSObject-bound.
743
+ if (unboundDecl == Impl.SwiftContext .getDictionaryDecl () ||
744
+ unboundDecl == Impl.SwiftContext .getSetDecl ()) {
745
+ auto &keyType = importedTypeArgs[0 ];
746
+ if (!Impl.matchesNSObjectBound (keyType))
747
+ keyType = Impl.getNSObjectType ();
748
+ }
749
+
750
+ // Form the specialized type.
751
+ if (unboundDecl == Impl.SwiftContext .getArrayDecl ()) {
752
+ // Type sugar for arrays.
753
+ assert (importedTypeArgs.size () == 1 );
754
+ bridgedType = ArraySliceType::get (importedTypeArgs[0 ]);
755
+ } else if (unboundDecl == Impl.SwiftContext .getDictionaryDecl ()) {
756
+ // Type sugar for dictionaries.
757
+ assert (importedTypeArgs.size () == 2 );
758
+ bridgedType = DictionaryType::get (importedTypeArgs[0 ],
759
+ importedTypeArgs[1 ]);
760
+ } else {
761
+ // Everything else.
762
+ bridgedType =
763
+ BoundGenericType::get (cast<NominalTypeDecl>(unboundDecl),
764
+ Type (), importedTypeArgs);
765
+ }
794
766
}
795
767
796
- return { importedType, ImportHint (ImportHint::NSSet, Type ()) };
768
+ return { importedType,
769
+ ImportHint (ImportHint::ObjCBridged, bridgedType) };
797
770
}
798
771
799
772
return { importedType, ImportHint::ObjCPointer };
@@ -898,6 +871,19 @@ static Type getUnmanagedType(ClangImporter::Implementation &impl,
898
871
return unmanagedClassType;
899
872
}
900
873
874
+ // / Determine whether type is 'NSString.
875
+ static bool isNSString (Type type) {
876
+ if (auto classType = type->getAs <ClassType>()) {
877
+ if (auto clangDecl = classType->getDecl ()->getClangDecl ()) {
878
+ if (auto objcClass = dyn_cast<clang::ObjCInterfaceDecl>(clangDecl)) {
879
+ return objcClass->getName () == " NSString" ;
880
+ }
881
+ }
882
+ }
883
+
884
+ return false ;
885
+ }
886
+
901
887
static Type adjustTypeForConcreteImport (ClangImporter::Implementation &impl,
902
888
clang::QualType clangType,
903
889
Type importedType,
@@ -919,10 +905,10 @@ static Type adjustTypeForConcreteImport(ClangImporter::Implementation &impl,
919
905
}
920
906
921
907
// Import NSString * globals as String.
922
- if (hint == ImportHint::NSString &&
908
+ if (hint == ImportHint::ObjCBridged && isNSString (importedType) &&
923
909
(importKind == ImportTypeKind::Variable ||
924
910
importKind == ImportTypeKind::AuditedVariable)) {
925
- return impl. getNamedSwiftType (impl. getStdlibModule (), " String " ) ;
911
+ return hint. BridgedType ;
926
912
}
927
913
928
914
// Reference types are only permitted as function parameter types.
@@ -1079,63 +1065,11 @@ static Type adjustTypeForConcreteImport(ClangImporter::Implementation &impl,
1079
1065
importedType = getUnmanagedType (impl, importedType);
1080
1066
}
1081
1067
1082
- // When NSString* is the type of a function parameter or a function
1083
- // result type, map it to String.
1084
- // FIXME: It's not really safe to do this when Foundation is missing.
1085
- // We do it anyway for ImportForwardDeclarations mode so that generated
1086
- // interfaces are correct, but trying to use the resulting declarations
1087
- // may result in compiler crashes further down the line.
1088
- if (hint == ImportHint::NSString && canBridgeTypes (importKind) &&
1089
- (impl.tryLoadFoundationModule () || impl.ImportForwardDeclarations )) {
1090
- importedType = impl.SwiftContext .getStringDecl ()->getDeclaredType ();
1091
- }
1092
-
1093
-
1094
- // When NSArray* is the type of a function parameter or a function
1095
- // result type, map it to [AnyObject].
1096
- if (hint == ImportHint::NSArray && canBridgeTypes (importKind) &&
1097
- impl.tryLoadFoundationModule ()) {
1098
- Type elementType = hint.TypeArgs [0 ];
1099
- if (elementType.isNull ())
1100
- elementType = impl.getNamedSwiftType (impl.getStdlibModule (), " AnyObject" );
1101
- importedType = ArraySliceType::get (elementType);
1102
- }
1103
-
1104
- // When NSDictionary* is the type of a function parameter or a function
1105
- // result type, map it to [K : V].
1106
- if (hint == ImportHint::NSDictionary && canBridgeTypes (importKind) &&
1107
- impl.tryLoadFoundationModule ()) {
1108
- Type keyType = hint.TypeArgs [0 ];
1109
- Type objectType = hint.TypeArgs [1 ];
1110
-
1111
- // If no key type was provided, or the key doesn't match the 'NSObject'
1112
- // bound required by the Swift Dictionary key, substitute in 'NSObject'.
1113
- if (keyType.isNull () || !impl.matchesNSObjectBound (keyType)) {
1114
- keyType = impl.getNSObjectType ();
1115
- }
1116
-
1117
- if (objectType.isNull ()) {
1118
- objectType = impl.getNamedSwiftType (impl.getStdlibModule (), " AnyObject" );
1119
- }
1120
-
1121
- importedType = DictionaryType::get (keyType, objectType);
1122
- }
1123
-
1124
- // When NSSet* is the type of a function parameter or a function
1125
- // result type, map it to Set<T>.
1126
- if (hint == ImportHint::NSSet && canBridgeTypes (importKind) &&
1127
- impl.tryLoadFoundationModule ()) {
1128
- Type elementType = hint.TypeArgs [0 ];
1129
-
1130
- // If no element type was provided, or the element type doesn't match the
1131
- // 'NSObject' bound required by the Swift Set, substitute in 'NSObject'.
1132
- if (elementType.isNull () || !impl.matchesNSObjectBound (elementType))
1133
- elementType = impl.getNSObjectType ();
1134
-
1135
- importedType = impl.getNamedSwiftTypeSpecialization (impl.getStdlibModule (),
1136
- " Set" ,
1137
- elementType);
1138
- }
1068
+ // If we have a bridged Objective-C type and we are allowed to
1069
+ // bridge, do so.
1070
+ if (hint == ImportHint::ObjCBridged && canBridgeTypes (importKind) &&
1071
+ (impl.tryLoadFoundationModule () || impl.ImportForwardDeclarations ))
1072
+ importedType = hint.BridgedType ;
1139
1073
1140
1074
if (!importedType)
1141
1075
return importedType;
0 commit comments