Files
Ben Cohen f8d211057e [SILOptimizer] Fold try_apply with an uninhabited error type (#92174)
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.
2026-09-22 20:03:31 -07:00
..