Skip to content

Commit de16ed8

Browse files
committed
SIL: Fix signature of reabstraction thunk involving parameterized existential
Fixes #74569 Fixes rdar://problem/130402282
1 parent a142b19 commit de16ed8

File tree

4 files changed

+91
-1
lines changed

4 files changed

+91
-1
lines changed

lib/AST/LocalArchetypeRequirementCollector.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ GenericSignature swift::buildGenericSignatureWithCapturedEnvironments(
136136
case GenericEnvironment::Kind::OpenedExistential: {
137137
auto constraint = genericEnv->getOpenedExistentialType();
138138
if (auto existential = constraint->getAs<ExistentialType>())
139-
constraint = existential->getConstraintType();
139+
constraint = existential->getConstraintType()->mapTypeOutOfContext();
140140
collector.addOpenedExistential(constraint);
141141
continue;
142142
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-swift-emit-silgen -disable-availability-checking %s | %FileCheck %s
2+
3+
protocol P<A> {
4+
associatedtype A
5+
associatedtype B
6+
var function: () -> B { get }
7+
}
8+
9+
func f<A>(p: any P<A>) {
10+
_ = p.function()
11+
}
12+
13+
// CHECK-LABEL: sil hidden [ossa] @$s40parameterized_existentials_reabstraction1f1pyAA1P_px1ARts_XP_tlF : $@convention(thin) <A> (@in_guaranteed any P<A>) -> () {
14+
15+
// CHECK-LABEL: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$s1B40parameterized_existentials_reabstraction1PPQyd__Iegr_ypIegr_1AQyd__RszAbCRd__r__lTR : $@convention(thin) <τ_0_0><τ_1_0 where τ_0_0 == τ_1_0.A, τ_1_0 : P> (@guaranteed @callee_guaranteed () -> @out τ_1_0.B) -> @out Any {
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-swift-frontend -emit-ir %s -disable-availability-checking
2+
3+
protocol Cache<Object> {
4+
associatedtype Object
5+
associatedtype Snapshot: Sequence<Object>
6+
7+
func entries(_ body: (Snapshot) -> Void) -> AsyncStream<Object>
8+
}
9+
10+
func readFromCacheImpl<T>(cache: any Cache<T>) async {
11+
let updateStream = cache.entries { _ in }
12+
13+
for await _ in updateStream {}
14+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// RUN: %target-swift-frontend -emit-ir %s -disable-availability-checking
2+
3+
protocol ContextDescriptor: Sendable { }
4+
5+
protocol OutcomeDescriptor: Sendable { }
6+
7+
protocol ResultDescriptor: Sendable { }
8+
9+
protocol ErasedReducer<Context>: Sendable {
10+
associatedtype Context: ContextDescriptor
11+
associatedtype TriggerOutcome: OutcomeDescriptor
12+
associatedtype Result: ResultDescriptor
13+
14+
var name: String { get }
15+
var function: @Sendable (_ context: Context?, _ trigger: TriggerOutcome) -> Result { get }
16+
}
17+
18+
protocol Reducer<Context, TriggerOutcome>: ErasedReducer {
19+
var name: String { get }
20+
var function: @Sendable (_ context: Context?, _ trigger: TriggerOutcome) -> Result { get }
21+
}
22+
23+
struct ExampleContext: ContextDescriptor { }
24+
25+
struct ExampleOutcome: OutcomeDescriptor { }
26+
27+
struct ExampleResult: ResultDescriptor { }
28+
29+
struct ExampleReducer<Context: ContextDescriptor, TriggerOutcome: OutcomeDescriptor, Result: ResultDescriptor>: Reducer {
30+
let name: String
31+
let function: @Sendable (_ context: Context?, _ trigger: TriggerOutcome) -> Result
32+
}
33+
34+
class ExampleService<Context: ContextDescriptor> {
35+
let reducers: [any ErasedReducer<Context>]
36+
37+
public init(reducers: [any ErasedReducer<Context>]) {
38+
self.reducers = reducers
39+
}
40+
41+
func reduce<TriggerOutcome: OutcomeDescriptor>(outcome: TriggerOutcome, context: Context) -> (any ResultDescriptor)? {
42+
// This line appears to be what's causing the crash
43+
guard let reducer = (reducers.compactMap { reducer in reducer as? any Reducer<Context, TriggerOutcome> }).first else {
44+
return nil
45+
}
46+
return reducer.function(context, outcome)
47+
}
48+
}
49+
50+
51+
public func testReducing() {
52+
let erasedReducers: [any ErasedReducer<ExampleContext>] = [
53+
ExampleReducer<ExampleContext, ExampleOutcome, ExampleResult>(name: "Example", function: { (_, _) in ExampleResult() })
54+
]
55+
let context = ExampleContext()
56+
let trigger = ExampleOutcome()
57+
58+
let service = ExampleService<ExampleContext>(reducers: erasedReducers)
59+
60+
_ = service.reduce(outcome: trigger, context: context)
61+
}

0 commit comments

Comments
 (0)