diff --git a/SwiftCompilerSources/Sources/AST/Type.swift b/SwiftCompilerSources/Sources/AST/Type.swift index 2a99f81686d09..c193387800f1a 100644 --- a/SwiftCompilerSources/Sources/AST/Type.swift +++ b/SwiftCompilerSources/Sources/AST/Type.swift @@ -50,6 +50,8 @@ public struct Type: TypeProperties, CustomStringConvertible, NoReflectionChildre public var staticTypeOfDynamicSelf: Type { Type(bridged: bridged.getStaticTypeOfDynamicSelf()) } + public var interfaceTypeOfArchetype: Type { Type(bridged: bridged.getInterfaceTypeOfArchetype()) } + public var superClassType: Type? { precondition(isClass) let bridgedSuperClassTy = bridged.getSuperClassType() @@ -134,6 +136,8 @@ extension TypeProperties { public var isArchetype: Bool { rawType.bridged.isArchetype() } public var isExistentialArchetype: Bool { rawType.bridged.isExistentialArchetype() } public var isExistentialArchetypeWithError: Bool { rawType.bridged.isExistentialArchetypeWithError() } + public var isRootArchetype: Bool { rawType.interfaceTypeOfArchetype.isGenericTypeParameter } + public var isRootExistentialArchetype: Bool { isExistentialArchetype && isRootArchetype } public var isExistential: Bool { rawType.bridged.isExistential() } public var isClassExistential: Bool { rawType.bridged.isClassExistential() } public var isGenericTypeParameter: Bool { rawType.bridged.isGenericTypeParam() } diff --git a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyAllocStack.swift b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyAllocStack.swift index 295c8bec7f3b4..4af01ed30b8a7 100644 --- a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyAllocStack.swift +++ b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyAllocStack.swift @@ -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 diff --git a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift index 71e403e70a432..5755f8b998d01 100644 --- a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift +++ b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift @@ -216,8 +216,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() - 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 } @@ -237,9 +238,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 } diff --git a/include/swift/AST/ASTBridging.h b/include/swift/AST/ASTBridging.h index 4e64241bdf7d4..99f9d05e0eef3 100644 --- a/include/swift/AST/ASTBridging.h +++ b/include/swift/AST/ASTBridging.h @@ -3009,6 +3009,7 @@ struct BridgedASTType { SWIFT_IMPORT_UNSAFE BRIDGED_INLINE OptionalBridgedDeclObj getAnyNominal() const; SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getInstanceTypeOfMetatype() const; SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getStaticTypeOfDynamicSelf() const; + SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getInterfaceTypeOfArchetype() const; SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getSuperClassType() const; BRIDGED_INLINE MetatypeRepresentation getRepresentationOfMetatype() const; BRIDGED_INLINE BridgedOptionalInt getValueOfIntegerType() const; diff --git a/include/swift/AST/ASTBridgingImpl.h b/include/swift/AST/ASTBridgingImpl.h index 06aed90209ee8..3d8d55b673c87 100644 --- a/include/swift/AST/ASTBridgingImpl.h +++ b/include/swift/AST/ASTBridgingImpl.h @@ -575,6 +575,10 @@ BridgedASTType BridgedASTType::getStaticTypeOfDynamicSelf() const { return {unbridged()->getAs()->getSelfType().getPointer()}; } +BridgedASTType BridgedASTType::getInterfaceTypeOfArchetype() const { + return {unbridged()->getAs()->getInterfaceType().getPointer()}; +} + BridgedASTType BridgedASTType::getSuperClassType() const { return {unbridged()->getSuperclass().getPointer()}; } diff --git a/test/SILOptimizer/simplify_alloc_stack.sil b/test/SILOptimizer/simplify_alloc_stack.sil index 9a5e4b5e14367..d1623d23cef60 100644 --- a/test/SILOptimizer/simplify_alloc_stack.sil +++ b/test/SILOptimizer/simplify_alloc_stack.sil @@ -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 diff --git a/test/SILOptimizer/simplify_apply.sil b/test/SILOptimizer/simplify_apply.sil index a5115f9802e55..fb123080fc4ec 100644 --- a/test/SILOptimizer/simplify_apply.sil +++ b/test/SILOptimizer/simplify_apply.sil @@ -30,6 +30,21 @@ enum E: String { case a, b, c, d, e } +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 : @@ -64,6 +79,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> @@ -128,6 +144,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'