@@ -5888,6 +5888,43 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
5888
5888
ConversionRestrictionKind::PointerToPointer);
5889
5889
}
5890
5890
}
5891
+
5892
+ // If both sides are non-optional pointers let's check whether
5893
+ // this argument supports Swift -> C pointer conversions.
5894
+ //
5895
+ // Do some light verification before recording restriction to
5896
+ // avoid allocating constraints for obviously invalid cases.
5897
+ if (type1IsPointer && !type1IsOptional && !type2IsOptional &&
5898
+ isArgumentOfImportedDecl (locator)) {
5899
+ // UnsafeRawPointer -> UnsafePointer<[U]Int8>
5900
+ if (type1PointerKind == PTK_UnsafeRawPointer &&
5901
+ pointerKind == PTK_UnsafePointer) {
5902
+ conversionsOrFixes.push_back (
5903
+ ConversionRestrictionKind::PointerToCPointer);
5904
+ }
5905
+
5906
+ // UnsafeMutableRawPointer -> Unsafe[Mutable]Pointer<[U]Int8>
5907
+ if (type1PointerKind == PTK_UnsafeMutableRawPointer &&
5908
+ (pointerKind == PTK_UnsafePointer ||
5909
+ pointerKind == PTK_UnsafeMutablePointer)) {
5910
+ conversionsOrFixes.push_back (
5911
+ ConversionRestrictionKind::PointerToCPointer);
5912
+ }
5913
+
5914
+ // Unsafe[Mutable]Pointer -> Unsafe[Mutable]Pointer
5915
+ if (type1PointerKind == PTK_UnsafePointer &&
5916
+ pointerKind == PTK_UnsafePointer) {
5917
+ conversionsOrFixes.push_back (
5918
+ ConversionRestrictionKind::PointerToCPointer);
5919
+ }
5920
+
5921
+ if (type1PointerKind == PTK_UnsafeMutablePointer &&
5922
+ (pointerKind == PTK_UnsafePointer ||
5923
+ pointerKind == PTK_UnsafeMutablePointer)) {
5924
+ conversionsOrFixes.push_back (
5925
+ ConversionRestrictionKind::PointerToCPointer);
5926
+ }
5927
+ }
5891
5928
}
5892
5929
break ;
5893
5930
@@ -11116,7 +11153,77 @@ ConstraintSystem::simplifyRestrictedConstraintImpl(
11116
11153
}
11117
11154
11118
11155
case ConversionRestrictionKind::PointerToCPointer: {
11119
- return SolutionKind::Error; // not yet implemented
11156
+ auto &ctx = getASTContext ();
11157
+
11158
+ PointerTypeKind swiftPtrKind, cPtrKind;
11159
+
11160
+ auto swiftPtr = type1->getAnyPointerElementType (swiftPtrKind);
11161
+ auto cPtr = type2->getAnyPointerElementType (cPtrKind);
11162
+
11163
+ // Unsafe[Mutable]RawPointer -> Unsafe[Mutable]Pointer<[U]Int8>
11164
+ if (swiftPtrKind == PTK_UnsafeRawPointer ||
11165
+ swiftPtrKind == PTK_UnsafeMutableRawPointer) {
11166
+ // Since it's a C pointer on parameter side it would always
11167
+ // be fully resolved.
11168
+ if (cPtr->isInt8 () || cPtr->isUInt8 ())
11169
+ return SolutionKind::Solved;
11170
+ } else {
11171
+ // Unsafe[Mutable]Pointer<T> -> Unsafe[Mutable]Pointer<[U]Int8>
11172
+ if (cPtr->isInt8 () || cPtr->isUInt8 ()) {
11173
+ // <T> can default to the type of C pointer.
11174
+ addConstraint (
11175
+ ConstraintKind::Defaultable, swiftPtr, cPtr,
11176
+ locator.withPathElement (LocatorPathElt::GenericArgument (0 )));
11177
+ return SolutionKind::Solved;
11178
+ }
11179
+
11180
+ auto elementLoc =
11181
+ locator.withPathElement (LocatorPathElt::GenericArgument (0 ));
11182
+
11183
+ // Unsafe[Mutable]Pointer<Int{8, 16, ...}> <->
11184
+ // Unsafe[Mutable]Pointer<UInt{8, 16, ...}>
11185
+
11186
+ if (swiftPtr->isInt () || swiftPtr->isUInt ()) {
11187
+ addConstraint (ConstraintKind::Equal, cPtr,
11188
+ swiftPtr->isUInt () ? ctx.getIntType () : ctx.getUIntType (),
11189
+ elementLoc);
11190
+ return SolutionKind::Solved;
11191
+ }
11192
+
11193
+ if (swiftPtr->isInt8 () || swiftPtr->isUInt8 ()) {
11194
+ addConstraint (ConstraintKind::Equal, cPtr,
11195
+ swiftPtr->isUInt8 () ? ctx.getInt8Type ()
11196
+ : ctx.getUInt8Type (),
11197
+ elementLoc);
11198
+ return SolutionKind::Solved;
11199
+ }
11200
+
11201
+ if (swiftPtr->isInt16 () || swiftPtr->isUInt16 ()) {
11202
+ addConstraint (ConstraintKind::Equal, cPtr,
11203
+ swiftPtr->isUInt16 () ? ctx.getInt16Type ()
11204
+ : ctx.getUInt16Type (),
11205
+ elementLoc);
11206
+ return SolutionKind::Solved;
11207
+ }
11208
+
11209
+ if (swiftPtr->isInt32 () || swiftPtr->isUInt32 ()) {
11210
+ addConstraint (ConstraintKind::Equal, cPtr,
11211
+ swiftPtr->isUInt32 () ? ctx.getInt32Type ()
11212
+ : ctx.getUInt32Type (),
11213
+ elementLoc);
11214
+ return SolutionKind::Solved;
11215
+ }
11216
+
11217
+ if (swiftPtr->isInt64 () || swiftPtr->isUInt64 ()) {
11218
+ addConstraint (ConstraintKind::Equal, cPtr,
11219
+ swiftPtr->isUInt64 () ? ctx.getInt64Type ()
11220
+ : ctx.getUInt64Type (),
11221
+ elementLoc);
11222
+ return SolutionKind::Solved;
11223
+ }
11224
+ }
11225
+
11226
+ return SolutionKind::Error;
11120
11227
}
11121
11228
11122
11229
// T < U or T is bridged to V where V < U ===> Array<T> <c Array<U>
0 commit comments