Skip to content

Commit 56521f0

Browse files
committed
Optimizer: fix handling of dependent existential archetypes in alloc_stack and apply simplification
When replacing an opened existential type with the concrete type, we didn't consider that the existential archetype can also be a "dependent" type of the root archetype. For now, just bail in this case. In future we can support dependent archetypes as well. Fixes a compiler crash. rdar://158594365
1 parent 0a8c602 commit 56521f0

File tree

4 files changed

+73
-5
lines changed

4 files changed

+73
-5
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyAllocStack.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,8 @@ private extension AllocStackInst {
179179
/// use %3
180180
/// ```
181181
func optimizeExistential(_ context: SimplifyContext) -> Bool {
182-
guard type.isExistential || type.isExistentialArchetype,
182+
// TODO: support non-root existential archetypes
183+
guard type.isExistential || type.isRootExistentialArchetype,
183184
let concreteFormalType = getConcreteTypeOfExistential()
184185
else {
185186
return false

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,9 @@ private extension FullApplySite {
216216
// Make sure that existential archetype _is_ a replacement type and not e.g. _contained_ in a
217217
// replacement type, like
218218
// apply %1<Array<@opened("...")>()
219-
guard substitutionMap.replacementTypes.contains(where: { $0.isExistentialArchetype }),
220-
substitutionMap.replacementTypes.allSatisfy({ $0.isExistentialArchetype || !$0.hasLocalArchetype })
219+
// TODO: support non-root existential archetypes
220+
guard substitutionMap.replacementTypes.contains(where: { $0.isRootExistentialArchetype }),
221+
substitutionMap.replacementTypes.allSatisfy({ $0.isRootExistentialArchetype || !$0.hasLocalArchetype })
221222
else {
222223
return false
223224
}
@@ -237,9 +238,9 @@ private extension FullApplySite {
237238
let type = value.type
238239
// Allow three cases:
239240
// case 1. the argument _is_ the existential archetype
240-
return type.isExistentialArchetype ||
241+
return type.isRootExistentialArchetype ||
241242
// case 2. the argument _is_ a metatype of the existential archetype
242-
(type.isMetatype && type.canonicalType.instanceTypeOfMetatype.isExistentialArchetype) ||
243+
(type.isMetatype && type.canonicalType.instanceTypeOfMetatype.isRootExistentialArchetype) ||
243244
// case 3. the argument has nothing to do with the existential archetype (or any other local archetype)
244245
!type.hasLocalArchetype
245246
}

test/SILOptimizer/simplify_alloc_stack.sil

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,27 @@ public struct S {}
1010
protocol P {
1111
}
1212

13+
protocol Q {
14+
associatedtype A
15+
}
16+
1317
public class C2: P {}
1418

1519
public struct T: P {
1620
let c: C
1721
let s: S
22+
23+
struct A {
24+
var y: String
25+
}
26+
}
27+
28+
public struct U: Q {
29+
let s: String
30+
31+
struct A {
32+
var y: String
33+
}
1834
}
1935

2036
public struct T1: P {
@@ -235,6 +251,24 @@ bb0(%0 : @owned $T):
235251
return %r
236252
}
237253

254+
// TODO: we don't support dependent existential archetypes, yet. Once we do, change this test case.
255+
// CHECK-LABEL: sil [ossa] @dont_replace_dependent_archetype :
256+
// CHECK: alloc_stack {{.*}}@opened
257+
// CHECK: } // end sil function 'dont_replace_dependent_archetype'
258+
sil [ossa] @dont_replace_dependent_archetype : $@convention(thin) (@owned U.A) -> () {
259+
bb0(%0 : @owned $U.A):
260+
%1 = metatype $@thick U.Type
261+
%2 = init_existential_metatype %1, $@thick Q.Type
262+
%3 = open_existential_metatype %2 to $@thick (@opened("82105EE0-DCB0-11E5-865D-C8E0EB309914", Q) Self).Type
263+
%4 = alloc_stack $(@opened("82105EE0-DCB0-11E5-865D-C8E0EB309914", Q) Self).A
264+
%5 = unchecked_addr_cast %4 to $*U.A
265+
store %0 to [init] %5
266+
destroy_addr %4
267+
dealloc_stack %4
268+
%r = tuple ()
269+
return %r
270+
}
271+
238272
// CHECK-LABEL: sil [ossa] @replace_existential_with_concrete_type1 :
239273
// CHECK: [[S:%.*]] = alloc_stack $T
240274
// CHECK-NOT: init_existential_addr

test/SILOptimizer/simplify_apply.sil

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,21 @@ enum E: String {
3030
case a, b, c, d, e
3131
}
3232

33+
protocol P2 {
34+
associatedtype A: Q
35+
}
36+
37+
protocol Q {
38+
}
39+
40+
public struct S2: P2 {
41+
var x: String
42+
struct A: Q {
43+
var y: String
44+
}
45+
}
46+
47+
3348
sil @cl : $@convention(thin) () -> Int
3449

3550
// CHECK-LABEL: sil [ossa] @thick_to_thin :
@@ -64,6 +79,7 @@ sil_vtable Bar {
6479
}
6580

6681
sil @createit : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type, Int) -> @out τ_0_0
82+
sil @create2 : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (Int) -> @out τ_0_0
6783
sil @useGenS : $@convention(thin) <τ_0_0 where τ_0_0 : P> (GenS<τ_0_0>) -> ()
6884
sil @returnGenS : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> GenS<τ_0_0>
6985

@@ -128,6 +144,22 @@ bb0(%0 : $Int):
128144
return %11
129145
}
130146

147+
// TODO: we don't support dependent existential archetypes, yet. Once we do, change this test case.
148+
// CHECK-LABEL: sil [ossa] @dont_replace_dependent_archetype :
149+
// CHECK: apply %{{[0-9]+}}<(@opened
150+
// CHECK: } // end sil function 'dont_replace_dependent_archetype'
151+
sil [ossa] @dont_replace_dependent_archetype : $@convention(thin) (Int) -> @out any Q {
152+
bb0(%0 : $*any Q, %1 : $Int):
153+
%2 = metatype $@thick S2.Type
154+
%3 = init_existential_metatype %2, $@thick any P2.Type
155+
%4 = open_existential_metatype %3 to $@thick (@opened("0FC03D78-E9DB-11EF-B47C-0EA13E3AABB4", any P2) Self).Type
156+
%6 = function_ref @create2 : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (Int) -> @out τ_0_0
157+
%7 = init_existential_addr %0, $(@opened("0FC03D78-E9DB-11EF-B47C-0EA13E3AABB4", any P2) Self).A
158+
%8 = apply %6<(@opened("0FC03D78-E9DB-11EF-B47C-0EA13E3AABB4", any P2) Self).A>(%7, %1) : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (Int) -> @out τ_0_0
159+
%11 = tuple ()
160+
return %11
161+
}
162+
131163
// CHECK-LABEL: sil [ossa] @dont_replace_returned_embedded_archetype :
132164
// CHECK: apply %{{[0-9]+}}<@opened
133165
// CHECK: } // end sil function 'dont_replace_returned_embedded_archetype'

0 commit comments

Comments
 (0)