@@ -1565,6 +1565,39 @@ swift::swift_getFunctionTypeMetadataGlobalActor(
15651565 return &FunctionTypes.getOrInsert (key).first ->Data ;
15661566}
15671567
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+
15681601const FunctionTypeMetadata *
15691602swift::swift_getExtendedFunctionTypeMetadata (
15701603 FunctionTypeFlags flags, FunctionMetadataDifferentiabilityKind diffKind,
@@ -1573,6 +1606,31 @@ swift::swift_getExtendedFunctionTypeMetadata(
15731606 ExtendedFunctionTypeFlags extFlags, const Metadata *thrownError) {
15741607 assert (flags.hasExtendedFlags () || extFlags.getIntValue () == 0 );
15751608 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+
15761634 FunctionCacheEntry::Key key = {
15771635 flags, diffKind, parameters,
15781636 reinterpret_cast <const ParameterFlags *>(parameterFlags), result,
0 commit comments