Files
swift-mirror/test/SILGen/mangling_retroactive.swift
John McCall 7095953f84 Fix the demangling of dependent protocol conformance refs.
When mangling a dependent protocol conformance ref, the mangler currently uses `0_` to mean an unknown index and `N_` to mean the index `N - 1`. Unfortunately, this is somewhat confused: `0_` is actually the mangling for index 1, and index 0 is supposed to be mangled as just `_`, so true indexes are actually offset by 2. So the first thing to do here is to clarify what's going on throughout the mangler, demangler, and ABI documentation.

Also, the demangler attempts to produce a `DependentProtocolConformance*` node with the appropriate child nodes and an optional index payload. Unfortunately, demangle nodes cannot have both children and a value payload, so whenever it creates a node with an index payload, the demangler will assert.  It does this whenever the mangled index is not 0; since (per above) the mangler always produces a non-zero mangled index in this production, the demangler will always assert when processing these. So clearly this is well-tested code, since +asserts builds will always trigger the demangler when mangling a name in the first place.  To fix this, we need to make the index a child of the mangling node instead of its payload; at the same time, we can make it store the semantically correct index value and just introduce a new `UnknownIndex` node to handle the `0_` case.  This is easy because all current clients ignore this information.

Finally, due to an apparent copy-and-paste error, the demangler attempts to produce a `DependentProtocolConformanceRoot` node for associated protocol conformances; this is easily resolved.

