Skip to content

Crash when opening existential type to an opaque type #71111

Open
@ollieatkinson

Description

@ollieatkinson

Description

The compiler crashes when handling a protocol with an associated type that is recursively constrained to conform to itself. Specifically, the issue occurs in a setup where:

  1. A protocol Foo has an associated type Bar constrained to Foo.
  2. An existential type any Foo is used as a parameter in a function.
  3. A generic function _crash<V: Foo> within the aforementioned function attempts to return some Foo using the associated type.
  4. The function _openExistential is used to open the existential container, leading to the crash.

Reproduction

protocol Foo {
    associatedtype Bar: Foo
    var bar: Bar { get }
}

func crash(existential foo: any Foo) {
    func _crash<V: Foo>(open foo: V) -> some Foo { foo.bar }
    let bar = _openExistential(foo, do: _crash(open:)) // ← Crashes
}

It's almost possible to workaround the issue, by providing the following code, though it fails to compile as it still retains the existential type and not the underlying concrete.

protocol Foo {
    associatedtype Bar: Foo
    var bar: Bar { get }
}

func crash(existential foo: any Foo) -> some Foo {
    func _crash<V: Foo>(open foo: V) -> some Foo { foo.bar }
    return _crash(open: foo) // Type 'any Foo' cannot conform to 'Foo'
}

My naive thinking is that it should be possible given that the concrete type is available... though this is not the right place to raise this request:

protocol Foo {
    associatedtype Bar: Foo
    var bar: Bar { get }
}

struct Qux<A, B>: Foo {
    var description: String
    var bar: Qux<String, String> { Qux<String, String>(description: "bar") }
}

struct Erased {
    let existential: any Foo
    init<V: Foo>(_ view: V) {
        existential = view
    }
}

let erased = Erased(Qux<Bool, Bool>(description: "qux"))

func printing(existential foo: any Foo) {
    func printing<F: Foo>(foo: F) {
        Swift.print("🪟", String(describing: foo)) // 🪟 Qux<Bool, Bool>(description: "qux")
        Swift.print("🪟", String(describing: foo.bar)) // 🪟 Qux<String, String>(description: "bar")
    }
   printing(foo: foo)
}

printing(existential: erased.existential)

