@@ -1535,31 +1535,29 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
15351535 return getTypeMatchSuccess ();
15361536}
15371537
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.
15401552static 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);
15591558}
15601559
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.
15631561static bool matchFunctionRepresentations (FunctionTypeRepresentation rep1,
15641562 FunctionTypeRepresentation rep2,
15651563 ConstraintKind kind,
@@ -1569,23 +1567,37 @@ static bool matchFunctionRepresentations(FunctionTypeRepresentation rep1,
15691567 case ConstraintKind::BindParam:
15701568 case ConstraintKind::BindToPointerType:
15711569 case ConstraintKind::Equal:
1572- return rep1 ! = rep2;
1570+ return rep1 = = rep2;
15731571
15741572 case ConstraintKind::Subtype: {
15751573 auto last = locator.last ();
15761574 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);
15821578 }
15831579
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.
15851594 case ConstraintKind::Conversion:
1586- case ConstraintKind::BridgingConversion:
15871595 case ConstraintKind::ArgumentConversion:
15881596 case ConstraintKind::OperatorArgumentConversion:
1597+ return true ;
1598+
1599+ case ConstraintKind::OpaqueUnderlyingType:
1600+ case ConstraintKind::BridgingConversion:
15891601 case ConstraintKind::ApplicableFunction:
15901602 case ConstraintKind::DynamicCallableApplicableFunction:
15911603 case ConstraintKind::BindOverload:
@@ -1609,7 +1621,7 @@ static bool matchFunctionRepresentations(FunctionTypeRepresentation rep1,
16091621 case ConstraintKind::OneWayEqual:
16101622 case ConstraintKind::OneWayBindParam:
16111623 case ConstraintKind::DefaultClosureType:
1612- return false ;
1624+ return true ;
16131625 }
16141626
16151627 llvm_unreachable (" Unhandled ConstraintKind in switch." );
@@ -1902,9 +1914,9 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
19021914 return getTypeMatchFailure (locator);
19031915 }
19041916
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)) {
19081920 return getTypeMatchFailure (locator);
19091921 }
19101922
0 commit comments