Possible compiler bug related to deeply nested enums

In my team at work we are building an app using the ReactiveSwift port of Point-Free's TCA (of which I am the maintainer).

One of the features of the app has its state represented as an enum with large levels of nesting of other enums via associated types, as opposed to the rest of the app which uses the more common approach of modelling the state as a struct.

We recently discovered that when running the app we were getting EXC_BAD_ACCESS crashes in some situations where the app state (which includes all the feature states) was being modified. However, the crash only occurs when running on an iOS device. There is no problem at all when running in the simulator.

It's important to note that the crashes occurred even when the feature in question was never invoked. It was enough to merely have the deeply nested enum exist as a property of the app state for the crash to happen. Removing this nested enum property from the app state completely resolves the crashes.

In searching for a solution we stumbled across an old Swift bug which sounded very similar. EXC_BAD_ACCESS crashes, only on device, involving nested structs.

Is it possible that there is a similar bug related to enums?

When the app crashes the runtime function where the exception occurs is either ___chkstk_darwin or ___chkstk_probe and it's a SIGBUS(BUS_ADDRERR) signal that the app receives.

The crash is 100% reproducible but it may be tricky to create a minimal demo project that just reproduces the crash. It's not just the existence of the nested enums, but in an application using ReactiveSwift and TCA the state is copied a huge number of times, and it during one of these assignment / copies that the crash occurs.

cc: @Slava_Pestov since you fixed the similar bug relating to nested structs.

3 Likes

If you are able to, you could share the project privately through feedbackassistant.apple.com . It's understandable that in many cases, creating a minimal reproducer is tricky, but having clear instructions for building and reproducing can help a compiler engineer drill down on the issue relatively quickly.

3 Likes

After further investigation, it would seem that the issue here is not a compiler bug at all, but just a stack overflow :grinning_face_with_smiling_eyes:

The deeply nested enum with all its associated values will occupy on the stack the size of the largest associated value combination possible. This turned out to be about 8KB. This made the total state of the app around 11KB.

With a reactive framework and uni-directional data flow, the stack depth can get quite big, and we just blew the limit. Can anyone confirm that on iOS the stack size of the main thread is still 1MB as mentioned here?

This would also explain why the crash only happened on device, since the stack size of the main thread on macOS is 8MB instead of just 1MB.

2 Likes