Skip to content

Commit 9e7a670

Browse files
committed
[ConstraintSystem] Implement new Swift -> C pointer conversions
Allow following conversions in argument positions (applies only to call to imported C/ObjC declarations): - Unsafe[Mutable]RawPointer -> Unsafe[Mutable]Pointer<[U]Int> - Unsafe[Mutable]Pointer<Int{8, 16, ...}> <-> Unsafe[Mutable]Pointer<UInt{8, 16, ...}>
1 parent 4f97ef0 commit 9e7a670

File tree

2 files changed

+109
-2
lines changed

2 files changed

+109
-2
lines changed

include/swift/Sema/Constraint.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ enum class ConversionRestrictionKind {
271271
CGFloatToDouble,
272272
/// Implicit conversion between Swift and C pointers:
273273
// - Unsafe[Mutable]RawPointer -> Unsafe[Mutable]Pointer<[U]Int>
274-
// - Unsafe[Mutable]Pointer<Int{8, 16, ...}> -> Unsafe[Mutable]Pointer<UInt{8, 16, ...}>
274+
// - Unsafe[Mutable]Pointer<Int{8, 16, ...}> <-> Unsafe[Mutable]Pointer<UInt{8, 16, ...}>
275275
PointerToCPointer,
276276
};
277277

lib/Sema/CSSimplify.cpp

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5888,6 +5888,43 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
58885888
ConversionRestrictionKind::PointerToPointer);
58895889
}
58905890
}
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+
}
58915928
}
58925929
break;
58935930

@@ -11116,7 +11153,77 @@ ConstraintSystem::simplifyRestrictedConstraintImpl(
1111611153
}
1111711154

1111811155
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;
1112011227
}
1112111228

1112211229
// T < U or T is bridged to V where V < U ===> Array<T> <c Array<U>

0 commit comments

Comments
 (0)