Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions SwiftCompilerSources/Sources/AST/Type.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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() }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer we just fixed this with the right abstractions. You can get this from the conformance of Self to the protocol, stored in the init_existential instruction.

guard type.isExistential || type.isRootExistentialArchetype,
let concreteFormalType = getConcreteTypeOfExistential()
else {
return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<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 }),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this a precondition?

substitutionMap.replacementTypes.allSatisfy({ $0.isRootExistentialArchetype || !$0.hasLocalArchetype })
else {
return false
}
Expand All @@ -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) ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't you handle all the cases by transforming the type recursively?

// case 3. the argument has nothing to do with the existential archetype (or any other local archetype)
!type.hasLocalArchetype
}
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/ASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions include/swift/AST/ASTBridgingImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,10 @@ BridgedASTType BridgedASTType::getStaticTypeOfDynamicSelf() const {
return {unbridged()->getAs<swift::DynamicSelfType>()->getSelfType().getPointer()};
}

BridgedASTType BridgedASTType::getInterfaceTypeOfArchetype() const {
return {unbridged()->getAs<swift::ArchetypeType>()->getInterfaceType().getPointer()};
}

BridgedASTType BridgedASTType::getSuperClassType() const {
return {unbridged()->getSuperclass().getPointer()};
}
Expand Down
34 changes: 34 additions & 0 deletions test/SILOptimizer/simplify_alloc_stack.sil
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
32 changes: 32 additions & 0 deletions test/SILOptimizer/simplify_apply.sil
Original file line number Diff line number Diff line change
Expand Up @@ -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 :
Expand Down Expand Up @@ -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>

Expand Down Expand Up @@ -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'
Expand Down