mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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
This commit is contained in:
@@ -179,7 +179,8 @@ private extension AllocStackInst {
|
||||
/// use %3
|
||||
/// ```
|
||||
func optimizeExistential(_ context: SimplifyContext) -> Bool {
|
||||
guard type.isExistential || type.isExistentialArchetype,
|
||||
// TODO: support non-root existential archetypes
|
||||
guard type.isExistential || type.isRootExistentialArchetype,
|
||||
let concreteFormalType = getConcreteTypeOfExistential()
|
||||
else {
|
||||
return false
|
||||
|
||||
@@ -170,8 +170,9 @@ private extension FullApplySite {
|
||||
// Make sure that existential archetype _is_ a replacement type and not e.g. _contained_ in a
|
||||
// replacement type, like
|
||||
// apply %1<Array<@opened("...")>()
|
||||
guard substitutionMap.replacementTypes.contains(where: { $0.isExistentialArchetype }),
|
||||
substitutionMap.replacementTypes.allSatisfy({ $0.isExistentialArchetype || !$0.hasLocalArchetype })
|
||||
// TODO: support non-root existential archetypes
|
||||
guard substitutionMap.replacementTypes.contains(where: { $0.isRootExistentialArchetype }),
|
||||
substitutionMap.replacementTypes.allSatisfy({ $0.isRootExistentialArchetype || !$0.hasLocalArchetype })
|
||||
else {
|
||||
return false
|
||||
}
|
||||
@@ -191,9 +192,9 @@ private extension FullApplySite {
|
||||
let type = value.type
|
||||
// Allow three cases:
|
||||
// case 1. the argument _is_ the existential archetype
|
||||
return type.isExistentialArchetype ||
|
||||
return type.isRootExistentialArchetype ||
|
||||
// case 2. the argument _is_ a metatype of the existential archetype
|
||||
(type.isMetatype && type.canonicalType.instanceTypeOfMetatype.isExistentialArchetype) ||
|
||||
(type.isMetatype && type.canonicalType.instanceTypeOfMetatype.isRootExistentialArchetype) ||
|
||||
// case 3. the argument has nothing to do with the existential archetype (or any other local archetype)
|
||||
!type.hasLocalArchetype
|
||||
}
|
||||
|
||||
@@ -10,11 +10,27 @@ public struct S {}
|
||||
protocol P {
|
||||
}
|
||||
|
||||
protocol Q {
|
||||
associatedtype A
|
||||
}
|
||||
|
||||
public class C2: P {}
|
||||
|
||||
public struct T: P {
|
||||
let c: C
|
||||
let s: S
|
||||
|
||||
struct A {
|
||||
var y: String
|
||||
}
|
||||
}
|
||||
|
||||
public struct U: Q {
|
||||
let s: String
|
||||
|
||||
struct A {
|
||||
var y: String
|
||||
}
|
||||
}
|
||||
|
||||
public struct T1: P {
|
||||
@@ -235,6 +251,24 @@ bb0(%0 : @owned $T):
|
||||
return %r
|
||||
}
|
||||
|
||||
// TODO: we don't support dependent existential archetypes, yet. Once we do, change this test case.
|
||||
// CHECK-LABEL: sil [ossa] @dont_replace_dependent_archetype :
|
||||
// CHECK: alloc_stack {{.*}}@opened
|
||||
// CHECK: } // end sil function 'dont_replace_dependent_archetype'
|
||||
sil [ossa] @dont_replace_dependent_archetype : $@convention(thin) (@owned U.A) -> () {
|
||||
bb0(%0 : @owned $U.A):
|
||||
%1 = metatype $@thick U.Type
|
||||
%2 = init_existential_metatype %1, $@thick Q.Type
|
||||
%3 = open_existential_metatype %2 to $@thick (@opened("82105EE0-DCB0-11E5-865D-C8E0EB309914", Q) Self).Type
|
||||
%4 = alloc_stack $(@opened("82105EE0-DCB0-11E5-865D-C8E0EB309914", Q) Self).A
|
||||
%5 = unchecked_addr_cast %4 to $*U.A
|
||||
store %0 to [init] %5
|
||||
destroy_addr %4
|
||||
dealloc_stack %4
|
||||
%r = tuple ()
|
||||
return %r
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @replace_existential_with_concrete_type1 :
|
||||
// CHECK: [[S:%.*]] = alloc_stack $T
|
||||
// CHECK-NOT: init_existential_addr
|
||||
|
||||
@@ -26,6 +26,20 @@ struct GenS<T> {
|
||||
var x: Int
|
||||
}
|
||||
|
||||
protocol P2 {
|
||||
associatedtype A: Q
|
||||
}
|
||||
|
||||
protocol Q {
|
||||
}
|
||||
|
||||
public struct S2: P2 {
|
||||
var x: String
|
||||
struct A: Q {
|
||||
var y: String
|
||||
}
|
||||
}
|
||||
|
||||
sil @cl : $@convention(thin) () -> Int
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @thick_to_thin :
|
||||
@@ -60,6 +74,7 @@ sil_vtable Bar {
|
||||
}
|
||||
|
||||
sil @createit : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type, Int) -> @out τ_0_0
|
||||
sil @create2 : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (Int) -> @out τ_0_0
|
||||
sil @useGenS : $@convention(thin) <τ_0_0 where τ_0_0 : P> (GenS<τ_0_0>) -> ()
|
||||
sil @returnGenS : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> GenS<τ_0_0>
|
||||
|
||||
@@ -124,6 +139,22 @@ bb0(%0 : $Int):
|
||||
return %11
|
||||
}
|
||||
|
||||
// TODO: we don't support dependent existential archetypes, yet. Once we do, change this test case.
|
||||
// CHECK-LABEL: sil [ossa] @dont_replace_dependent_archetype :
|
||||
// CHECK: apply %{{[0-9]+}}<@opened
|
||||
// CHECK: } // end sil function 'dont_replace_dependent_archetype'
|
||||
sil [ossa] @dont_replace_dependent_archetype : $@convention(thin) (Int) -> @out any Q {
|
||||
bb0(%0 : $*any Q, %1 : $Int):
|
||||
%2 = metatype $@thick S2.Type
|
||||
%3 = init_existential_metatype %2, $@thick any P2.Type
|
||||
%4 = open_existential_metatype %3 to $@thick (@opened("0FC03D78-E9DB-11EF-B47C-0EA13E3AABB4", any P2) Self).Type
|
||||
%6 = function_ref @create2 : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (Int) -> @out τ_0_0
|
||||
%7 = init_existential_addr %0, $(@opened("0FC03D78-E9DB-11EF-B47C-0EA13E3AABB4", any P2) Self).A
|
||||
%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
|
||||
%11 = tuple ()
|
||||
return %11
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @dont_replace_returned_embedded_archetype :
|
||||
// CHECK: apply %{{[0-9]+}}<@opened
|
||||
// CHECK: } // end sil function 'dont_replace_returned_embedded_archetype'
|
||||
|
||||
Reference in New Issue
Block a user