Skip to content

compactMap { $0 as? Protocol } on [AnyObject?] causes SIGSEGV under -O, works under -Onone #89178

@Julioacarrettoni

Description

@Julioacarrettoni

Description

When an array is typed as [AnyObject?] and elements are filtered and downcast via compactMap { $0 as? SomeProtocol }, the program crashes with a segmentation fault (exit code 139) in optimized builds. The exact same code runs correctly in debug builds. Changing the array type to [SomeProtocol?] and using compactMap { $0 } eliminates the crash.

This was first encountered in production code following this pattern:

Full code also available here: SwiftAnyObjectCast.zip

let items: [AnyObject?] = [
    ConcreteSection(title: "Always"),
    condition ? ConcreteSection(title: "Optional") : nil,
]
self.sections = items.compactMap { $0 as? SettingsSection }

Reproduction

protocol SettingsSection: AnyObject {
    var title: String { get }
    func process()
}

final class ConcreteSettingsSection: SettingsSection {
    let title: String
    init(title: String) { self.title = title }
    func process() { _ = title.uppercased() }
}

@inline(never)
func buildSections(includeOptional: Bool) -> [SettingsSection] {
    let optionalSection = ConcreteSettingsSection(title: "Optional Section")
    let optionalSections: [AnyObject?] = [
        ConcreteSettingsSection(title: "Non Optional Section"),
        includeOptional ? optionalSection : nil,
    ]
    return optionalSections.compactMap { $0 as? SettingsSection }
}

@inline(never)
func consume(_ sections: [SettingsSection]) {
    for section in sections {
        section.process()
        _ = section.title
    }
}

for i in 0..<10_000 {
    consume(buildSections(includeOptional: i.isMultiple(of: 2)))
}
print("Done")

Steps to reproduce

  1. Use the reproduction code here or create a Swift Package with the code above as the executable target's main.swift
  2. Run swift build -c release && .build/release/<target> → crashes immediately with SIGSEGV (exit 139), no output
  3. Run swift build && .build/debug/<target> → runs to completion, prints "Done"

Expected behavior

Both debug and release builds should run to completion.

Actual behavior

Release build (-O) crashes on the first call to buildSections with SIGSEGV before producing any output.

Workaround

Change the array type from [AnyObject?] to [SettingsSection?] and replace compactMap { $0 as? SettingsSection } with compactMap { $0 }. This produces identical runtime behavior and does not crash.

Environment

  • Swift 6.3.1 (swiftlang-6.3.1.1.2, clang-2100.0.123.102)
  • Apple Silicon (arm64-apple-macosx26.0)
  • Optimization: -O (release); -Onone (debug) is not affected

Attachments

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions