Can we get consistent assertion behavior in the latest release Swift compiler across host platforms?

I have been noticing issues raised for compiler assertion crashes this year with the OSS macOS release toolchains, which are not reproducible with the Xcode or linux release toolchains, presumably because those assertions are disabled in those builds. In particular, @marcprux has filed issues like these, and I raised this problem in the forum five months ago.

I understand that it may be a contentious issue of whether the release compiler should have these assertions enabled or disabled, but I'd at least like to argue for consistency across platforms and builds, ie the latest release should make the same choice for all release compiler builds. I just raised the issue with @compnerd and @etcwilde, and @compnerd tells us that the release Windows compiler has these assertions enabled.

This is not going to be a great dev experience, if the Swift 6.1.2 compiler on linux can compile those samples linked, but the Swift 6.1.2 compiler on Windows can't.

Let me emphasize that I'm only talking about the latest patch releases like 6.1.2, the nightly snapshot builds are excluded from this discussion.

I'd like to see some consensus reached on this topic by the Swift teams, and I suspect a growing amount of Swift devs would also.

6 Likes

From a supportability point of view, the windows toolchain really does rely on the assertions heavily. The assertions have almost always found real issues that would silently potentially cause invalid code generation. or potentially allow invalid code through. I think that given the resources available for Windows, the assertions are not reasonable to disable.

We are waiting on @mishal_shah to coordiinat getting Rename toolchain msi and cab files to include name of variant (asserts) by mhegazy · Pull Request #428 · swiftlang/swift-installer-scripts · GitHub merged which will allow us to package both an Asserts and NoAsserts toolchain and the user can then select if they want to ignore the issues and build the code anyway.

2 Likes

I've been consistently running into this issue for months, and have had to refactor and rearchitect a ton of perfectly valid swift code, with pure swift dependencies just to avoid compiler crashes.

This affects Skip.tools android apps, because the android sdk relies on the macOS toolchain. I started running into this as well when I was testing out the new swiftly toolchain manager.

I did notice that the last couple changes to the build toolchain are related to adding flags that allow you to target macOS specifically, and one about adding an assertions flag. Could this be an unintended interaction between those flags?

Unfortunately, programs that only compile with a no-asserts toolchain aren’t quite perfectly valid. At the very least it means you’re exercising some compiler code path that’s not covered by tests, so it could regress in a future release. We’ve also seen bugs where an input program that trips an assertion then silently miscompiles without asserts.

7 Likes

Unfortunately, programs that only compile with a no-asserts toolchain aren’t quite perfectly valid. At the very least it means you’re exercising some compiler code path that’s not covered by tests, so it could regress in a future release. We’ve also seen bugs where an input program that trips an assertion then silently miscompiles without asserts.

So does that mean that the Xcode toolchain has these assertions enabled, but generates code in a more correct way? Or does the xcode toolchain disable these assertions, potentially allowing through code that can silently miscompile?

If thats the case should people be concerned about using these features in production systems?

1 Like

https://github.com/swiftlang/swift/issues/82529

I’m coming back to this a few months later and I don’t think I’ve seen any movement.

The macOS toolchain crashes when compiling valid code on the main swift release, and the most recent 6.2 snapshot.

This issue has a minimum reproduction. It’s using newer parameter pack features. As more and more libraries adopt code that trips these assertions, projects that are using the macOS toolchain get harder and harder to compile.

Is anybody else experiencing this? Popular libraries like swift-sharing trip these assertions when I use swiftly and try to build them using the command line.

The code is not valid, because it trips an assertion. I believe this pattern can miscompile in some cases, and there’s a bug that needs to be fixed.

2 Likes

What is the rationale for the OSS toolchain enabling assertions beside shining light on bugs in the compiler itself?

Assume that a correct piece of swift code triggers an assertion failure in the OSS toolchain because the compiler does a bad transformation in SIL (or IR), then a swift-dev can compile their project using the xcode stock toolchain but not the OSS toolchain.

At least for my project, this makes the OSS toolchain nearly unusable because the SIL assertion failure might come from a dependency that I do not have control over or just from a bad transformation in the compiler.

1 Like

It’s mostly that, yeah. Asserts builds produce far more actionable crash reports for compiler developers.

I understand that compiler bugs are frustrating, and having two build configurations for the toolchain is suboptimal. I do believe that an assertion should either be checked all or the time, or removed from the code — there shouldn’t be such a thing as an approximately correct precondition.

Even though it will address your immediate issue, disabling assertions in the OSS toolchain is going to move things in the wrong direction rather than improving the stability of the compiler in the long term.

The point I want to emphasize is if you’re seeing assertion failures regularly, it means you’re hitting code paths in the compiler which are not tested by the test suite, because CI always runs the compiler with assertions on. I would not trust the compiler’s output in this scenario.

6 Likes

Thanks for addressing our concerns somewhat. However,

How is Xcode handling these cases: is it simply disabling the assertions or is it doing something different where you can then trust it to compile such code?

I'm sure you can see the problem in saying you don't want to disable assertions because of the problems it would cause, then seemingly doing so anyway in Xcode and linux.

I understand that this is probably a contentious issue internally and maybe there is no way to get the cross-platform consistency I asked for given current constraints, but it is harming the cross-platform Swift experience, and it may help to at least know why certain platforms have them enabled and others don't.

