Files
swift-mirror/test/stdlib/Inputs/KeyPathMultiModule_b.swift
Joe Groff 02e1f2ea15 IRGen: Fix key path generic environment marshalling for external property descriptors.
The layout of a computed key path component carries an argument buffer for captures, which has
the following layout:

```
---
captured values (subscript indices)
---
generic arguments
---
```

When we reference an externally-defined public property or subscript from a key path, and the
external declaration has a property descriptor, then the generic arguments for the external
declaration get appended to the end of this buffer, giving:

```
---
captured values (subscript indices)
---
generic arguments
---
external property's generic arguments
---
```

The convention for key path accessors to bind their generic environment is thus to unpack them
from the end of the argument buffer, so that the external keypath's accessors can find the
arguments to bind the external generic environment while still allowing the enclosing key path
to save the original captured generic environment (which may be necessary to capture the
appropriate conditional and/or retroactive `Equatable` and `Hashable` conformances for
subscript indices).

However, our code generation for binding the generic arguments out of the argument buffer
contained a flawed optimization: for a property, we know there are never any captured values,
so I had assumed that the generic parameters could always be bound from the beginning of the
argument buffer, assuming that the generic parameters make up the totality of the buffer. This
falls over for external property descriptor references when the key path itself captures a
generic environment, since the external property's expected generic environment appears after
the key path's original generic environment. We can fix this by removing the conditional
entirely, and always adjusting the offset we load the generic environment from to look at the
end of the buffer. Fixes rdar://125886333.
2024-04-25 10:36:13 -07:00

346 lines
7.8 KiB
Swift

