-
Notifications
You must be signed in to change notification settings - Fork 10.6k
Description
Description
We ran into a crash while building a project in release mode.
Isolating it as best I can, it seems to happen when specializing a function that applies a stored closure returning a generic existential type.
Reproduction
// Minimal protocol with associated type
protocol P<Shape> {
associatedtype Shape
}
// Builder stores a closure returning the constrained existential
struct Builder<A> {
let f: () -> any P<A> // Dropping the constraint on P avoids the crash
// i.e. `let f: () -> any P`
}
// Array helper
extension Array {
func resolve<A>() -> [any P]
where Element == Builder<A>
{
map { $0.f() }
}
}
// Concrete witness and concrete type to specialize
struct Concrete<S>: P { typealias Shape = S }
struct X {}
_ = [
Builder<X>.init { Concrete<X>() }
].resolve()I've minimized down to the above code in a single file, compiling with optimizations: swiftc -O repro.swift
Note that it compiles successfully without optimizations, so -O is required.
As I was working to minimize the reproducer, I noticed that dropping the constraint on the existential P in Builder's f return type caused compilation to succeed, so that seems like a clue as to where the bug is.
Stack dump
SIL verification failed: result of struct_element_addr does not match type of field
$*@callee_guaranteed () -> @out any P<X>
$*@callee_guaranteed @substituted <τ_0_0> () -> @out any P<τ_0_0> for <X>
Verifying instruction:
%56 = store_borrow %54 to %55 : $*Builder<X> // users: %62, %57
-> %57 = struct_element_addr %56 : $*Builder<X>, #Builder.f // user: %58
%58 = load_borrow %57 : $*@callee_guaranteed @substituted <τ_0_0> () -> @out any P<τ_0_0> for <X> // users: %61, %60
In function:
// specialized Array.resolve<A>()
sil shared [ossa] @$sSa4mainE7resolveSayAA1P_pGyAA7BuilderVyqd__GRszlFAA1XV_Tg5 : $@convention(method) (@guaranteed Array<Builder<X>>) -> @owned Array<any P> {
// %0 "self" // users: %53, %51, %3, %1
bb0(%0 : @guaranteed $Array<Builder<X>>):
debug_value %0, let, name "self", argno 1 // id: %1
// function_ref specialized Array.count.getter
%2 = function_ref @$sSa5countSivg4main7BuilderVyAB1XVG_Tg5 : $@convention(method) (@guaranteed Array<Builder<X>>) -> Int // user: %3
%3 = apply %2(%0) : $@convention(method) (@guaranteed Array<Builder<X>>) -> Int // users: %19, %5
%4 = integer_literal $Builtin.Int64, 0 // users: %33, %37, %41, %20, %8, %6
%5 = struct_extract %3, #Int._value // users: %33, %84, %43, %20, %6
%6 = builtin "cmp_eq_Int64"(%5, %4) : $Builtin.Int1 // user: %7
cond_br %6, bb1, bb2 // id: %7
bb1: // Preds: bb0
%8 = struct $Int (%4) // user: %10
// function_ref specialized static Array._allocateUninitialized(_:)
%9 = function_ref @$sSa22_allocateUninitializedySayxG_SpyxGtSiFZ4main1P_p_Tt0g5 : $@convention(thin) (Int) -> (@owned Array<any P>, UnsafeMutablePointer<any P>) // user: %10
%10 = apply %9(%8) : $@convention(thin) (Int) -> (@owned Array<any P>, UnsafeMutablePointer<any P>) // user: %11
(%11, %12) = destructure_tuple %10 // user: %13
br bb3(%11) // id: %13
bb2: // Preds: bb0
%14 = alloc_stack [var_decl] $ContiguousArray<any P> // users: %93, %86, %82, %81, %80, %28, %70, %19, %17
// function_ref specialized ContiguousArray.init()
%15 = function_ref @$ss15ContiguousArrayVAByxGycfC4main1P_p_Ttg5 : $@convention(thin) () -> @owned ContiguousArray<any P> // user: %16
%16 = apply %15() : $@convention(thin) () -> @owned ContiguousArray<any P> // user: %17
store %16 to [init] %14 // id: %17
// function_ref specialized ContiguousArray.reserveCapacity(_:)
%18 = function_ref @$ss15ContiguousArrayV15reserveCapacityyySiF4main1P_p_Tg5 : $@convention(method) (Int, @inout ContiguousArray<any P>) -> () // user: %19
%19 = apply %18(%3, %14) : $@convention(method) (Int, @inout ContiguousArray<any P>) -> ()
%20 = builtin "cmp_slt_Int64"(%5, %4) : $Builtin.Int1 // user: %21
cond_fail %20, "Range requires lowerBound <= upperBound" // id: %21
%22 = integer_literal $Builtin.Int1, -1 // users: %46, %44
%23 = integer_literal $Builtin.Int64, 1 // user: %46
// function_ref specialized Array._hoistableIsNativeTypeChecked()
%24 = function_ref @$sSa29_hoistableIsNativeTypeCheckedSbyF4main7BuilderVyAB1XVG_Tg5 : $@convention(method) (@guaranteed Array<Builder<X>>) -> Bool // user: %51
// function_ref specialized Array._checkSubscript(_:wasNativeTypeChecked:)
%25 = function_ref @$sSa15_checkSubscript_20wasNativeTypeCheckeds16_DependenceTokenVSi_SbtF4main7BuilderVyAE1XVG_Tg5 : $@convention(method) (Int, Bool, @guaranteed Array<Builder<X>>) -> _DependenceToken
// function_ref specialized Array._getElement(_:wasNativeTypeChecked:matchingSubscriptCheck:)
%26 = function_ref @$sSa11_getElement_20wasNativeTypeChecked22matchingSubscriptCheckxSi_Sbs16_DependenceTokenVtF4main7BuilderVyAF1XVG_Tg5 : $@convention(method) (Int, Bool, _DependenceToken, @guaranteed Array<Builder<X>>) -> @owned Builder<X> // user: %53
// function_ref specialized ContiguousArray._makeUniqueAndReserveCapacityIfNotUnique()
%27 = function_ref @$ss15ContiguousArrayV034_makeUniqueAndReserveCapacityIfNotD0yyF4main1P_p_Tg5 : $@convention(method) (@inout ContiguousArray<any P>) -> () // user: %70
%28 = struct_element_addr %14, #ContiguousArray._buffer // user: %29
%29 = struct_element_addr %28, #_ContiguousArrayBuffer._storage // user: %71
// function_ref specialized ContiguousArray._reserveCapacityAssumingUniqueBuffer(oldCount:)
%30 = function_ref @$ss15ContiguousArrayV36_reserveCapacityAssumingUniqueBuffer8oldCountySi_tF4main1P_p_Tg5 : $@convention(method) (Int, @inout ContiguousArray<any P>) -> () // user: %80
// function_ref specialized ContiguousArray._appendElementAssumeUniqueAndCapacity(_:newElement:)
%31 = function_ref @$ss15ContiguousArrayV37_appendElementAssumeUniqueAndCapacity_03newD0ySi_xntF4main1P_p_Tg5 : $@convention(method) (Int, @in any P, @inout ContiguousArray<any P>) -> () // user: %81
// function_ref specialized ContiguousArray._endMutation()
%32 = function_ref @$ss15ContiguousArrayV12_endMutationyyF4main1P_p_Tg5 : $@convention(method) (@inout ContiguousArray<any P>) -> () // user: %82
%33 = builtin "cmp_sge_Int64"(%4, %5) : $Builtin.Int1 // user: %34
cond_fail %33, "loop induction variable overflowed" // id: %34
%35 = integer_literal $Builtin.Int1, 0 // user: %42
%36 = integer_literal $Builtin.Int1, -1 // user: %44
br bb4(%4) // id: %37
// %38 // user: %39
bb3(%38 : @owned $Array<any P>): // Preds: bb5 bb1
return %38 // id: %39
// %40 // users: %50, %46, %43, %41
bb4(%40 : $Builtin.Int64): // Preds: bb6 bb2
%41 = builtin "cmp_slt_Int64"(%40, %4) : $Builtin.Int1
cond_fail %35, "Index out of bounds" // id: %42
%43 = builtin "cmp_slt_Int64"(%40, %5) : $Builtin.Int1
%44 = builtin "xor_Int1"(%36, %22) : $Builtin.Int1 // user: %45
cond_fail %44, "Index out of bounds" // id: %45
%46 = builtin "sadd_with_overflow_Int64"(%40, %23, %22) : $(Builtin.Int64, Builtin.Int1) // users: %48, %47
%47 = tuple_extract %46, 0 // users: %95, %84
%48 = tuple_extract %46, 1
%49 = alloc_stack [lexical] $any P // users: %64, %83, %81
%50 = struct $Int (%40) // user: %53
%51 = apply %24(%0) : $@convention(method) (@guaranteed Array<Builder<X>>) -> Bool // user: %53
%52 = struct $_DependenceToken () // user: %53
%53 = apply %26(%50, %51, %52, %0) : $@convention(method) (Int, Bool, _DependenceToken, @guaranteed Array<Builder<X>>) -> @owned Builder<X> // user: %54
%54 = move_value [lexical] %53 // users: %66, %56
%55 = alloc_stack $Builder<X> // users: %69, %56
%56 = store_borrow %54 to %55 // users: %62, %57
%57 = struct_element_addr %56, #Builder.f // user: %58
%58 = load_borrow %57 // users: %61, %60
%59 = alloc_stack $any P<X> // users: %68, %67, %63, %60
%60 = apply %58(%59) : $@callee_guaranteed @substituted <τ_0_0> () -> @out any P<τ_0_0> for <X>
end_borrow %58 // id: %61
end_borrow %56 // id: %62
%63 = open_existential_addr immutable_access %59 to $*@opened("49D17B98-C03C-11F0-A3D3-066CDC995E31", any P<X>) Self // users: %65, %64
%64 = init_existential_addr %49, $@opened("49D17B98-C03C-11F0-A3D3-066CDC995E31", any P<X>) Self // type-defs: %63; user: %65
copy_addr %63 to [init] %64 // id: %65
destroy_value %54 // id: %66
destroy_addr %59 // id: %67
dealloc_stack %59 // id: %68
dealloc_stack %55 // id: %69
%70 = apply %27(%14) : $@convention(method) (@inout ContiguousArray<any P>) -> ()
%71 = load_borrow %29 // users: %79, %72
%72 = ref_element_addr %71, #__ContiguousArrayStorageBase.countAndCapacity // user: %73
%73 = struct_element_addr %72, #_ArrayBody._storage // user: %74
%74 = struct_element_addr %73, #_SwiftArrayBodyStorage.count // user: %75
%75 = struct_element_addr %74, #Int._value // user: %76
%76 = load [trivial] %75 // user: %77
%77 = builtin "assumeNonNegative_Int64"(%76) : $Builtin.Int64 // user: %78
%78 = struct $Int (%77) // users: %81, %80
end_borrow %71 // id: %79
%80 = apply %30(%78, %14) : $@convention(method) (Int, @inout ContiguousArray<any P>) -> ()
%81 = apply %31(%78, %49, %14) : $@convention(method) (Int, @in any P, @inout ContiguousArray<any P>) -> ()
%82 = apply %32(%14) : $@convention(method) (@inout ContiguousArray<any P>) -> ()
dealloc_stack %49 // id: %83
%84 = builtin "cmp_eq_Int64"(%47, %5) : $Builtin.Int1 // user: %85
cond_br %84, bb5, bb6 // id: %85
bb5: // Preds: bb4
%86 = load [take] %14 // user: %87
%87 = destructure_struct %86 // user: %88
%88 = destructure_struct %87 // user: %89
%89 = unchecked_ref_cast %88 to $Builtin.BridgeObject // user: %90
%90 = struct $_BridgeStorage<__ContiguousArrayStorageBase> (%89) // user: %91
%91 = struct $_ArrayBuffer<any P> (%90) // user: %92
%92 = struct $Array<any P> (%91) // user: %94
dealloc_stack %14 // id: %93
br bb3(%92) // id: %94
bb6: // Preds: bb4
br bb4(%47) // id: %95
} // end sil function '$sSa4mainE7resolveSayAA1P_pGyAA7BuilderVyqd__GRszlFAA1XV_Tg5'
Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the crash backtrace.
Stack dump:
0. Program arguments: ~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend -frontend -c -primary-file repro.swift -target arm64-apple-macosx26.0 -Xllvm -aarch64-use-tbi -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -color-diagnostics -Xcc -fcolor-diagnostics -O -empty-abi-descriptor -no-auto-bridging-header-chaining -module-name main -in-process-plugin-server-path ~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/lib/swift/host/libSwiftInProcPluginServer.dylib -plugin-path ~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/lib/swift/host/plugins -plugin-path ~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/local/lib/swift/host/plugins -target-sdk-version 26.1 -target-sdk-name macosx26.1 -external-plugin-path /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib/swift/host/plugins#/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/bin/swift-plugin-server -external-plugin-path /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/local/lib/swift/host/plugins#/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/bin/swift-plugin-server -enable-default-cmo -o /var/folders/4v/lbp_rtss3q1fwqdfv5y4d0wh0000gp/T/TemporaryDirectory.ZQgaPV/sil-verification-crash_5-1.o
1. Apple Swift version 6.2.1 (swift-6.2.1-RELEASE)
2. Compiling with effective version 5.10
3. While evaluating request ExecuteSILPipelineRequest(Run pipelines { PrepareOptimizationPasses, EarlyModulePasses, HighLevel,Function+EarlyLoopOpt, HighLevel,Module+StackPromote, MidLevel,Function, ClosureSpecialize, LowLevel,Function, LateLoopOpt, SIL Debug Info Generator } on SIL for main)
4. While running pass #3657 SILFunctionTransform "BoundsCheckOpts" on SILFunction "@$sSa4mainE7resolveSayAA1P_pGyAA7BuilderVyqd__GRszlFAA1XV_Tg5".
for 'resolve()' (at repro.swift:13:5)
5. While verifying SIL function "@$sSa4mainE7resolveSayAA1P_pGyAA7BuilderVyqd__GRszlFAA1XV_Tg5".
for 'resolve()' (at repro.swift:13:5)
#0 0x000000010a0bcb6c (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x1059dcb6c)
#1 0x000000010a0bb298 (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x1059db298)
#2 0x000000010a0bd1b4 (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x1059dd1b4)
#3 0x000000019f492744 (/usr/lib/system/libsystem_platform.dylib+0x1804d6744)
#4 0x000000019f488888 (/usr/lib/system/libsystem_pthread.dylib+0x1804cc888)
#5 0x000000019f38e808 (/usr/lib/system/libsystem_c.dylib+0x1803d2808)
#6 0x000000010581cb1c (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x10113cb1c)
#7 0x0000000105834df8 (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x101154df8)
#8 0x00000001058249d0 (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x1011449d0)
#9 0x0000000105823258 (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x101143258)
#10 0x000000010581d534 (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x10113d534)
#11 0x00000001051cac00 (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x100aeac00)
#12 0x000000010530a0cc (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x100c2a0cc)
#13 0x000000010530adf0 (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x100c2adf0)
#14 0x0000000105307ffc (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x100c27ffc)
#15 0x0000000105307f7c (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x100c27f7c)
#16 0x000000010532d7bc (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x100c4d7bc)
#17 0x000000010530f1c8 (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x100c2f1c8)
#18 0x00000001053081ec (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x100c281ec)
#19 0x0000000105310950 (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x100c30950)
#20 0x0000000104bb59ac (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x1004d59ac)
#21 0x0000000104974c48 (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x100294c48)
#22 0x00000001049742a8 (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x1002942a8)
#23 0x0000000104980a6c (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x1002a0a6c)
#24 0x00000001049760a0 (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x1002960a0)
#25 0x000000010497585c (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x10029585c)
#26 0x0000000104718d48 (~/Library/Developer/Toolchains/swift-6.2.1-RELEASE.xctoolchain/usr/bin/swift-frontend+0x100038d48)
#27 0x000000019f0c9d54
Expected behavior
The provided code should compile successfully with optimizations enabled.
Environment
macOS: 26.0.1
Xcode: 26.1
swift: Reproduced with both the open source 6.2.1 release, as well as the latest main snapshot (2025-11-03).
Note that this does not reproduce in a linux container.
Additional information
No response