mirror of
https://github.com/apple/swift.git
synced 2026-09-28 10:03:29 +02:00
A `try_apply` whose callee's error result is uninhabited can never take
its error branch. Turn it into `apply [nothrow]` and let the dead-block
cleanup remove the error block.
This mostly shows up in Embedded Swift, which specializes generics at
-Onone: a `rethrows`-shaped `throws(E)` function specialized for `E ==
Never` keeps the rethrow, and IRGen has to emit that as an unconditional
trap ("Never can't be initialized") reached by an equally dead test of
the error register. Calling `withTemporaryAllocation` or `Optional.map`
was enough to get one per call site.
Enums which are resilient from the caller's point of view are excluded,
since a case-less non-frozen enum can gain cases in a future version of
its module.
`TryApplyInst` is both `OnoneSimplifiable` (so
`MandatoryPerformanceOptimizations` gets it, i.e. Embedded `-Onone`) and
`SILCombineSimplifiable` (so `-O` gets it without depending on the
inliner).
The predicate is `FunctionConvention.hasUninhabitedErrorResult(in:)`,
written in Swift over low-level bridges
(`TypeProperties.isStructurallyUninhabited`,
`EnumDecl.hasCasesUnavailableDuringLowering`,
`EnumDecl.isEffectivelyExhaustive`). `ResultInfo.getReturnValueType` now
takes the function type the result belongs to; it used to hardcode the
enclosing function's lowered type, which is wrong for a result of an
apply site's substituted callee type (it had no prior callers).
Two existing tests change behaviour because their error enums are
genuinely case-less: closure_lifetime_fixup's `Optional.map<_, Never,
_>` call is now an `apply`, and devirt_class_witness_method's local
`enum Error` gets a case so that 'caller2' keeps testing a throwing
witness call.