And there is always the option to use the linux toolchain and cross-compile using that instead or build a Swift toolchain yourself from source, so nobody can say there aren't release valves.

1 Like

Just to add some real-world color here, we at Skip are regularly getting reports of code that builds and runs fine for iOS is raising an assertion when building for Android, especially for some of the more notorious Swift compiler 6 bugs like Parameter pack compilation crash "This isn't an lvalue" with 6.0.3 OSS toolchain but works with Xcode toolchain · Issue #79870 · swiftlang/swift · GitHub. This makes it seem like the Swift Android SDK is buggy, when in fact it is the OSS host toolchain that is exhibiting different behavior from the Xcode toolchain. This, of course, will also affect the static Linux and WASM SDKs, and any other Swift SDK due to the need to align with the OSS toolchain rather than Xcode's.

The code is not valid, because it trips an assertion. I believe this pattern can miscompile in some cases, and there’s a bug that needs to be fixed.

I don't think we've yet gotten a response about why Xcode's toolchain doesn't have assertions enabled. Is it for performance, or some other reason? Isn't there consternation at the prospect of invalid assertion-tripping code being allowed to miscompile and make its way into production iOS apps?

6 Likes

Here’s an example where assertions may be (are) causing inconsistent build behavior: Compiler Crash When Building With Swift 6.2.x Release Toolchain (swift.org) · Issue #128 · apple/swift-configuration · GitHub

1 Like

In the past we've had some bugs where SIL verification failed: inconsistent stack heights entering basic block: state.Stack == foundState.Stack || isUnreachable() indicated a genuine miscompile. I think @John_McCall might want to take a look.

From the perspective of a maintainer of packages supported across platforms, some of which have assertions enabled while others disabled, the status quo is quite a frustrating experience.

I think it's fine to have assertions behavior differ between development and release snapshots.

But can we please have consistent assertion behavior between platforms? Pick one, either is fine (enabled or disabled), but bring them all to the same behavior. As otherwise bugs found on the less prioritized platforms always struggle to get fixes in, if they don't affect the more prioritized platforms that have assertions disabled.

14 Likes

Huge +1 for this. Always encounter some strange CI failure of the Linux compiler. And I have to change my code somehow to workaround it. It is very frustrating that I can't reproduce it with my Xcode toolchain.

I know this is a compiler bug which needs to be fixed. But I really hope we have the same configuration for non-Darwin platform release toolchain and Darwin platform release toolchain to avoid blocking our pipeline.

3 Likes

At least for Windows, the default is the asserting toolchain. Sadly, adding the no asserts toolchain is quite expensive (adding an additional ~1.5h and increasing the installer by an additional ~500MB). Granted that we do this for the BCNY releases, but I’m not sure that the calculus works out in the swift.org case currently. If this is for CI/CD purposes, perhaps adopting the OSS toolchain on Darwin might be an option to consider.

I appreciate that there might be work required to resolve the inconsistency, but I do think the Core Team or Platform Steering Group should discuss and then communicate one recommendation for release toolchains across platforms that API-stable packages should be using in CI.

When the same Swift code is valid according to a toolchain shipped on one platform but invalid (and crashes) on another (same version), this shifts the complexity of dealing with toolchain bugs onto library authors, which in turn makes it difficult (and sometimes, simply not worth it) to support more (officially supported) platforms in packages. In practice, this creates an incentive to support as few platforms as possible, which I believe is not what we want for the Swift ecosystem.

9 Likes

I wasn't making that comment on behalf of either of those groups - simply as the maintainer for the Windows toolchain.

I can understand where you are coming from, but the PSG cannot make a recommendation here. The toolchain that is being discussed here is the Apple toolchain. This is an issue to be discussed on Feedback not the forums. AIUI, the OSS toolchain does enable assertions, just like the Windows and Linux toolchains. What Xcode does is not something that the OSS Swift Project has any control over. If the issue is that the OSS toolchains differ then that is something to consider.

1 Like

I agree that if the PSG/CT officially recommend that release toolchains should ship with assertions enabled, then it'd make sense to move this into Feedback. Has that happened?

Until then, the community just sees inconsistent behavior without a clear guideline on which one is correct and which one needs adjusting.

@mishal_shah is "assertions enabled" the recommendation for release toolchains?

1 Like

Only indirectly, we are primarily talking about inconsistent behavior of the OSS patch release toolchains on different platforms above. Xcode only came up because some Apple employees have claimed that the assertions build is the right choice, to which the natural counter-argument is that Xcode seems to have those same assertions turned off.

Yes, they do differ: see my OP above, ie the OSS mac and windows release toolchains have them turned on, while the equivalent linux release toolchain has them turned off. So @Honza_Dvorsky is right that this is a matter for the PSG and core team to consider and justify their decision.

Ultimately, this only affects individuals and new users, as any serious company will build their own non-Xcode toolchain from the open source, as Readdle does with their own cross-compilation toolchain for Android and which is easy to do with the CI Dockerfiles. But as the language goes more cross-platform, that remaining more casual, less Apple-tied demographic of individuals and new entrants, who are not going to build and customize the toolchain from source early in their use, is important to consider.

2 Likes