@@ -1535,31 +1535,29 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
1535
1535
return getTypeMatchSuccess ();
1536
1536
}
1537
1537
1538
- // Determine whether conversion is allowed between two function types
1539
- // based on their representations.
1538
+ // / Check where a representation is a subtype of another.
1539
+ // /
1540
+ // / The subtype relationship is defined as:
1541
+ // / 1. any representation R is a sub-type of itself.
1542
+ // / 2. a thin representation is a subtype of any other representation.
1543
+ // / 3. a thick representation is a subtype of any other thick representation.
1544
+ // /
1545
+ // / For example, since `@convention(c)` is a thin representation, and
1546
+ // / `@convention(swift)` is a thick representation,
1547
+ // / `@convention(c) (A) -> B` is a sub-type of `(A) -> B`.
1548
+ // /
1549
+ // / NOTE: Unlike typical subtyping relationships, this is not anti-symmetric.
1550
+ // / For example, @convention(c) and @convention(thin) are subtypes of each other
1551
+ // / but not equal.
1540
1552
static bool
1541
- isConversionAllowedBetween (FunctionTypeRepresentation rep1,
1542
- FunctionTypeRepresentation rep2) {
1543
- auto isThin = [](FunctionTypeRepresentation rep) {
1544
- return rep == FunctionTypeRepresentation::CFunctionPointer ||
1545
- rep == FunctionTypeRepresentation::Thin;
1546
- };
1547
-
1548
- // Allowing "thin" (c, thin) to "thin" conventions
1549
- if (isThin (rep1) && isThin (rep2))
1550
- return true ;
1551
-
1552
- // Allowing all to "thick" (swift, block) conventions
1553
- // "thin" (c, thin) to "thick" or "thick" to "thick"
1554
- if (rep2 == FunctionTypeRepresentation::Swift ||
1555
- rep2 == FunctionTypeRepresentation::Block)
1556
- return true ;
1557
-
1558
- return rep1 == rep2;
1553
+ isSubtypeOf (FunctionTypeRepresentation potentialSubRepr,
1554
+ FunctionTypeRepresentation potentialSuperRepr) {
1555
+ return (potentialSubRepr == potentialSuperRepr)
1556
+ || isThinRepresentation (potentialSubRepr)
1557
+ || isThickRepresentation (potentialSuperRepr);
1559
1558
}
1560
1559
1561
- // Returns 'false' (i.e. no error) if it is legal to match functions with the
1562
- // corresponding function type representations and the given match kind.
1560
+ // / Returns true if `constraint rep1 rep2` is satisfied.
1563
1561
static bool matchFunctionRepresentations (FunctionTypeRepresentation rep1,
1564
1562
FunctionTypeRepresentation rep2,
1565
1563
ConstraintKind kind,
@@ -1569,23 +1567,37 @@ static bool matchFunctionRepresentations(FunctionTypeRepresentation rep1,
1569
1567
case ConstraintKind::BindParam:
1570
1568
case ConstraintKind::BindToPointerType:
1571
1569
case ConstraintKind::Equal:
1572
- return rep1 ! = rep2;
1570
+ return rep1 = = rep2;
1573
1571
1574
1572
case ConstraintKind::Subtype: {
1575
1573
auto last = locator.last ();
1576
1574
if (!(last && last->is <LocatorPathElt::FunctionArgument>()))
1577
- return false ;
1578
-
1579
- // Inverting the result because matchFunctionRepresentations
1580
- // returns false in conversions are allowed.
1581
- return !isConversionAllowedBetween (rep1, rep2);
1575
+ return true ;
1576
+
1577
+ return isSubtypeOf (rep1, rep2);
1582
1578
}
1583
1579
1584
- case ConstraintKind::OpaqueUnderlyingType:
1580
+
1581
+ // [NOTE: diagnose-swift-to-c-convention-change]: @convention(swift) ->
1582
+ // @convention(c) conversions are permitted only in certain cases.
1583
+ //
1584
+ // var w = 3; func f() { print(w) }; func g(_ : @convention(c) () -> ()) {}
1585
+ // g(f); // OK
1586
+ // let h = f as @convention(c) () -> (); g(h) // OK
1587
+ // let k = f; g(k) // error
1588
+ // func m() { let x = 0; g({ print(x) }) } // error
1589
+ // func n() { let y = 0; func p() { }; g(p); } // OK
1590
+ // func q() { let z = 0; func r() { print(z) }; g(r); } // error
1591
+ //
1592
+ // Since checking for disallowed cases requires access to captures,
1593
+ // it is simpler to defer diagnosing (to CSApply/SILGen) and return true here.
1585
1594
case ConstraintKind::Conversion:
1586
- case ConstraintKind::BridgingConversion:
1587
1595
case ConstraintKind::ArgumentConversion:
1588
1596
case ConstraintKind::OperatorArgumentConversion:
1597
+ return true ;
1598
+
1599
+ case ConstraintKind::OpaqueUnderlyingType:
1600
+ case ConstraintKind::BridgingConversion:
1589
1601
case ConstraintKind::ApplicableFunction:
1590
1602
case ConstraintKind::DynamicCallableApplicableFunction:
1591
1603
case ConstraintKind::BindOverload:
@@ -1609,7 +1621,7 @@ static bool matchFunctionRepresentations(FunctionTypeRepresentation rep1,
1609
1621
case ConstraintKind::OneWayEqual:
1610
1622
case ConstraintKind::OneWayBindParam:
1611
1623
case ConstraintKind::DefaultClosureType:
1612
- return false ;
1624
+ return true ;
1613
1625
}
1614
1626
1615
1627
llvm_unreachable (" Unhandled ConstraintKind in switch." );
@@ -1902,9 +1914,9 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
1902
1914
return getTypeMatchFailure (locator);
1903
1915
}
1904
1916
1905
- if (matchFunctionRepresentations (func1->getExtInfo ().getRepresentation (),
1906
- func2->getExtInfo ().getRepresentation (),
1907
- kind, locator)) {
1917
+ if (! matchFunctionRepresentations (func1->getExtInfo ().getRepresentation (),
1918
+ func2->getExtInfo ().getRepresentation (),
1919
+ kind, locator)) {
1908
1920
return getTypeMatchFailure (locator);
1909
1921
}
1910
1922
0 commit comments