@@ -1557,19 +1557,38 @@ isSubtypeOf(FunctionTypeRepresentation potentialSubRepr,
1557
1557
|| isThickRepresentation (potentialSuperRepr);
1558
1558
}
1559
1559
1560
- // / Returns true if `constraint rep1 rep2` is satisfied.
1561
- static bool matchFunctionRepresentations (FunctionTypeRepresentation rep1,
1562
- FunctionTypeRepresentation rep2,
1563
- ConstraintKind kind) {
1560
+ // / Returns true if `constraint extInfo1 extInfo2` is satisfied.
1561
+ static bool matchFunctionRepresentations (FunctionType::ExtInfo einfo1,
1562
+ FunctionType::ExtInfo einfo2,
1563
+ ConstraintKind kind,
1564
+ ConstraintSystemOptions options) {
1565
+ auto rep1 = einfo1.getRepresentation ();
1566
+ auto rep2 = einfo2.getRepresentation ();
1567
+ bool clangTypeMismatch =
1568
+ (options.contains (ConstraintSystemFlags::UseClangFunctionTypes) &&
1569
+ (einfo1.getClangTypeInfo () != einfo2.getClangTypeInfo ()));
1564
1570
switch (kind) {
1565
1571
case ConstraintKind::Bind:
1566
1572
case ConstraintKind::BindParam:
1567
1573
case ConstraintKind::BindToPointerType:
1568
1574
case ConstraintKind::Equal:
1569
- return rep1 == rep2;
1570
-
1575
+ return ( rep1 == rep2) && !clangTypeMismatch ;
1576
+
1571
1577
case ConstraintKind::Subtype: {
1572
- return isSubtypeOf (rep1, rep2);
1578
+ // Breakdown of cases:
1579
+ // 1. isSubtypeOf(rep1, rep2) == false (hence rep1 != rep2):
1580
+ // In this case, this function will return false, indicating that we
1581
+ // can't convert. E.g. you can't convert from @convention(swift) to
1582
+ // @convention(c).
1583
+ // 2. isSubtypeOf(rep1, rep2) == true and rep1 != rep2:
1584
+ // In this case, this function will return true, indicating that we
1585
+ // can convert, because the Clang type doesn't matter when converting
1586
+ // between different representations. E.g. it is okay to convert from
1587
+ // @convention(c) (regardless of cType) to @convention(swift).
1588
+ // 3. isSubtypeOf(rep1, rep2) == true and rep1 == rep2:
1589
+ // In this case, the function returns !clangTypeMismatch, as we forbid
1590
+ // conversions between @convention(c) functions with different cTypes.
1591
+ return isSubtypeOf (rep1, rep2) && ((rep1 != rep2) || !clangTypeMismatch);
1573
1592
}
1574
1593
1575
1594
// [NOTE: diagnose-swift-to-c-convention-change]: @convention(swift) ->
@@ -1588,6 +1607,19 @@ static bool matchFunctionRepresentations(FunctionTypeRepresentation rep1,
1588
1607
case ConstraintKind::Conversion:
1589
1608
case ConstraintKind::ArgumentConversion:
1590
1609
case ConstraintKind::OperatorArgumentConversion:
1610
+ // For now, forbid conversion if representations match but cTypes differ.
1611
+ //
1612
+ // let f : @convention(c, cType: "id (*)(void) __attribute__((ns_returns_retained))")
1613
+ // () -> AnyObject = ...
1614
+ // let _ : @convention(c, cType: "id (*)(void)")
1615
+ // () -> AnyObject = f // error
1616
+ // let g : @convention(c, cType: "void (*)(void *)")
1617
+ // (OpaquePointer?) -> () = ...
1618
+ // let _ : @convention(c, cType: "void (*)(MyCtx *)")
1619
+ // (OpaquePointer?) -> () = g // error
1620
+ if ((rep1 == rep2) && clangTypeMismatch) {
1621
+ return false ;
1622
+ }
1591
1623
return true ;
1592
1624
1593
1625
case ConstraintKind::OpaqueUnderlyingType:
@@ -1908,9 +1940,8 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
1908
1940
return getTypeMatchFailure (locator);
1909
1941
}
1910
1942
1911
- if (!matchFunctionRepresentations (func1->getExtInfo ().getRepresentation (),
1912
- func2->getExtInfo ().getRepresentation (),
1913
- kind)) {
1943
+ if (!matchFunctionRepresentations (func1->getExtInfo (), func2->getExtInfo (),
1944
+ kind, Options)) {
1914
1945
return getTypeMatchFailure (locator);
1915
1946
}
1916
1947
0 commit comments