@@ -1557,19 +1557,38 @@ isSubtypeOf(FunctionTypeRepresentation potentialSubRepr,
15571557 || isThickRepresentation (potentialSuperRepr);
15581558}
15591559
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 ()));
15641570 switch (kind) {
15651571 case ConstraintKind::Bind:
15661572 case ConstraintKind::BindParam:
15671573 case ConstraintKind::BindToPointerType:
15681574 case ConstraintKind::Equal:
1569- return rep1 == rep2;
1570-
1575+ return ( rep1 == rep2) && !clangTypeMismatch ;
1576+
15711577 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);
15731592 }
15741593
15751594 // [NOTE: diagnose-swift-to-c-convention-change]: @convention(swift) ->
@@ -1588,6 +1607,19 @@ static bool matchFunctionRepresentations(FunctionTypeRepresentation rep1,
15881607 case ConstraintKind::Conversion:
15891608 case ConstraintKind::ArgumentConversion:
15901609 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+ }
15911623 return true ;
15921624
15931625 case ConstraintKind::OpaqueUnderlyingType:
@@ -1908,9 +1940,8 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
19081940 return getTypeMatchFailure (locator);
19091941 }
19101942
1911- if (!matchFunctionRepresentations (func1->getExtInfo ().getRepresentation (),
1912- func2->getExtInfo ().getRepresentation (),
1913- kind)) {
1943+ if (!matchFunctionRepresentations (func1->getExtInfo (), func2->getExtInfo (),
1944+ kind, Options)) {
19141945 return getTypeMatchFailure (locator);
19151946 }
19161947
0 commit comments