Stack dump

Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the crash backtrace.
Stack dump:
0.	Program arguments: /Applications/Xcode-15.1.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend -frontend -c -primary-file /Users/oliveratkinson/Development/Page/Sources/Page/Page.swift -emit-dependencies-path /Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Page-biekgzigjyhbfrfwypmsqcetysjd/Build/Intermediates.noindex/Page.build/Debug-iphonesimulator/Page.build/Objects-normal/arm64/Page.d -emit-const-values-path /Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Page-biekgzigjyhbfrfwypmsqcetysjd/Build/Intermediates.noindex/Page.build/Debug-iphonesimulator/Page.build/Objects-normal/arm64/Page.swiftconstvalues -emit-reference-dependencies-path /Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Page-biekgzigjyhbfrfwypmsqcetysjd/Build/Intermediates.noindex/Page.build/Debug-iphonesimulator/Page.build/Objects-normal/arm64/Page.swiftdeps -serialize-diagnostics-path /Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Page-biekgzigjyhbfrfwypmsqcetysjd/Build/Intermediates.noindex/Page.build/Debug-iphonesimulator/Page.build/Objects-normal/arm64/Page.dia -target arm64-apple-ios17.0-simulator -Xllvm -aarch64-use-tbi -enable-objc-interop -sdk /Applications/Xcode-15.1.0.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator17.2.sdk -I /Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Page-biekgzigjyhbfrfwypmsqcetysjd/Build/Products/Debug-iphonesimulator -I /Applications/Xcode-15.1.0.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/lib -F /Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Page-biekgzigjyhbfrfwypmsqcetysjd/Build/Products/Debug-iphonesimulator -F /Applications/Xcode-15.1.0.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Frameworks -F /Applications/Xcode-15.1.0.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator17.2.sdk/Developer/Library/Frameworks -no-color-diagnostics -enable-testing -g -module-cache-path /Users/oliveratkinson/Library/Developer/Xcode/DerivedData/ModuleCache.noindex -profile-generate -profile-coverage-mapping -swift-version 5 -enforce-exclusivity=checked -Onone -D SWIFT_PACKAGE -D DEBUG -D Xcode -serialize-debugging-options -package-name page -const-gather-protocols-file /Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Page-biekgzigjyhbfrfwypmsqcetysjd/Build/Intermediates.noindex/Page.build/Debug-iphonesimulator/Page.build/Objects-normal/arm64/Page_const_extract_protocols.json -empty-abi-descriptor -validate-clang-modules-once -clang-build-session-file /Users/oliveratkinson/Library/Developer/Xcode/DerivedData/ModuleCache.noindex/Session.modulevalidation -Xcc -working-directory -Xcc /Users/oliveratkinson/Development/Page -resource-dir /Applications/Xcode-15.1.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift -enable-anonymous-context-mangled-names -Xcc -ivfsstatcache -Xcc /Users/oliveratkinson/Library/Developer/Xcode/DerivedData/SDKStatCaches.noindex/iphonesimulator17.2-21C52-74d182069ce2f8b17958adf49e5cbcd9.sdkstatcache -Xcc -I/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Page-biekgzigjyhbfrfwypmsqcetysjd/Build/Intermediates.noindex/Page.build/Debug-iphonesimulator/Page.build/swift-overrides.hmap -Xcc -I/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Page-biekgzigjyhbfrfwypmsqcetysjd/Build/Products/Debug-iphonesimulator/include -Xcc -I/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Page-biekgzigjyhbfrfwypmsqcetysjd/Build/Intermediates.noindex/Page.build/Debug-iphonesimulator/Page.build/DerivedSources-normal/arm64 -Xcc -I/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Page-biekgzigjyhbfrfwypmsqcetysjd/Build/Intermediates.noindex/Page.build/Debug-iphonesimulator/Page.build/DerivedSources/arm64 -Xcc -I/Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Page-biekgzigjyhbfrfwypmsqcetysjd/Build/Intermediates.noindex/Page.build/Debug-iphonesimulator/Page.build/DerivedSources -Xcc -DSWIFT_PACKAGE -Xcc -DDEBUG=1 -module-name Page -frontend-parseable-output -disable-clang-spi -target-sdk-version 17.2 -target-sdk-name iphonesimulator17.2 -external-plugin-path /Applications/Xcode-15.1.0.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator17.2.sdk/usr/lib/swift/host/plugins#/Applications/Xcode-15.1.0.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator17.2.sdk/usr/bin/swift-plugin-server -external-plugin-path /Applications/Xcode-15.1.0.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator17.2.sdk/usr/local/lib/swift/host/plugins#/Applications/Xcode-15.1.0.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator17.2.sdk/usr/bin/swift-plugin-server -external-plugin-path /Applications/Xcode-15.1.0.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/lib/swift/host/plugins#/Applications/Xcode-15.1.0.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/swift-plugin-server -external-plugin-path /Applications/Xcode-15.1.0.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/local/lib/swift/host/plugins#/Applications/Xcode-15.1.0.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/swift-plugin-server -plugin-path /Applications/Xcode-15.1.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/host/plugins -plugin-path /Applications/Xcode-15.1.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/local/lib/swift/host/plugins -parse-as-library -o /Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Page-biekgzigjyhbfrfwypmsqcetysjd/Build/Intermediates.noindex/Page.build/Debug-iphonesimulator/Page.build/Objects-normal/arm64/Page.o -index-unit-output-path /Page.build/Debug-iphonesimulator/Page.build/Objects-normal/arm64/Page.o -index-store-path /Users/oliveratkinson/Library/Developer/Xcode/DerivedData/Page-biekgzigjyhbfrfwypmsqcetysjd/Index.noindex/DataStore -index-system-modules
1.	Apple Swift version 5.9.2 (swiftlang-5.9.2.2.56 clang-1500.1.0.2.5)
2.	Compiling with the current language version
3.	While evaluating request IRGenRequest(IR Generation for file "/Users/oliveratkinson/Development/Page/Sources/Page/Page.swift")
4.	While emitting IR SIL function "@$s4Page5crash11existentialyAA3Foo_p_tF".
 for 'crash(existential:)' (at /Users/oliveratkinson/Development/Page/Sources/Page/Page.swift:8:1)
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  swift-frontend           0x0000000107b19abc llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1  swift-frontend           0x000000010a77fcb0 llvm::sys::RunSignalHandlers() + 112
2  swift-frontend           0x000000010a4e9054 SignalHandler(int) + 352
3  libsystem_platform.dylib 0x000000018d8c1a24 _sigtramp + 56
4  swift-frontend           0x0000000109007d48 swift::irgen::emitArchetypeTypeMetadataRef(swift::irgen::IRGenFunction&, swift::CanTypeWrapper<swift::ArchetypeType>, swift::irgen::DynamicMetadataRequest) + 288
5  swift-frontend           0x0000000109007e18 swift::irgen::emitArchetypeTypeMetadataRef(swift::irgen::IRGenFunction&, swift::CanTypeWrapper<swift::ArchetypeType>, swift::irgen::DynamicMetadataRequest) + 496
6  swift-frontend           0x000000010a5b64d8 emitDirectTypeMetadataRef(swift::irgen::IRGenFunction&, swift::CanType, swift::irgen::DynamicMetadataRequest) + 252
7  swift-frontend           0x00000001064bc668 swift::irgen::IRGenFunction::emitTypeMetadataRef(swift::CanType, swift::irgen::DynamicMetadataRequest) + 292
8  swift-frontend           0x00000001064bda08 swift::irgen::IRGenFunction::emitTypeMetadataRefForLayout(swift::SILType, swift::irgen::DynamicMetadataRequest) + 296
9  swift-frontend           0x00000001057a5d14 swift::irgen::IRGenFunction::emitValueWitnessTableRef(swift::SILType, swift::irgen::DynamicMetadataRequest, llvm::Value**) + 136
10 swift-frontend           0x0000000108bb56e4 swift::irgen::emitLoadOfSize(swift::irgen::IRGenFunction&, swift::SILType) + 96
11 swift-frontend           0x00000001070ee92c swift::irgen::WitnessSizedTypeInfo<(anonymous namespace)::OpaqueArchetypeTypeInfo>::allocateStack(swift::irgen::IRGenFunction&, swift::SILType, llvm::Twine const&) const + 52
12 swift-frontend           0x000000010770ef40 (anonymous namespace)::IRGenSILFunction::visitSILBasicBlock(swift::SILBasicBlock*) + 22292
13 swift-frontend           0x0000000109e9dfdc swift::irgen::IRGenModule::emitSILFunction(swift::SILFunction*) + 11680
14 swift-frontend           0x0000000107a9c9c8 swift::irgen::IRGenerator::emitGlobalTopLevel(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&) + 2516
15 swift-frontend           0x00000001061419d0 swift::IRGenRequest::evaluate(swift::Evaluator&, swift::IRGenDescriptor) const + 6532
16 swift-frontend           0x0000000105a14adc swift::SimpleRequest<swift::IRGenRequest, swift::GeneratedModule (swift::IRGenDescriptor), (swift::RequestFlags)9>::evaluateRequest(swift::IRGenRequest const&, swift::Evaluator&) + 176
17 swift-frontend           0x00000001073e5f64 llvm::Expected<swift::IRGenRequest::OutputType> swift::Evaluator::getResultUncached<swift::IRGenRequest>(swift::IRGenRequest const&) + 1480
18 swift-frontend           0x000000010968cfb8 swift::performIRGeneration(swift::FileUnit*, swift::IRGenOptions const&, swift::TBDGenOptions const&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>, llvm::StringRef, swift::PrimarySpecificPaths const&, llvm::StringRef, llvm::GlobalVariable**) + 264
19 swift-frontend           0x000000010a05999c generateIR(swift::IRGenOptions const&, swift::TBDGenOptions const&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>, swift::PrimarySpecificPaths const&, llvm::StringRef, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, llvm::GlobalVariable*&, llvm::ArrayRef<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>) + 156
20 swift-frontend           0x000000010a0616d4 performCompileStepsPostSILGen(swift::CompilerInstance&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, swift::PrimarySpecificPaths const&, int&, swift::FrontendObserver*) + 1596
21 swift-frontend           0x000000010a05ca08 performCompile(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 1748
22 swift-frontend           0x000000010a060854 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 4568
23 swift-frontend           0x000000010a0c7d44 swift::mainEntry(int, char const**) + 4408
24 dyld                     0x000000018d5110e0 start + 2360

Expected behavior

I would not expect a crash but instead a warning the same as the near-workaround. It would be nice to avoid writing explicit type erasure for Foo - but understand this may not be possible in the language yet.

Environment

swift-driver version: 1.87.3 Apple Swift version 5.9.2 (swiftlang-5.9.2.2.56 clang-1500.1.0.2.5)
Target: arm64-apple-macosx14.0

Additional information

No response

Metadata

Metadata

Assignees

Labels

_openExistentialArea → standard library: The `_openExistential` intrinsicassertion failureBug → crash: An assertion failurebugA deviation from expected or documented behavior. Also: expected but undesirable behavior.compilerThe Swift compiler itselfcrashBug: A crash, i.e., an abnormal termination of softwareexistentialsFeature: values of types like `any Collection`, `Any` and `AnyObject`; type-erased valuesopaque result typesFeature → types → opaque types: opaque result typesopaque typesFeature → types: opaque typesswift 6.0type checkerArea → compiler: Semantic analysis

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions