@@ -1565,6 +1565,39 @@ swift::swift_getFunctionTypeMetadataGlobalActor(
1565
1565
return &FunctionTypes.getOrInsert (key).first ->Data ;
1566
1566
}
1567
1567
1568
+ extern " C" const EnumDescriptor NOMINAL_TYPE_DESCR_SYM (s5NeverO);
1569
+ extern " C" const ProtocolDescriptor PROTOCOL_DESCR_SYM (s5Error);
1570
+
1571
+ namespace {
1572
+ // / Classification for a given thrown error type.
1573
+ enum class ThrownErrorClassification {
1574
+ // / An arbitrary thrown error.
1575
+ Arbitrary,
1576
+ // / 'Never', which means a function type is non-throwing.
1577
+ Never,
1578
+ // / 'any Error', which means the function type uses untyped throws.
1579
+ AnyError,
1580
+ };
1581
+
1582
+ // / Classify a thrown error type.
1583
+ ThrownErrorClassification classifyThrownError (const Metadata *type) {
1584
+ if (auto enumMetadata = dyn_cast<EnumMetadata>(type)) {
1585
+ if (enumMetadata->getDescription () == &NOMINAL_TYPE_DESCR_SYM (s5NeverO))
1586
+ return ThrownErrorClassification::Never;
1587
+ } else if (auto existential = dyn_cast<ExistentialTypeMetadata>(type)) {
1588
+ auto protocols = existential->getProtocols ();
1589
+ if (protocols.size () == 1 &&
1590
+ !protocols[0 ].isObjC () &&
1591
+ protocols[0 ].getSwiftProtocol () == &PROTOCOL_DESCR_SYM (s5Error) &&
1592
+ !existential->isClassBounded () &&
1593
+ !existential->isObjC ())
1594
+ return ThrownErrorClassification::AnyError;
1595
+ }
1596
+
1597
+ return ThrownErrorClassification::Arbitrary;
1598
+ }
1599
+ }
1600
+
1568
1601
const FunctionTypeMetadata *
1569
1602
swift::swift_getExtendedFunctionTypeMetadata (
1570
1603
FunctionTypeFlags flags, FunctionMetadataDifferentiabilityKind diffKind,
@@ -1573,6 +1606,31 @@ swift::swift_getExtendedFunctionTypeMetadata(
1573
1606
ExtendedFunctionTypeFlags extFlags, const Metadata *thrownError) {
1574
1607
assert (flags.hasExtendedFlags () || extFlags.getIntValue () == 0 );
1575
1608
assert (flags.hasExtendedFlags () || thrownError == nullptr );
1609
+
1610
+ if (thrownError) {
1611
+ // Perform adjustments based on the given thrown error.
1612
+ switch (classifyThrownError (thrownError)){
1613
+ case ThrownErrorClassification::Arbitrary:
1614
+ // Nothing to do.
1615
+ break ;
1616
+
1617
+ case ThrownErrorClassification::Never:
1618
+ // The thrown error was 'Never', so make this a non-throwing function
1619
+ flags = flags.withThrows (false );
1620
+
1621
+ // Fall through to clear out the error.
1622
+ SWIFT_FALLTHROUGH;
1623
+
1624
+ case ThrownErrorClassification::AnyError:
1625
+ // Clear out the thrown error and extended flags.
1626
+ thrownError = nullptr ;
1627
+ extFlags = extFlags.withTypedThrows (false );
1628
+ if (extFlags.getIntValue () == 0 )
1629
+ flags = flags.withExtendedFlags (false );
1630
+ break ;
1631
+ }
1632
+ }
1633
+
1576
1634
FunctionCacheEntry::Key key = {
1577
1635
flags, diffKind, parameters,
1578
1636
reinterpret_cast <const ParameterFlags *>(parameterFlags), result,
0 commit comments