This fixes the crash in SR-10926 (rdar://51710424).  The obscurity of this crash --- which originally made us think it might be related to Error self-conformance --- is because it is only triggered when a function signature takes advantage of a concrete-but-dependent retroactive conformance, which (to be both concrete and dependent) must furthermore be conditional.  Testing the other cases besides a root conformance requires an even more obscure testcase.
2019-07-09 17:25:44 -04:00

107 lines
4.9 KiB
Swift

// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/RetroactiveA.swift
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/RetroactiveB.swift
// RUN: %target-swift-emit-silgen -I %t %s | %FileCheck %s
import RetroactiveA
import RetroactiveB
struct Z<T: P, U: Hashable, V: Q> { }
extension X: P { } // retroactive
extension Y: Q { } // retroactive
// CHECK: sil hidden [ossa] @$s20mangling_retroactive5test0yyAA1ZVy12RetroactiveB1XVSiAE1YVAG0D1A1PAAyHCg_AiJ1QAAyHCg1_GF
func test0(_: Z<X, Int, Y>) { }
struct Z2<T: P> {
struct Inner<V: Q> { }
}
// CHECK: sil hidden [ossa] @$s20mangling_retroactive5test1yyAA2Z2V5InnerVy12RetroactiveB1XV_AG1YVAI0F1A1PAAyHCg_AkL1QAAyHCg0_GF
func test1(_: Z2<X>.Inner<Y>) { }
extension X: Hashable {
public static func ==(lhs: X, rhs: X) -> Bool { return true }
public func hash(into hasher: inout Hasher) { }
}
extension Y: Hashable {
public static func ==(lhs: Y, rhs: Y) -> Bool { return true }
public func hash(into hasher: inout Hasher) { }
}
extension Z: Equatable where T: Hashable, V: Equatable {
static func ==(lhs: Z, rhs: Z) -> Bool { return true }
}
struct RequiresEquatable<T: Equatable> { }
// Conditional requirement involves retroactive conformances.
// CHECK: sil hidden [ossa] @$s20mangling_retroactive5test2yyAA17RequiresEquatableVyAA1ZVy12RetroactiveB1XVSiAG1YVAI0F1A1PAAyHCg_AkL1QAAyHCg1_GAOSQHPAISHAAyHC_AKSQAAyHCHCg_GF
func test2(_: RequiresEquatable<Z<X, Int, Y>>) { }
struct UnconditionallyP<T: Q>: P {}
struct RequiresP<T: P> {}
// RequiresP uses a non-retroactive conformance for its generic param
// UnconditionallyP, even though UnconditionallyP's generic param uses a
// retroactive conformance to conform to Q.
func rdar46735592(_: RequiresP<UnconditionallyP<Y>>) { }
// CHECK: sil hidden [ossa] @$s20mangling_retroactive12rdar46735592yyAA9RequiresPVyAA16UnconditionallyPVy12RetroactiveB1YVAI0F1A1QAAyHCg_GGF
struct QImpl: Q {}
struct ConditionallyP<T> {}
extension ConditionallyP: P where T: Q {}
func useConditionallyP(_: RequiresP<ConditionallyP<QImpl>>) {}
func useConditionallyP_retroactive(_: RequiresP<ConditionallyP<Y>>) {}
// CHECK: sil hidden [ossa] @$s20mangling_retroactive17useConditionallyPyyAA9RequiresPVyAA0D1PVyAA5QImplVGGF
// CHECK: sil hidden [ossa] @$s20mangling_retroactive018useConditionallyP_B0yyAA9RequiresPVyAA0D1PVy12RetroactiveB1YVGAJ0F1A1PHPAiK1QAAyHC_HCg_GF
protocol Wrapper {
associatedtype Wrapped
}
struct WrapperImpl<Wrapped>: Wrapper {}
struct IndirectlyConditionallyP<T: Wrapper> {}
extension IndirectlyConditionallyP: P where T.Wrapped: Q {}
func useIndirectlyConditionallyP(_: RequiresP<IndirectlyConditionallyP<WrapperImpl<QImpl>>>) {}
func useIndirectlyConditionallyP_retroactive(_: RequiresP<IndirectlyConditionallyP<WrapperImpl<Y>>>) {}
// CHECK: sil hidden [ossa] @$s20mangling_retroactive27useIndirectlyConditionallyPyyAA9RequiresPVyAA0dE1PVyAA11WrapperImplVyAA5QImplVGGGF
// CHECK: sil hidden [ossa] @$s20mangling_retroactive028useIndirectlyConditionallyP_B0yyAA9RequiresPVyAA0dE1PVyAA11WrapperImplVy12RetroactiveB1YVGGAM0I1A1PHPAkN1QAAyHC_HCg_GF
struct IndirectlyConditionallyP2<T> {}
extension IndirectlyConditionallyP2: P where T: Wrapper, T.Wrapped: Q {}
func useIndirectlyConditionallyP2(_: RequiresP<IndirectlyConditionallyP<WrapperImpl<QImpl>>>) {}
func useIndirectlyConditionallyP2_retroactive(_: RequiresP<IndirectlyConditionallyP<WrapperImpl<Y>>>) {}
// CHECK: sil hidden [ossa] @$s20mangling_retroactive28useIndirectlyConditionallyP2yyAA9RequiresPVyAA0dE1PVyAA11WrapperImplVyAA5QImplVGGGF
// CHECK: sil hidden [ossa] @$s20mangling_retroactive029useIndirectlyConditionallyP2_B0yyAA9RequiresPVyAA0dE1PVyAA11WrapperImplVy12RetroactiveB1YVGGAM0J1A1PHPAkN1QAAyHC_HCg_GF
protocol NonRetroactive {}
extension Y: NonRetroactive {}
struct ConditionallyP2<T> {}
extension ConditionallyP2: P where T: Q, T: NonRetroactive {}
func useConditionallyP2(_: RequiresP<ConditionallyP2<Y>>) {}
// CHECK: sil hidden [ossa] @$s20mangling_retroactive18useConditionallyP2yyAA9RequiresPVyAA0dE0Vy12RetroactiveB1YVGAJ0G1A1PHPAiK1QAAyHC_AiA03NonG0HpyHCHCg_GF
struct RequiresError<T> where T: Error { }
extension ExternalGeneric: Error where Argument: Error { }
func useRequiresError(_: RequiresError<ExternalGeneric<Error>>) {}
// CHECK: sil hidden [ossa] @$s20mangling_retroactive16useRequiresErroryyAA0dE0Vy12RetroactiveB15ExternalGenericVys0E0_pGAIsAhAsAH_psAHHPyHC_HCg_GF
// SR-10926
protocol OurBaseProtocol: P {
associatedtype Assoc: P
}
protocol OurDerivedProtocol: OurBaseProtocol {}
extension AnotherExternalGeneric: P where Argument: P {}
enum OurType<Value: P> {
case value(Value)
}
func useDependentConformances<T: OurDerivedProtocol>(_: T.Type) -> OurType<AnotherExternalGeneric<T.Assoc>> {}
// CHECK: sil hidden [ossa] @$s20mangling_retroactive24useDependentConformancesyAA7OurTypeOy12RetroactiveB22AnotherExternalGenericVy5AssocQzGAJ0H1A1PAAxAA0F15DerivedProtocolHD1_AA0f4BaseN0HI1_AikLHA2__HCg_GxmAaMRzlF