import StdlibUnittest
// rdar://125886333
public struct GenericExternalKeyPathTest<E> {
public private(set) var property: String {
get {
return "\(E.self)"
}
set {
}
}
public init() {}
}
public struct A {
public var x: Int { return 0 }
// NB: These declarations intentionally do not constrain the index type
// to be Hashable, to ensure that we get the Hashable conformance from
// the context where the key path was formed for equality while using the
// property descriptor's accessors.
public subscript<T>(withGeneric index: T) -> T {
return index
}
public private(set) subscript<T>(withGenericPrivateSet index: T) -> T {
get {
return index
}
set { }
}
public subscript<T>(withGenericSettable index: T) -> T {
get {
return index
}
set { }
}
public var storedA: B<Int>
public private(set) var storedB: Double
public var y: Int {
get { return 0 }
set { }
}
public private(set) var z: Int {
get { return 0 }
set { }
}
public internal(set) var w: Int {
get { return 0 }
set { }
}
public fileprivate(set) var v: Int {
get { return 0 }
set { }
}
public let immutable: Int = 1738
}
public struct B<U> {
public var x: Int { return 0 }
public var y: Int {
get { return 0 }
set { }
}
public private(set) var z: Int {
get { return 0 }
set { }
}
public subscript(withInt i: Int) -> Int {
return i
}
// NB: These declarations intentionally do not constrain the index type
// to be Hashable, to ensure that we get the Hashable conformance from
// the context where the key path was formed for equality while using the
// property descriptor's accessors.
public subscript<T>(withGeneric i: T) -> T {
return i
}
public private(set) subscript<T>(withGenericPrivateSet index: T) -> T {
get {
return index
}
set { }
}
public subscript<T>(withGenericSettable index: T) -> T {
get {
return index
}
set { }
}
public var storedA: U
public internal(set) var storedB: U
}
public func A_x_keypath() -> KeyPath<A, Int> {
return \A.x
}
public func A_y_keypath() -> KeyPath<A, Int> {
return \A.y
}
public func A_z_keypath() -> KeyPath<A, Int> {
return \A.z
}
public func A_w_keypath() -> KeyPath<A, Int> {
return \A.w
}
public func A_v_keypath() -> KeyPath<A, Int> {
return \A.v
}
public func A_immutable_keypath() -> KeyPath<A, Int> {
return \A.immutable
}
public func A_subscript_withGeneric_keypath<T: Hashable>(index: T)
-> KeyPath<A, T> {
return \A.[withGeneric: index]
}
public func A_subscript_withGenericSettable_keypath<T: Hashable>(index: T)
-> KeyPath<A, T> {
return \A.[withGenericSettable: index]
}
public func A_subscript_withGenericPrivateSet_keypath<T: Hashable>(index: T)
-> KeyPath<A, T> {
return \A.[withGenericPrivateSet: index]
}
public func A_subscript_withGeneric_butt_keypath()
-> KeyPath<A, String> {
return \A.[withGeneric: "pomeranian's big butt"]
}
public func B_subscript_withInt_keypath<T>(_: T.Type, index: Int)
-> KeyPath<B<T>, Int> {
return \B<T>.[withInt: index]
}
public func B_Double_subscript_withInt_0_keypath()
-> KeyPath<B<Double>, Int> {
return \B<Double>.[withInt: 0]
}
public func B_subscript_withGeneric_keypath<T, U: Hashable>(
_: T.Type, index: U
) -> KeyPath<B<T>, U> {
return \B<T>.[withGeneric: index]
}
public func B_subscript_withGenericSettable_keypath<T, U: Hashable>(
_: T.Type, index: U
) -> KeyPath<B<T>, U> {
return \B<T>.[withGenericSettable: index]
}
public func B_subscript_withGenericPrivateSet_keypath<T, U: Hashable>(
_: T.Type, index: U
) -> KeyPath<B<T>, U> {
return \B<T>.[withGenericPrivateSet: index]
}
public func B_Double_subscript_withGeneric_butt_keypath()
-> KeyPath<B<Double>, String> {
return \B<Double>.[withGeneric: "Never is the universal butt type"]
}
public func A_storedA_keypath() -> KeyPath<A, B<Int>> {
return \A.storedA
}
public func A_storedA_storedB_keypath() -> KeyPath<A, Int> {
return \A.storedA.storedB
}
public func A_storedB_keypath() -> KeyPath<A, Double> {
return \A.storedB
}
public func B_x_keypath<T>(_: T.Type) -> KeyPath<B<T>, Int> {
return \B<T>.x
}
public func B_y_keypath<T>(_: T.Type) -> KeyPath<B<T>, Int> {
return \B<T>.y
}
public func B_z_keypath<T>(_: T.Type) -> KeyPath<B<T>, Int> {
return \B<T>.z
}
public func B_Int_x_keypath() -> KeyPath<B<Int>, Int> {
return \B<Int>.x
}
public func B_Int_y_keypath() -> KeyPath<B<Int>, Int> {
return \B<Int>.y
}
public func B_Int_z_keypath() -> KeyPath<B<Int>, Int> {
return \B<Int>.z
}
public func B_storedA_keypath<T>(_: T.Type) -> KeyPath<B<T>, T> {
return \B<T>.storedA
}
public func B_storedB_keypath<T>(_: T.Type) -> KeyPath<B<T>, T> {
return \B<T>.storedB
}
public func B_Int_storedA_keypath() -> KeyPath<B<Int>, Int> {
return \B<Int>.storedA
}
public func B_Int_storedB_keypath() -> KeyPath<B<Int>, Int> {
return \B<Int>.storedB
}
open class ResilientRoot {
open var storedA = "a"
open var storedB = "b"
public let storedLet = "c"
open var virtual: String {
get { return "foo" }
set { }
}
open var virtualRO: String {
get { return "foo" }
}
final public var final: String {
get { return "foo" }
set { }
}
}
open class ResilientSub: ResilientRoot {
open var storedC = "c"
override open var virtual: String {
get { return "bar" }
set { }
}
open var sub: String {
get { return "bar" }
set { }
}
open var subRO: String {
get { return "foo" }
}
}
public func ResilientRoot_storedA_keypath() -> KeyPath<ResilientRoot, String> {
return \ResilientRoot.storedA
}
public func ResilientRoot_storedB_keypath() -> KeyPath<ResilientRoot, String> {
return \ResilientRoot.storedB
}
public func ResilientRoot_storedLet_keypath() -> KeyPath<ResilientRoot, String> {
return \ResilientRoot.storedLet
}
public func ResilientRoot_virtual_keypath() -> KeyPath<ResilientRoot, String> {
return \ResilientRoot.virtual
}
public func ResilientRoot_virtualRO_keypath() -> KeyPath<ResilientRoot, String> {
return \ResilientRoot.virtualRO
}
public func ResilientRoot_final_keypath() -> KeyPath<ResilientRoot, String> {
return \ResilientRoot.final
}
public func ResilientSub_storedA_keypath() -> KeyPath<ResilientSub, String> {
return \ResilientSub.storedA
}
public func ResilientSub_storedB_keypath() -> KeyPath<ResilientSub, String> {
return \ResilientSub.storedB
}
public func ResilientSub_storedC_keypath() -> KeyPath<ResilientSub, String> {
return \ResilientSub.storedC
}
public func ResilientSub_virtual_keypath() -> KeyPath<ResilientSub, String> {
return \ResilientSub.virtual
}
public func ResilientSub_virtualRO_keypath() -> KeyPath<ResilientSub, String> {
return \ResilientSub.virtualRO
}
public func ResilientSub_final_keypath() -> KeyPath<ResilientSub, String> {
return \ResilientSub.final
}
public func ResilientSub_sub_keypath() -> KeyPath<ResilientSub, String> {
return \ResilientSub.sub
}
public func ResilientSub_subRO_keypath() -> KeyPath<ResilientSub, String> {
return \ResilientSub.subRO
}
public protocol ResilientRootProto {
var root: String { get }
}
public protocol ResilientSubProto: ResilientRootProto {
var sub: String { get }
}
extension Int: ResilientSubProto {
public var root: String { return "root" }
public var sub: String { return "sub" }
}
public func ResilientRootProto_root_keypath<T: ResilientRootProto>(_: T.Type) -> KeyPath<T, String> {
return \T.root
}
public func ResilientSubProto_sub_keypath<T: ResilientSubProto>(_: T.Type) -> KeyPath<T, String> {
return \T.sub
}
extension Int {
public var appendTest: Int { return self }
}
extension String {
public var appendTest: String { return self }
}
extension LifetimeTracked {
public var appendTest: LifetimeTracked { return self }
}