Slide 1

Slide 1 text

Swift6ͷprotocol Θ͍Θ͍swiftc #36 @omochimetaru 1

Slide 2

Slide 2 text

protocolֵ໋͕དྷΔ • SE-0309: Unlock existentials for all protocols • SE-0328: Structural opaque result types • SE-0335: Introduce existential any • SE-0341: Opaque Parameter Declarations • SE-0346: Lightweight same-type requirements for primary associated types • SE-0352: Implicitly Opened Existentials • SE-0353: Constrained Existential Types 2

Slide 3

Slide 3 text

• SE-0309: Unlock existentials for all protocols1 • SE-0328: Structural opaque result types2 • SE-0335: Introduce existential any3 • SE-0341: Opaque Parameter Declarations4 • SE-0346: Lightweight same-type requirements for primary associated types5 • SE-0352: Implicitly Opened Existentials6 • SE-0353: Constrained Existential Types7 7 https://github.com/apple/swift-evolution/blob/main/proposals/0353-constrained-existential-types.md 6 https://github.com/apple/swift-evolution/blob/main/proposals/0352-implicit-open-existentials.md 5 https://github.com/apple/swift-evolution/blob/main/proposals/0346-light-weight-same-type-syntax.md 4 https://github.com/apple/swift-evolution/blob/main/proposals/0341-opaque-parameters.md 3 https://github.com/apple/swift-evolution/blob/main/proposals/0335-existential-any.md 2 https://github.com/apple/swift-evolution/blob/main/proposals/0328-structural-opaque-result-types.md 1 https://github.com/apple/swift-evolution/blob/main/proposals/0309-unlock-existential-types-for-all- protocols.md 3

Slide 4

Slide 4 text

ࠓ೔ͷ໨ඪ • ৽͍͠ݴޠػೳͷจ๏ɺҙຯɺ࣮૷Λཧղ͢Δ 4

Slide 5

Slide 5 text

࿩ͷྲྀΕ • ྺ࢙ • طଘػೳͷ෮श • ৽ػೳͷ঺հ 5

Slide 6

Slide 6 text

ྺ࢙ 6

Slide 7

Slide 7 text

Generics in Swift8 SwiftͷδΣωϦΫεͷॳظઃܭॻɻ Self Type, Associated Type, Explicit Conformance, Retroactive Conformance, Constraints, Existential ͳͲͷओཁͳಛ௃͕ఏএ͞Ε͍ͯΔɻ 8 https://github.com/apple/swift/blob/main/docs/Generics.rst 7

Slide 8

Slide 8 text

Generics Manifesto9 SwiftͷδΣωϦΫεͷকདྷͷํ޲ੑΛࣔ͢จॻɻ Swift 3ͷࠒʹެ։͞Εɺ͔ͳΓઌ୺తͳػೳʹ΋ݴٴ͍ͯ͠ Δɻ Swift 4Ͱܰඍͳ΋ͷ͸࣮ݱ͞Ε͕ͨɺ ߴ౓ͳ΋ͷ͸ Swift 5 ࣌୅ʹ͋·Γਐḿ͸ແ͔ͬͨɻ 9 https://github.com/apple/swift/blob/main/docs/GenericsManifesto.md 8

Slide 9

Slide 9 text

Improving the UI of generics10 Swift͕ࠓޙूத͍ͯ͘͠δΣωϦΫεͷํ޲ੑΛࣔ͢ϑΥʔϥ Ϝͷॻ͖ࠐΈɻ Swift 5ͷࠒʹެ։͞ΕɺϚχϑΣετͷҰ෦ͷ಺༰Λ۷ΓԼ͛ ͍ͯΔɻ Swift 6ʹ޲͚ͯ͜͜Ͱݴٴ͞Εͨ಺༰͕ಋೖ͞Εͦ͏ɻ 10 https://forums.swift.org/t/improving-the-ui-of-generics/22814 9

Slide 10

Slide 10 text

طଘػೳͷ෮श 10

Slide 11

Slide 11 text

protocolͷػೳ 1. ܕͷػೳΛએݴ͢Δ 2. δΣωϦοΫύϥϝʔλʹ੍໿(Constraint)Λ༩͑Δ 3. ExistentialΛ࡞Δ 11

Slide 12

Slide 12 text

ܕͷػೳΛએݴ͢Δ protocol P { associatedtype A func f(a: A) static func s() -> Self } struct S: P { ... } • P͸ܕ Ͱ͸ͳ͘ ͋͘·Ͱ΋ܕͷػೳͷએݴ 12

Slide 13

Slide 13 text

associated typeͱSelf type Self type͸ػೳ্͸associated typeͱ͍ۙɻ ४ڌ(conform)͢ΔଆͰࣗ਎ΛׂΓ౰ͯΔࣄ͕ڧ͍ΒΕ͍ͯΔ͚ͩɻ protocol P { associatedtype CustomSelf } struct S: P { typealias CustomSelf = S } 13

Slide 14

Slide 14 text

static member ͱ metatype static member͸metatypeʹର͢Δmemberఆٛͱଊ͑ΒΕΔɻ protocol P { associatedtype A static func s(a: A) -> Self } struct S: P { ... } func foo(type: P.Type) { ... } func main() { foo(type: S.self) } 14

Slide 15

Slide 15 text

protocol P { associatedtype A static func s(a: A) -> Self } // ҎԼͷΑ͏ͳؾ࣋ͪ protocol PMetatype { associatedtype A associatedtype P func s(a: A) -> P } 15

Slide 16

Slide 16 text

੍໿Λ༩͑Δ ·੍ͣ໿Λ༩͑ͳ͍৔߹Λ֬ೝ͢Δ func foo(t: T) -> T { ... } • ܕ ʹ͍ͭͯఆٛ͞Εͨؔ਺ 16

Slide 18

Slide 18 text

Value Witness Table11 • ϝλλΠϓ(%swift.type*) ͔Β͸ Value Witness Table ͕औΓग़ͤ Δɻ • δΣωϦοΫͳܕ ͷ஋(value)ʹର͢Δجຊૢ࡞͕ೖͬͨؔ਺ ςʔϒϧɻ • init, copy, destroy, sizeͳͲɻ • ݺͼग़͢ଆ͕ ͷਅͷܕ S ͷϝλλΠϓ(ͱVWT)ΛηοτͰ౉͢ɻ 11 https://github.com/apple/swift/blob/main/include/swift/ABI/ValueWitness.def 18

Slide 19

Slide 19 text

੍໿Λ༩͑Δ func foo(t: P) -> T { ... } • ܕ ͕ P ʹ४ڌ(conform)͢Δͱ͍͏੍໿(constraint)Λ௥ Ճ 19

Slide 21

Slide 21 text

Protocol Witness Table12 • ܕ ͕ P ʹ४ڌ͢ΔͨΊͷૢ࡞͕ೖͬͨؔ਺ςʔϒϧɻ • ͦͷ಺༰͸ P ͷఆٛͱ΄΅ಉ͡ܗʹͳΔɻ • ݺͼग़͢ଆ͕ ͷਅͷܕ S ͷ P ΁ͷPWTΛηοτͰ౉͢ɻ 12 https://github.com/apple/swift/blob/main/docs/ABI/TypeLayout.rst#existential-container-layout 21

Slide 22

Slide 22 text

protocol P { associatedtype A func foo(a: A) static func s() -> Self } struct S: P { typealias A = Int func foo(a: Int) { } static func s() -> S { S() } } 22

Slide 23

Slide 23 text

; protocol witness table for a.S : a.P in a @"$s1a1SVAA1PAAWP" = hidden global [4 x i8*] [ ; protocol conformance descriptor i8* bitcast (%swift.protocol_conformance_descriptor* @"$s1a1SVAA1PAAMc" to i8*), ; A = Swift.Int i8* getelementptr inbounds ( <{ [2 x i8], i8 }>, <{ [2 x i8], i8 }>* @"symbolic Si", i32 0, i32 0, i64 1 ), ; func foo i8* bitcast (void (%TSi*, %T1a1SV*, %swift.type*, i8**)* @"$s1a1SVAA1PA2aDP3fooAAy1AQz_tFTW" to i8*), ; static func s i8* bitcast (void (%T1a1SV*, %swift.type*, %swift.type*, i8**)* @"$s1a1SVAA1PA2aDP1sxyFZTW" to i8*) ], align 8 23

Slide 24

Slide 24 text

associated typeʹ΋੍໿Λ༩͑Δ protocol Q {} protocol P { associatedtype A: Q func foo(a: A) static func s() -> Self } 24

Slide 25

Slide 25 text

; protocol witness table for a.S : a.P in a @"$s1a1SVAA1PAAWP" = hidden global [5 x i8*] [ ; protocol conformance descriptor i8* bitcast (%swift.protocol_conformance_descriptor* @"$s1a1SVAA1PAAMc" to i8*), ; SͷP४ڌʹ͓͚ΔS.AͷQ४ڌͷ৘ใ i8* getelementptr ( i8, i8* getelementptr inbounds ( <{ i8, i8, i32, i8 }>, <{ i8, i8, i32, i8 }>* @"associated conformance 1a1SVAA1PAA1AAaDP_AA1Q", i32 0, i32 0 ), i64 1 ), ; A = Swift.Int i8* getelementptr inbounds (<{ [2 x i8], i8 }>, <{ [2 x i8], i8 }>* @"symbolic Si", i32 0, i32 0, i64 1), ; func foo i8* bitcast (void (%TSi*, %T1a1SV*, %swift.type*, i8**)* @"$s1a1SVAA1PA2aDP3fooAAy1AQz_tFTW" to i8*), ; static func s i8* bitcast (void (%T1a1SV*, %swift.type*, %swift.type*, i8**)* @"$s1a1SVAA1PA2aDP1sxyFZTW" to i8*) ], align 8 25

Slide 26

Slide 26 text

੍໿ͷ·ͱΊ • δΣωϦοΫͳܕʹରͯ͠ߦ͑Δૢ࡞ΛϓϩτίϧͰ੍໿͢ΔࣄͰ એݴ͢Δ • ݺͼग़͢ͱ͖ͷਅͷܕ͸ίϯύΠϧ࣌ʹܾఆ͢Δ • callee͸ɺ஋ΛopaqueͳϙΠϯλɺجຊૢ࡞ͷͨΊͷVWTɺϓϩτ ίϧͱͯ͠ͷૢ࡞ͷͨΊͷPWTΛड͚औΓɺ ͦΕΒͷςʔϒϧͷؔ਺Λ௨ͯ͠஋Λૢ࡞͢Δ • caller͸ɺ౉ͦ͏ͱ͍ͯ͠Δਅͷܕͷઐ༻ͷVWTͱPWTΛҰॹʹ౉͢ 26

Slide 27

Slide 27 text

Existential 27

Slide 28

Slide 28 text

ϓϩτίϧΛܕͱͯ͠࢖͑Δ(?) protocol P { func foo() } func makeFoo() -> P { ... } func callFoo(_ p: P) { ... } func main() { let p: P = makeFoo() callFoo(p) } 28

Slide 29

Slide 29 text

struct S: P {} func makeFoo() -> P { // S Λ P ʹ֨ೲ return S() } func callFoo(_ p: P) { // P ͔Β ΛऔΓग़͢ p.foo() } 29

Slide 30

Slide 30 text

Existential Container12 // ؾ࣋ͪදݱ struct PContainer { var value: T func foo() { value.foo() } } • ! ϓϩτίϧΛܕͱͯ͠࢖͑Δ • " Λอ࣋Ͱ͖ΔίϯςφܕΛ࢖͑Δ 12 https://github.com/apple/swift/blob/main/docs/ABI/TypeLayout.rst#existential-container-layout 30

Slide 31

Slide 31 text

Existential Metatype Container func useMetatype(type: P.Type) {} func callUseMetatype(p: P) { useMetatype(type: type(of: p)) } func main() { useMetatype(type: S.self) callUseMetatype(p: S()) } • P ʹ४ڌ͢Δܕ T ͷϝλλΠϓͷίϯςφ 31

Slide 32

Slide 32 text

Existential Container Metatype func useExistentialContainerMetatype(type: P.Protocol) {} func main() { useExistentialContainerMetatype(type: P.self) } • Existential ContainerͷϝλλΠϓ 32

Slide 33

Slide 33 text

Existentialͷ੍ݶ 33

Slide 34

Slide 34 text

associated type͕͋Δͱ࢖͑ͳ͍ protocol P { associatedtype A } // error: protocol 'P' can only be used as a generic constraint // because it has Self or associated type requirements func useP(p: P) {} 34

Slide 35

Slide 35 text

΋͠࢖͑ͨͱ͢Δͱ໰୊͕ੜ͡Δɻ func useP(p: P) { // P.A͕ίϯύΠϧ࣌ʹܾఆͰ͖ͳ͍ func f(a: P.A) {} } 35

Slide 36

Slide 36 text

AnyܕΛ࢖ͬͯ΋contravariantͳ৔߹ʹ͏·͍͔͘ͳ͍ɻ protocol P { associatedtype A func useA(a: A) } struct S: P { func useA(a: Int) {} } func useP(p: P) { // useA(a: Any) ? p.useA(a: "string") } 36

Slide 37

Slide 37 text

contravariantͳSelf type͕͋Δͱ࢖͑ͳ͍ protocol P { func foo(_ a: Self) } // error: protocol 'P' can only be used as a generic constraint // because it has Self or associated type requirements func useP(p: P) {} 37

Slide 38

Slide 38 text

΋͠࢖͑ͨͱ͢Δͱ໰୊͕ੜ͡Δɻ func makeP() -> P { ... } func useP(p: P) { // pͷਅͷܕͱmakeP͕ฦ͢ਅͷܕ͕ಉҰͱ͸ݶΒͳ͍ p.foo(makeP()) } 38

Slide 39

Slide 39 text

covariantͳSelf type͸େৎ෉ protocol P { func s() -> Self func os() -> Self? func fs() -> () -> Self func ts() -> (Self, Self) func ffs() -> ((Self) -> Void) -> Void } // OK func useFoo(p: P) {} Self = existenal P ͱϥοϓ͢Δ͚ͩ 39

Slide 40

Slide 40 text

Existential ͷ self conformance 40

Slide 41

Slide 41 text

P͸PͰ͸ͳ͍ protocol P {} // error: protocol 'P' as a type cannot // conform to the protocol itself func useGenericP(p: P) {} func useExistentialP(p: P) { useGenericP(p: p) } Pͷexistential͸protocol Pʹ४ڌ͍ͯ͠ͳ͍ 41

Slide 42

Slide 42 text

associated type͕ղܾͰ͖ͳ͍ protocol P { associatedtype A } P.A ͸ਅͷܕʹΑͬͯҟͳΔ 42

Slide 43

Slide 43 text

contravariantͳSelf type͕ղܾͰ͖ͳ͍ protocol P { func foo(p: Self) } Self ͸ਅͷܕʹΑͬͯҟͳΔ 43

Slide 44

Slide 44 text

static member͕࣮૷Ͱ͖ͳ͍ protocol P { static func s() } func main() { // error: static member 's' cannot be used // on protocol metatype 'P.Protocol' P.s() } 44

Slide 45

Slide 45 text

@objc protocol͸ࣗݾ४ڌ͢Δ @objc protocol P { func foo() } func useGenericP(p: T) {} func useExistentialP(p: P) { useGenericP(p: p) } • static member͕ແ͍৔߹ͷΈ • associatedtype͸ͦ΋ͦ΋ېࢭ • Self͸͋ͬͯ΋Α͍(?) 45

Slide 46

Slide 46 text

import Foundation @objc protocol P { // contravariance Self ? func foo(_ p: Self) } @objc class S: NSObject, P { var x: String = "s" func foo(_ s: S) { print("expected: s, actual: \(s.s())") } func s() -> String { x } } @objc class K: NSObject, P { var y: Int = 2 func foo(_ k: K) { print("expected: 2, actual: \(k.k())") } func k() -> Int { y } } func makeSP() -> P { S() } func makeKP() -> P { K() } func useP(p1: T, p2: T) { p1.foo(p2) } // Segmentation fault: 11 useP(p1: makeSP(), p2: makeKP()) 46

Slide 47

Slide 47 text

Swift.Error ͸ࣗݾ४ڌ͢Δ func useGenericError(error: T) {} func useError(error: Error) { useGenericError(error: error) } • ௒ಛผ଴۰ • ϝϯό͸Կ΋ͳ͍ͷͰ໰୊͸ͳ͍ 47

Slide 48

Slide 48 text

Existentialͷopen 48

Slide 49

Slide 49 text

open P ͔Β ΛऔΓग़͢ࣄΛ open ͱݺͿ func callFoo(p: P) { // ͜͜Ͱopen͍ͯ͠Δ p.foo() } 49

Slide 50

Slide 50 text

extensionʹΑΔopen func proc(_ t: T) { print(t) } func useP(p: P) { // error: protocol 'P' as a type cannot // conform to the protocol itself proc(p) } P ͕खݩʹ͋Δ͚Ͳ ͕΄͍͠ࣄ͕͋Δ 50

Slide 51

Slide 51 text

extension P { func callProc() { // let self: proc(self) } } func useP(p: P) { p.callProc() } protocol extensionͷϝιουͷself͸open͞Εͨܕ ʹͳͬ ͍ͯΔɻ 51

Slide 52

Slide 52 text

existentialͷ࣮૷ 52

Slide 53

Slide 53 text

protocol P { func foo() } func useP(p: P) { p.foo() } 53

Slide 54

Slide 54 text

• Opaque Existential Containers12 struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTables[NUM_WITNESS_TABLES]; }; 12 https://github.com/apple/swift/blob/main/docs/ABI/TypeLayout.rst#existential-container-layout 54

Slide 55

Slide 55 text

%T1b1PP = type { [24 x i8], %swift.type*, i8** } %__opaque_existential_type_1 = type { [24 x i8], %swift.type*, i8** } define hidden swiftcc void @"$s1b4useP1pyAA1P_p_tF"( %T1b1PP* noalias nocapture dereferenceable(40) %0 ) #0 { entry: %p.debug = alloca %T1b1PP*, align 8 %1 = bitcast %T1b1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %T1b1PP* %0, %T1b1PP** %p.debug, align 8 %2 = getelementptr inbounds %T1b1PP, %T1b1PP* %0, i32 0, i32 1 %3 = load %swift.type*, %swift.type** %2, align 8 %4 = getelementptr inbounds %T1b1PP, %T1b1PP* %0, i32 0, i32 2 %5 = load i8**, i8*** %4, align 8 %6 = bitcast %T1b1PP* %0 to %__opaque_existential_type_1* %7 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1( %__opaque_existential_type_1* %6, %swift.type* %3 ) #3 %8 = getelementptr inbounds i8*, i8** %5, i32 1 %9 = load i8*, i8** %8, align 8, !invariant.load !22 %10 = bitcast i8* %9 to void (%swift.opaque*, %swift.type*, i8**)* call swiftcc void %10(%swift.opaque* noalias nocapture swiftself %7, %swift.type* %3, i8** %5) ret void } 55

Slide 56

Slide 56 text

ܕͷऔΓग़͠ %T1b1PP = type { [24 x i8], %swift.type*, i8** } %__opaque_existential_type_1 = type { [24 x i8], %swift.type*, i8** } define hidden swiftcc void @"$s1b4useP1pyAA1P_p_tF"( %T1b1PP* noalias nocapture dereferenceable(40) %0 ) #0 { entry: %p.debug = alloca %T1b1PP*, align 8 %1 = bitcast %T1b1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %T1b1PP* %0, %T1b1PP** %p.debug, align 8 %2 = getelementptr inbounds %T1b1PP, %T1b1PP* %0, i32 0, i32 1 %3 = load %swift.type*, %swift.type** %2, align 8 %4 = getelementptr inbounds %T1b1PP, %T1b1PP* %0, i32 0, i32 2 %5 = load i8**, i8*** %4, align 8 %6 = bitcast %T1b1PP* %0 to %__opaque_existential_type_1* %7 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1( %__opaque_existential_type_1* %6, %swift.type* %3 ) #3 %8 = getelementptr inbounds i8*, i8** %5, i32 1 %9 = load i8*, i8** %8, align 8, !invariant.load !22 %10 = bitcast i8* %9 to void (%swift.opaque*, %swift.type*, i8**)* call swiftcc void %10(%swift.opaque* noalias nocapture swiftself %7, %swift.type* %3, i8** %5) ret void } 56

Slide 57

Slide 57 text

PWTͱͦͷதͷؔ਺ͷऔΓग़͠ %T1b1PP = type { [24 x i8], %swift.type*, i8** } %__opaque_existential_type_1 = type { [24 x i8], %swift.type*, i8** } define hidden swiftcc void @"$s1b4useP1pyAA1P_p_tF"( %T1b1PP* noalias nocapture dereferenceable(40) %0 ) #0 { entry: %p.debug = alloca %T1b1PP*, align 8 %1 = bitcast %T1b1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %T1b1PP* %0, %T1b1PP** %p.debug, align 8 %2 = getelementptr inbounds %T1b1PP, %T1b1PP* %0, i32 0, i32 1 %3 = load %swift.type*, %swift.type** %2, align 8 %4 = getelementptr inbounds %T1b1PP, %T1b1PP* %0, i32 0, i32 2 %5 = load i8**, i8*** %4, align 8 %6 = bitcast %T1b1PP* %0 to %__opaque_existential_type_1* %7 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1( %__opaque_existential_type_1* %6, %swift.type* %3 ) #3 %8 = getelementptr inbounds i8*, i8** %5, i32 1 %9 = load i8*, i8** %8, align 8, !invariant.load !22 %10 = bitcast i8* %9 to void (%swift.opaque*, %swift.type*, i8**)* call swiftcc void %10(%swift.opaque* noalias nocapture swiftself %7, %swift.type* %3, i8** %5) ret void } 57

Slide 58

Slide 58 text

஋ͷऔΓग़͠ %T1b1PP = type { [24 x i8], %swift.type*, i8** } %__opaque_existential_type_1 = type { [24 x i8], %swift.type*, i8** } define hidden swiftcc void @"$s1b4useP1pyAA1P_p_tF"( %T1b1PP* noalias nocapture dereferenceable(40) %0 ) #0 { entry: %p.debug = alloca %T1b1PP*, align 8 %1 = bitcast %T1b1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %T1b1PP* %0, %T1b1PP** %p.debug, align 8 %2 = getelementptr inbounds %T1b1PP, %T1b1PP* %0, i32 0, i32 1 %3 = load %swift.type*, %swift.type** %2, align 8 %4 = getelementptr inbounds %T1b1PP, %T1b1PP* %0, i32 0, i32 2 %5 = load i8**, i8*** %4, align 8 %6 = bitcast %T1b1PP* %0 to %__opaque_existential_type_1* %7 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1( %__opaque_existential_type_1* %6, %swift.type* %3 ) #3 %8 = getelementptr inbounds i8*, i8** %5, i32 1 %9 = load i8*, i8** %8, align 8, !invariant.load !22 %10 = bitcast i8* %9 to void (%swift.opaque*, %swift.type*, i8**)* call swiftcc void %10(%swift.opaque* noalias nocapture swiftself %7, %swift.type* %3, i8** %5) ret void } 58

Slide 59

Slide 59 text

औΓग़ͨؔ͠਺ʹɺ஋ɺܕɺPWTΛ౉ͯ͠ݺͼग़͢ %T1b1PP = type { [24 x i8], %swift.type*, i8** } %__opaque_existential_type_1 = type { [24 x i8], %swift.type*, i8** } define hidden swiftcc void @"$s1b4useP1pyAA1P_p_tF"( %T1b1PP* noalias nocapture dereferenceable(40) %0 ) #0 { entry: %p.debug = alloca %T1b1PP*, align 8 %1 = bitcast %T1b1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %T1b1PP* %0, %T1b1PP** %p.debug, align 8 %2 = getelementptr inbounds %T1b1PP, %T1b1PP* %0, i32 0, i32 1 %3 = load %swift.type*, %swift.type** %2, align 8 %4 = getelementptr inbounds %T1b1PP, %T1b1PP* %0, i32 0, i32 2 %5 = load i8**, i8*** %4, align 8 %6 = bitcast %T1b1PP* %0 to %__opaque_existential_type_1* %7 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1( %__opaque_existential_type_1* %6, %swift.type* %3 ) #3 %8 = getelementptr inbounds i8*, i8** %5, i32 1 %9 = load i8*, i8** %8, align 8, !invariant.load !22 %10 = bitcast i8* %9 to void (%swift.opaque*, %swift.type*, i8**)* call swiftcc void %10(%swift.opaque* noalias nocapture swiftself %7, %swift.type* %3, i8** %5) ret void } 59

Slide 60

Slide 60 text

Existentialͷ࣮૷ͷ·ͱΊ • Existential Container͸ɺਅͷ஋ɺͦͷܕɺPWTΛ·ͱΊͨ ΋ͷɻ • PWT͔ΒऔΓग़ͨؔ͠਺Λݺͼग़͢ܗࣜ͸ɺδΣωϦοΫؔ ਺ʹ͓͚Δ ͷૢ࡞ͱશ͘ಉ͡Ͱɺopen͍ͯ͠Δͱݴ ͑Δɻ 60

Slide 61

Slide 61 text

Existentialͷ·ͱΊ • Existential͸ Λอ࣋͢Δίϯςφ • ϝιουݺͼग़͠ʹΑΔopenͰ ΛऔΓग़ͤΔ • associated type, Self type͸varianceͷ໰୊ΛؚΉ • ࣮૷Ͱ͸ɺਅͷ஋ɺͦͷܕɺPWTΛ͍࣋ͬͯͯɺ͜Ε͸ Genericؔ਺Λݺͼग़͢ͱ͖ͷҾ਺ͱಉ͡΋ͷ 61

Slide 62

Slide 62 text

GenericsͱExistential ͷҧ͍ 62

Slide 63

Slide 63 text

Generic Parameter Type͸͋ΔಛఆͷܕΛҙ ຯ͢Δ func foo(t: T) -> T { var u: T = t // NG // u = S() return u } ͸ͦͷίϯςΩετʹ͓͚Δɺ͋ΔಛఆͷܕͰ͋Γɺ ͨͱ࣮͑ߦ࣌ʹͦ͏ͩͬͨͱͯ͠΋ɺܕνΣοΫʹ͓͍ͯ͸ S Ͱ΋ K Ͱ΋ͳ͍ɻ Ҿ਺Ͱ౉ͨ͠ t: T ͱɺͦͷίϐʔͷ u: T ΍ฦΓ஋ͷ T ͸ಉ͡ܕͰ͋Γɺ࣮ߦ࣌ʹ͓͍ͯ΋౉ͨ͠ܕ͕ฦͬͯ͘ Δɻ 63

Slide 64

Slide 64 text

Existential Container͸ಛఆͷܕΛҙຯ͠ͳ͍ func foo(p: P) -> P { var u: P = p // OK u = S() return u } P ͸ Λ֨ೲͰ͖ΔίϯςφͰɺத਎ͷܕ͸ಈతʹมԽ͠͏Δɻ Ҿ਺Ͱ౉ͨ͠ p: P ͔Βίϐʔͨ͠ u: P ʹରͯ͠ɺ طଘͷத਎ͱ͸ແؔ܎ʹ S Λ୅ೖͨ͠ΓɺͦΕΛฦͨ͠ΓͰ͖Δɻ 64

Slide 65

Slide 65 text

Type Erasure 65

Slide 66

Slide 66 text

Type Erasure associated typeͱࣗݾ४ڌʹରԠͨ͠existentialͷΑ͏ͳ΋ͷΛ ࣗ࡞͢Δࣄ͕͋ΓɺType Erasureͱݺ͹ΕΔɻ ඪ४ϥΠϒϥϦͰ͸ AnySequence, AnyHashable, KeyedDecodingContainer ͳͲ͕͋Δɻ ݴޠػೳͰ͸ͳ͘୯ͳΔ࣮૷ύλʔϯͳͷͰ࣮૷͸ׂѪɻ 66

Slide 67

Slide 67 text

Opaque Result Types 67

Slide 68

Slide 68 text

Opaque Result Types Improving the UI of generics ͷ಺༰Λड͚ͯ Swift 5.1 Ͱ࣮૷͞Εͨɻ protocol P { func foo() } struct S: P { func foo() {} } func makeP() -> some P { S() } 68

Slide 69

Slide 69 text

Reverse Generics ORT͸ callee ଆ͕ܾఆ͢Δ Generic Parameter Type ͱݴ͑Δɻ Reverse Genericsͱ͍͏ՍۭͷߏจΛߟ͑Δͱཧղ͠΍͍͢ɻ // ORT func makeP() -> some P { S() } // Reverse Generics func makeP() -> T { S() } 69

Slide 70

Slide 70 text

ར༻ଆͷղऍ protocol P { associatedtype A func a() -> A func useA(a: A) } func main() { let p = makeP() let a = p.a() p.useA(a: a) } ORT͸ExistentialͰ͸ͳ͘GenericsͳͷͰɺassociatedtype͕࢖͑Δɻ 70

Slide 71

Slide 71 text

makePͷݺͼग़͕͠ɺܕύϥϝʔλΛಋೖ͠ɺܾఆ͍ͯ͠Δͱ ߟ͑ΔͱΘ͔Γ΍͍͔͢΋͠Εͳ͍ɻ func main() { // ↑͜ͷTͷਅͷܕ͸ // ↓͜ͷmakeP͕ܾΊΔ let p: T = makeP() let a: T.A = p.a() p.useA(a: a) } 71

Slide 72

Slide 72 text

func main() { let p = makeP() let p2 = makeP() let a = p2.a() p.useA(a: a) } p ͱ p2 ͸ҟͳΔม਺͕ͩɺಉ͡ ʮmakeP ͷฦΓ஋ͷܕʯͳͷ Ͱɺ ಉ͡ܕͰ͋Γɺassociatedtype΋ಉ͡ܕɻ 72

Slide 73

Slide 73 text

ܕύϥϝʔλΛॻ͘ͱ͜͏ଊ͑ΒΕΔɻ func main() { // ↑͜ͷT͸ʮmakePͷฦΓ஋ͷܕʯ let p: T = makeP() let p2: T = makeP() let a: T.A = p2.a() p.useA(a: a) } 73

Slide 74

Slide 74 text

֎ଆʹύϥϝʔλ͕࿐ग़͍ͯ͠Δͷ͕ؾʹͳΔͳΒɺ͜͏ߟ͑ͯ΋ ྑ͍ɻ func main() { func body(p: T) { let p: T = p let p2: T = makeP() let a: T.A = p2.a() p.useA(a: a) } body(p: makeP()) } 74

Slide 75

Slide 75 text

ਅͷܕ͸ͦͷؔ਺͝ͱʹఆ·ΔͷͰɺͨͱ࣮͑ࡍʹ͸ಉ͡ܕʹͳΔͱͯ͠ ΋ɺҟͳΔ some P ͸ผͷܕͱͯ͠ѻΘΕΔɻ func makeP() -> some P { S() } func makeP2() -> some P { S() } func main() { let p = makeP() let p2 = makeP2() let a = p2.a() // error: cannot convert value of type // '(some b.P).A' (associated type of protocol 'P') // to expected argument type // '(some b.P).A' (associated type of protocol 'P') p.useA(a: a) } 75

Slide 76

Slide 76 text

͜Ε΋ύϥϝʔλදࣔ͢Δͱ͙͢Θ͔Δɻ func main() { let p: T1 = makeP() let p2: T2 = makeP2() let a: T2.A = p2.a() // T2.A ͸ T1.A ͱͯ͠౉ͤͳ͍ p.useA(a: a) } 76

Slide 77

Slide 77 text

ORTͷ࣮૷ 77

Slide 78

Slide 78 text

// c.swift public protocol P { func foo() -> Int } struct S: P { func foo() -> Int { 1 } } public func makeP() -> some P { S() } // b.swift import c func main() { let p = makeP() p.foo() } 78

Slide 79

Slide 79 text

define hidden swiftcc void @"$s1b4mainyyF"() #0 { entry: %p.debug = alloca i8*, align 8 %0 = bitcast i8** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1c5makePQryFQOyQo_MD") #7 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !18, !dereferenceable !19 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !18 %6 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %6) %7 = bitcast i8* %6 to %swift.opaque* store i8* %6, i8** %p.debug, align 8 call swiftcc void @"$s1c5makePQryF"(%swift.opaque* noalias nocapture sret(%swift.opaque) %7) %8 = call swiftcc i8** @swift_getOpaqueTypeConformance(i8* undef, %swift.type_descriptor* @"$s1c5makePQryFQOMQ", i64 1) #8 %9 = getelementptr inbounds i8*, i8** %8, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !18 %11 = bitcast i8* %10 to i64 (%swift.opaque*, %swift.type*, i8**)* %12 = call swiftcc i64 %11(%swift.opaque* noalias nocapture swiftself %7, %swift.type* %1, i8** %8) %13 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 1 %14 = load i8*, i8** %13, align 8, !invariant.load !18 %destroy = bitcast i8* %14 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %7, %swift.type* %1) #9 %15 = bitcast %swift.opaque* %7 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %15) ret void } 79

Slide 80

Slide 80 text

makeP ͷฦΓ஋ͷਅͷܕͷऔΓग़͠ ; $s1c5makePQryFQOyQo_MD ---> ; demangling cache variable for type metadata for < some>>.0 define hidden swiftcc void @"$s1b4mainyyF"() #0 { entry: %p.debug = alloca i8*, align 8 %0 = bitcast i8** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1c5makePQryFQOyQo_MD") #7 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !18, !dereferenceable !19 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !18 %6 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %6) %7 = bitcast i8* %6 to %swift.opaque* store i8* %6, i8** %p.debug, align 8 call swiftcc void @"$s1c5makePQryF"(%swift.opaque* noalias nocapture sret(%swift.opaque) %7) %8 = call swiftcc i8** @swift_getOpaqueTypeConformance(i8* undef, %swift.type_descriptor* @"$s1c5makePQryFQOMQ", i64 1) #8 %9 = getelementptr inbounds i8*, i8** %8, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !18 %11 = bitcast i8* %10 to i64 (%swift.opaque*, %swift.type*, i8**)* %12 = call swiftcc i64 %11(%swift.opaque* noalias nocapture swiftself %7, %swift.type* %1, i8** %8) %13 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 1 %14 = load i8*, i8** %13, align 8, !invariant.load !18 %destroy = bitcast i8* %14 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %7, %swift.type* %1) #9 %15 = bitcast %swift.opaque* %7 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %15) ret void } 80

Slide 81

Slide 81 text

ਅͷܕɺVWTɺܕͷαΠζΛऔΓग़ͯ͠ϩʔΧϧม਺ΛελοΫʹ֬อ͢Δ define hidden swiftcc void @"$s1b4mainyyF"() #0 { entry: %p.debug = alloca i8*, align 8 %0 = bitcast i8** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1c5makePQryFQOyQo_MD") #7 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !18, !dereferenceable !19 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !18 %6 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %6) %7 = bitcast i8* %6 to %swift.opaque* store i8* %6, i8** %p.debug, align 8 call swiftcc void @"$s1c5makePQryF"(%swift.opaque* noalias nocapture sret(%swift.opaque) %7) %8 = call swiftcc i8** @swift_getOpaqueTypeConformance(i8* undef, %swift.type_descriptor* @"$s1c5makePQryFQOMQ", i64 1) #8 %9 = getelementptr inbounds i8*, i8** %8, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !18 %11 = bitcast i8* %10 to i64 (%swift.opaque*, %swift.type*, i8**)* %12 = call swiftcc i64 %11(%swift.opaque* noalias nocapture swiftself %7, %swift.type* %1, i8** %8) %13 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 1 %14 = load i8*, i8** %13, align 8, !invariant.load !18 %destroy = bitcast i8* %14 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %7, %swift.type* %1) #9 %15 = bitcast %swift.opaque* %7 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %15) ret void } 81

Slide 82

Slide 82 text

makeP ͷݺͼग़͠ɻฦΓ஋Λୈ1Ҿ਺ͷopaque pointerͰड͚औΔɻ define hidden swiftcc void @"$s1b4mainyyF"() #0 { entry: %p.debug = alloca i8*, align 8 %0 = bitcast i8** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1c5makePQryFQOyQo_MD") #7 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !18, !dereferenceable !19 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !18 %6 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %6) %7 = bitcast i8* %6 to %swift.opaque* store i8* %6, i8** %p.debug, align 8 call swiftcc void @"$s1c5makePQryF"(%swift.opaque* noalias nocapture sret(%swift.opaque) %7) %8 = call swiftcc i8** @swift_getOpaqueTypeConformance(i8* undef, %swift.type_descriptor* @"$s1c5makePQryFQOMQ", i64 1) #8 %9 = getelementptr inbounds i8*, i8** %8, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !18 %11 = bitcast i8* %10 to i64 (%swift.opaque*, %swift.type*, i8**)* %12 = call swiftcc i64 %11(%swift.opaque* noalias nocapture swiftself %7, %swift.type* %1, i8** %8) %13 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 1 %14 = load i8*, i8** %13, align 8, !invariant.load !18 %destroy = bitcast i8* %14 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %7, %swift.type* %1) #9 %15 = bitcast %swift.opaque* %7 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %15) ret void } 82

Slide 83

Slide 83 text

ਅͷܕͷ P ͷ PWT Λऔಘ ; $s1c5makePQryFQOMQ ---> opaque type descriptor for < some>> define hidden swiftcc void @"$s1b4mainyyF"() #0 { entry: %p.debug = alloca i8*, align 8 %0 = bitcast i8** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1c5makePQryFQOyQo_MD") #7 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !18, !dereferenceable !19 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !18 %6 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %6) %7 = bitcast i8* %6 to %swift.opaque* store i8* %6, i8** %p.debug, align 8 call swiftcc void @"$s1c5makePQryF"(%swift.opaque* noalias nocapture sret(%swift.opaque) %7) %8 = call swiftcc i8** @swift_getOpaqueTypeConformance(i8* undef, %swift.type_descriptor* @"$s1c5makePQryFQOMQ", i64 1) #8 %9 = getelementptr inbounds i8*, i8** %8, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !18 %11 = bitcast i8* %10 to i64 (%swift.opaque*, %swift.type*, i8**)* %12 = call swiftcc i64 %11(%swift.opaque* noalias nocapture swiftself %7, %swift.type* %1, i8** %8) %13 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 1 %14 = load i8*, i8** %13, align 8, !invariant.load !18 %destroy = bitcast i8* %14 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %7, %swift.type* %1) #9 %15 = bitcast %swift.opaque* %7 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %15) ret void } 83

Slide 84

Slide 84 text

PWT͔ΒऔΓग़ͨؔ͠਺Λݺͼग़͢ define hidden swiftcc void @"$s1b4mainyyF"() #0 { entry: %p.debug = alloca i8*, align 8 %0 = bitcast i8** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1c5makePQryFQOyQo_MD") #7 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !18, !dereferenceable !19 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !18 %6 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %6) %7 = bitcast i8* %6 to %swift.opaque* store i8* %6, i8** %p.debug, align 8 call swiftcc void @"$s1c5makePQryF"(%swift.opaque* noalias nocapture sret(%swift.opaque) %7) %8 = call swiftcc i8** @swift_getOpaqueTypeConformance(i8* undef, %swift.type_descriptor* @"$s1c5makePQryFQOMQ", i64 1) #8 %9 = getelementptr inbounds i8*, i8** %8, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !18 %11 = bitcast i8* %10 to i64 (%swift.opaque*, %swift.type*, i8**)* %12 = call swiftcc i64 %11(%swift.opaque* noalias nocapture swiftself %7, %swift.type* %1, i8** %8) %13 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 1 %14 = load i8*, i8** %13, align 8, !invariant.load !18 %destroy = bitcast i8* %14 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %7, %swift.type* %1) #9 %15 = bitcast %swift.opaque* %7 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %15) ret void } 84

Slide 85

Slide 85 text

VWTͷdestroyͰϩʔΧϧม਺Λ࡟আ͢Δ define hidden swiftcc void @"$s1b4mainyyF"() #0 { entry: %p.debug = alloca i8*, align 8 %0 = bitcast i8** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1c5makePQryFQOyQo_MD") #7 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !18, !dereferenceable !19 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !18 %6 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %6) %7 = bitcast i8* %6 to %swift.opaque* store i8* %6, i8** %p.debug, align 8 call swiftcc void @"$s1c5makePQryF"(%swift.opaque* noalias nocapture sret(%swift.opaque) %7) %8 = call swiftcc i8** @swift_getOpaqueTypeConformance(i8* undef, %swift.type_descriptor* @"$s1c5makePQryFQOMQ", i64 1) #8 %9 = getelementptr inbounds i8*, i8** %8, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !18 %11 = bitcast i8* %10 to i64 (%swift.opaque*, %swift.type*, i8**)* %12 = call swiftcc i64 %11(%swift.opaque* noalias nocapture swiftself %7, %swift.type* %1, i8** %8) %13 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 1 %14 = load i8*, i8** %13, align 8, !invariant.load !18 %destroy = bitcast i8* %14 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %7, %swift.type* %1) #9 %15 = bitcast %swift.opaque* %7 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %15) ret void } 85

Slide 86

Slide 86 text

__swift_instantiateConcreteTypeFromMangledName ͸ swift_getTypeByMangledNameInContext ͷΩϟογϡ෇͖ϥούʔɻ define linkonce_odr hidden %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* %0) #1 { entry: %1 = bitcast { i32, i32 }* %0 to i64* %2 = load atomic i64, i64* %1 monotonic, align 8 %3 = icmp slt i64 %2, 0 %4 = call i1 @llvm.expect.i1(i1 %3, i1 false) br i1 %4, label %8, label %5 5: ; preds = %8, %entry %6 = phi i64 [ %2, %entry ], [ %17, %8 ] %7 = inttoptr i64 %6 to %swift.type* ret %swift.type* %7 8: ; preds = %entry %9 = ashr i64 %2, 32 %10 = sub i64 0, %9 %11 = trunc i64 %2 to i32 %12 = sext i32 %11 to i64 %13 = ptrtoint { i32, i32 }* %0 to i64 %14 = add i64 %13, %12 %15 = inttoptr i64 %14 to i8* %16 = call swiftcc %swift.type* @swift_getTypeByMangledNameInContext(i8* %15, i64 %10, %swift.type_descriptor* null, i8** null) #7 %17 = ptrtoint %swift.type* %16 to i64 store atomic i64 %17, i64* %1 monotonic, align 8 br label %5 } 86

Slide 87

Slide 87 text

ORTͷ࣮૷ͷ·ͱΊ • ΠϯλʔϑΣʔε͸Genericsͱಉ͡opaque pointerΛ࢖͏ ͕ɺਅͷܕ΍PWT͸౉͞ͳ͍ɻ • ORTͷਅͷܕͱPWT͸ɺͦͷdescriptorΛϥϯλΠϜؔ਺ʹ ౉͢͜ͱͰɺݺͼग़͠ଆͰऔಘͰ͖ΔΑ͏ʹͳ͍ͬͯΔɻ 87

Slide 88

Slide 88 text

৽ػೳ 88

Slide 89

Slide 89 text

SE-0335: Introduce existential any protocol P {} func useP(_ p: any P) {} Existentialͷܕ໊͕ any P ʹͳͬͨࣄͰɺ ͱผͷ֓೦Ͱ ͋Δ͜ͱ͕௚ײతʹΘ͔Γ΍͘͢ͳΔ 89

Slide 90

Slide 90 text

Any ͱ AnyObject ͸ෆཁ func useAny(_ a: Any) {} func useAnyObject(_ a: AnyObject) {} ͢Ͱʹ໊લʹ Any ͷจࣈ͕෇͍͍ͯͯΘ͔Γ΍͍͢ 90

Slide 91

Slide 91 text

Existential Metatype Container func useMetatype(_ p: any P.Type) {} useMetatype(S.self) P ʹ४ڌ͢ΔܕͷϝλλΠϓͷܕ͸ any P.Type ͱදه͢Δɻ any ͸ P.Type ʹର͔͔͍ͯͬͯ͠Δɻ ैདྷ͸ P.Type ͱॻ͍͍ͯͨɻ 91

Slide 92

Slide 92 text

Existential Container Metatype func useExistentialMetatype(_ p: (any P).Type) {} useExistentialMetatype((any P).self) Existential ContainerͷϝλλΠϓ͸ (any P).Type ͱදه͢ Δɻ ஋͸ (any P).self Ͱੜ੒Ͱ͖Δɻ ैདྷͳ P.Protocol ͱ P.self ͱॻ͍͍ͯͨɻ 92

Slide 93

Slide 93 text

Protocol Composition func useExistential(_ e: any P & Q) {} func useMetatype(_ t: any (P & Q).Type) {} func useExistentialMetatype(_ t: (any P & Q).Type) {} useExistential(S()) useMetatype(S.self) useExistentialMetatype((any P & Q).self) 93

Slide 94

Slide 94 text

SE-0309: Unlock existentials for all protocols protocol P { associatedtype A } func useP(_ p: any P) {} ͋ΒΏΔϓϩτίϧ͕ Existential Λߏ੒Ͱ͖ΔΑ͏ʹͳͬͨ 94

Slide 95

Slide 95 text

contravariantͳassociated type͸࢖͑ͳ͍ protocol P { associatedtype A func a() -> A func useA(_ a: A) } func useP(_ p: any P) { // ok p.a() // error: member 'useA' cannot be used on value of type 'any P'; // consider using a generic constraint instead p.useA(1) } 95

Slide 96

Slide 96 text

contravariantͳSelf type͸࢖͑ͳ͍ protocol P { func p() -> Self func useP(_ p: Self) } func useP(_ p: any P) { // ok p.p() // error: member 'useP' cannot be used on value of type 'any P'; // consider using a generic constraint instead p.useP(p) } 96

Slide 97

Slide 97 text

covariantͳϝϯό͸upper boundʹͳΔ protocol BP {} protocol P { associatedtype A associatedtype B: BP func p() -> Self func a() -> A func b() -> B } func useP(_ p: any P) { let p2: any P = p.p() let a: Any = p.a() let b: any BP = p.b() } ͜ͷ upper boundͳexistentialܕͷੜ੒͸શ͘৽͍͠ϩδοΫ 97

Slide 98

Slide 98 text

ෳࡶͳcovariance protocol P { func passSelf(_ f: (Self) -> Void) } func useP(_ p: any P) { p.passSelf { (p: any P) in } } 98

Slide 99

Slide 99 text

ܧঝ࣌ͷconstraintʹΑΔܕͷݻఆ protocol P { associatedtype A func a() -> A func useA(_ a: A) } protocol Q: P where Self.A == Int {} func useQ(q: any Q) { let a: Int = q.a() q.useA(1) } 99

Slide 100

Slide 100 text

compositionʹΑΔܕͷݻఆ protocol P { associatedtype A } class C: P { typealias A = Int } protocol Q: P { func a() -> A func useA(_ a: A) } func useQ(q: any Q & C) { let a: Int = q.a() q.useA(1) } 100

Slide 101

Slide 101 text

Existentialͷ upper boundม׵ͷ࣮૷ 101

Slide 102

Slide 102 text

protocol BP {} protocol P { associatedtype A associatedtype B: BP func p() -> Self func a() -> A func b() -> B } func callP(_ p: any P) -> any P { p.p() } 102

Slide 103

Slide 103 text

Existential Containerͷܗ͸ಛʹมΘΒͳ͍ %T1d1PP = type { [24 x i8], %swift.type*, i8** } 103

Slide 104

Slide 104 text

define hidden swiftcc void @"$s1d5callPyAA1P_pAaC_pF"( %T1d1PP* noalias nocapture sret(%T1d1PP) %0, %T1d1PP* noalias nocapture dereferenceable(40) %1 ) #0 { entry: %p.debug = alloca %T1d1PP*, align 8 %2 = bitcast %T1d1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 8, i1 false) store %T1d1PP* %1, %T1d1PP** %p.debug, align 8 %3 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 1 %4 = load %swift.type*, %swift.type** %3, align 8 %5 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 2 %6 = load i8**, i8*** %5, align 8 %7 = bitcast %T1d1PP* %1 to %__opaque_existential_type_1* %8 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %7, %swift.type* %4) #4 %9 = getelementptr inbounds i8*, i8** %6, i32 4 %10 = load i8*, i8** %9, align 8, !invariant.load !39 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %12 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 1 store %swift.type* %4, %swift.type** %12, align 8 %13 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 2 store i8** %6, i8*** %13, align 8 %14 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 0 %15 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 0 %16 = bitcast %T1d1PP* %0 to %__opaque_existential_type_1* %17 = call %swift.opaque* @__swift_allocate_boxed_opaque_existential_1(%__opaque_existential_type_1* %16) #4 call swiftcc void %11( %swift.opaque* noalias nocapture sret(%swift.opaque) %17, %swift.opaque* noalias nocapture swiftself %8, %swift.type* %4, i8** %6 ) ret void } 104

Slide 105

Slide 105 text

Ҿ਺ͷopenͱwitnessϝιουऔΓग़͠ define hidden swiftcc void @"$s1d5callPyAA1P_pAaC_pF"( %T1d1PP* noalias nocapture sret(%T1d1PP) %0, %T1d1PP* noalias nocapture dereferenceable(40) %1 ) #0 { entry: %p.debug = alloca %T1d1PP*, align 8 %2 = bitcast %T1d1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 8, i1 false) store %T1d1PP* %1, %T1d1PP** %p.debug, align 8 %3 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 1 %4 = load %swift.type*, %swift.type** %3, align 8 %5 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 2 %6 = load i8**, i8*** %5, align 8 %7 = bitcast %T1d1PP* %1 to %__opaque_existential_type_1* %8 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %7, %swift.type* %4) #4 %9 = getelementptr inbounds i8*, i8** %6, i32 4 %10 = load i8*, i8** %9, align 8, !invariant.load !39 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %12 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 1 store %swift.type* %4, %swift.type** %12, align 8 %13 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 2 store i8** %6, i8*** %13, align 8 %14 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 0 %15 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 0 %16 = bitcast %T1d1PP* %0 to %__opaque_existential_type_1* %17 = call %swift.opaque* @__swift_allocate_boxed_opaque_existential_1(%__opaque_existential_type_1* %16) #4 call swiftcc void %11( %swift.opaque* noalias nocapture sret(%swift.opaque) %17, %swift.opaque* noalias nocapture swiftself %8, %swift.type* %4, i8** %6 ) ret void } 105

Slide 106

Slide 106 text

ฦΓ஋ͷ any P ΁ͷܕͱwitness tableͷॻ͖ࠐΈ define hidden swiftcc void @"$s1d5callPyAA1P_pAaC_pF"( %T1d1PP* noalias nocapture sret(%T1d1PP) %0, %T1d1PP* noalias nocapture dereferenceable(40) %1 ) #0 { entry: %p.debug = alloca %T1d1PP*, align 8 %2 = bitcast %T1d1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 8, i1 false) store %T1d1PP* %1, %T1d1PP** %p.debug, align 8 %3 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 1 %4 = load %swift.type*, %swift.type** %3, align 8 %5 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 2 %6 = load i8**, i8*** %5, align 8 %7 = bitcast %T1d1PP* %1 to %__opaque_existential_type_1* %8 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %7, %swift.type* %4) #4 %9 = getelementptr inbounds i8*, i8** %6, i32 4 %10 = load i8*, i8** %9, align 8, !invariant.load !39 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %12 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 1 store %swift.type* %4, %swift.type** %12, align 8 %13 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 2 store i8** %6, i8*** %13, align 8 %14 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 0 %15 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 0 %16 = bitcast %T1d1PP* %0 to %__opaque_existential_type_1* %17 = call %swift.opaque* @__swift_allocate_boxed_opaque_existential_1(%__opaque_existential_type_1* %16) #4 call swiftcc void %11( %swift.opaque* noalias nocapture sret(%swift.opaque) %17, %swift.opaque* noalias nocapture swiftself %8, %swift.type* %4, i8** %6 ) ret void } 106

Slide 107

Slide 107 text

ฦΓ஋ any P ͷ஋෦෼ͷϙΠϯλͷऔΓग़͠ define hidden swiftcc void @"$s1d5callPyAA1P_pAaC_pF"( %T1d1PP* noalias nocapture sret(%T1d1PP) %0, %T1d1PP* noalias nocapture dereferenceable(40) %1 ) #0 { entry: %p.debug = alloca %T1d1PP*, align 8 %2 = bitcast %T1d1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 8, i1 false) store %T1d1PP* %1, %T1d1PP** %p.debug, align 8 %3 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 1 %4 = load %swift.type*, %swift.type** %3, align 8 %5 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 2 %6 = load i8**, i8*** %5, align 8 %7 = bitcast %T1d1PP* %1 to %__opaque_existential_type_1* %8 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %7, %swift.type* %4) #4 %9 = getelementptr inbounds i8*, i8** %6, i32 4 %10 = load i8*, i8** %9, align 8, !invariant.load !39 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %12 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 1 store %swift.type* %4, %swift.type** %12, align 8 %13 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 2 store i8** %6, i8*** %13, align 8 %14 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 0 %15 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 0 %16 = bitcast %T1d1PP* %0 to %__opaque_existential_type_1* %17 = call %swift.opaque* @__swift_allocate_boxed_opaque_existential_1(%__opaque_existential_type_1* %16) #4 call swiftcc void %11( %swift.opaque* noalias nocapture sret(%swift.opaque) %17, %swift.opaque* noalias nocapture swiftself %8, %swift.type* %4, i8** %6 ) ret void } 107

Slide 108

Slide 108 text

witnessϝιουͷpͷݺͼग़͠ define hidden swiftcc void @"$s1d5callPyAA1P_pAaC_pF"( %T1d1PP* noalias nocapture sret(%T1d1PP) %0, %T1d1PP* noalias nocapture dereferenceable(40) %1 ) #0 { entry: %p.debug = alloca %T1d1PP*, align 8 %2 = bitcast %T1d1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 8, i1 false) store %T1d1PP* %1, %T1d1PP** %p.debug, align 8 %3 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 1 %4 = load %swift.type*, %swift.type** %3, align 8 %5 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 2 %6 = load i8**, i8*** %5, align 8 %7 = bitcast %T1d1PP* %1 to %__opaque_existential_type_1* %8 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %7, %swift.type* %4) #4 %9 = getelementptr inbounds i8*, i8** %6, i32 4 %10 = load i8*, i8** %9, align 8, !invariant.load !39 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %12 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 1 store %swift.type* %4, %swift.type** %12, align 8 %13 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 2 store i8** %6, i8*** %13, align 8 %14 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 0 %15 = getelementptr inbounds %T1d1PP, %T1d1PP* %0, i32 0, i32 0 %16 = bitcast %T1d1PP* %0 to %__opaque_existential_type_1* %17 = call %swift.opaque* @__swift_allocate_boxed_opaque_existential_1(%__opaque_existential_type_1* %16) #4 call swiftcc void %11( %swift.opaque* noalias nocapture sret(%swift.opaque) %17, %swift.opaque* noalias nocapture swiftself %8, %swift.type* %4, i8** %6 ) ret void } 108

Slide 109

Slide 109 text

func callA(_ p: any P) -> Any { p.a() } 109

Slide 110

Slide 110 text

define hidden swiftcc void @"$s1d5callAyypAA1P_pF"( %Any* noalias nocapture sret(%Any) %0, %T1d1PP* noalias nocapture dereferenceable(40) %1 ) #0 { entry: %p.debug = alloca %T1d1PP*, align 8 %2 = bitcast %T1d1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 8, i1 false) store %T1d1PP* %1, %T1d1PP** %p.debug, align 8 %3 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 1 %4 = load %swift.type*, %swift.type** %3, align 8 %5 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 2 %6 = load i8**, i8*** %5, align 8 %7 = bitcast %T1d1PP* %1 to %__opaque_existential_type_1* %8 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %7, %swift.type* %4) #4 %9 = getelementptr inbounds i8*, i8** %6, i32 5 %10 = load i8*, i8** %9, align 8, !invariant.load !39 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %12 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %6, %swift.type* %4, %swift.protocol_requirement* getelementptr ( %swift.protocol_requirement, %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 9 ), i32 -1 ), %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 10 ) ) #9 %13 = extractvalue %swift.metadata_response %12, 0 %14 = getelementptr inbounds %Any, %Any* %0, i32 0, i32 1 store %swift.type* %13, %swift.type** %14, align 8 %15 = getelementptr inbounds %Any, %Any* %0, i32 0, i32 0 %16 = getelementptr inbounds %Any, %Any* %0, i32 0, i32 0 %17 = bitcast %Any* %0 to %__opaque_existential_type_0* %18 = call %swift.opaque* @__swift_allocate_boxed_opaque_existential_0(%__opaque_existential_type_0* %17) #4 call swiftcc void %11(%swift.opaque* noalias nocapture sret(%swift.opaque) %18, %swift.opaque* noalias nocapture swiftself %8, %swift.type* %4, i8** %6) ret void } 110

Slide 111

Slide 111 text

ฦΓ஋ͷ Any ͸ witness table Λ࣋ͨͳ͍existentialͷܗΛ͍ͯ͠Δ %Any = type { [24 x i8], %swift.type* } define hidden swiftcc void @"$s1d5callAyypAA1P_pF"( %Any* noalias nocapture sret(%Any) %0, %T1d1PP* noalias nocapture dereferenceable(40) %1 ) #0 { entry: %p.debug = alloca %T1d1PP*, align 8 %2 = bitcast %T1d1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 8, i1 false) store %T1d1PP* %1, %T1d1PP** %p.debug, align 8 %3 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 1 %4 = load %swift.type*, %swift.type** %3, align 8 %5 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 2 %6 = load i8**, i8*** %5, align 8 %7 = bitcast %T1d1PP* %1 to %__opaque_existential_type_1* %8 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %7, %swift.type* %4) #4 %9 = getelementptr inbounds i8*, i8** %6, i32 5 %10 = load i8*, i8** %9, align 8, !invariant.load !39 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %12 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %6, %swift.type* %4, %swift.protocol_requirement* getelementptr ( %swift.protocol_requirement, %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 9 ), i32 -1 ), %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 10 ) ) #9 %13 = extractvalue %swift.metadata_response %12, 0 %14 = getelementptr inbounds %Any, %Any* %0, i32 0, i32 1 store %swift.type* %13, %swift.type** %14, align 8 %15 = getelementptr inbounds %Any, %Any* %0, i32 0, i32 0 %16 = getelementptr inbounds %Any, %Any* %0, i32 0, i32 0 %17 = bitcast %Any* %0 to %__opaque_existential_type_0* %18 = call %swift.opaque* @__swift_allocate_boxed_opaque_existential_0(%__opaque_existential_type_0* %17) #4 call swiftcc void %11(%swift.opaque* noalias nocapture sret(%swift.opaque) %18, %swift.opaque* noalias nocapture swiftself %8, %swift.type* %4, i8** %6) ret void } 111

Slide 112

Slide 112 text

Ҿ਺ͷ any P ͔ΒਅͷܕͱWTͷऔΓग़͠ define hidden swiftcc void @"$s1d5callAyypAA1P_pF"( %Any* noalias nocapture sret(%Any) %0, %T1d1PP* noalias nocapture dereferenceable(40) %1 ) #0 { entry: %p.debug = alloca %T1d1PP*, align 8 %2 = bitcast %T1d1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 8, i1 false) store %T1d1PP* %1, %T1d1PP** %p.debug, align 8 %3 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 1 %4 = load %swift.type*, %swift.type** %3, align 8 %5 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 2 %6 = load i8**, i8*** %5, align 8 %7 = bitcast %T1d1PP* %1 to %__opaque_existential_type_1* %8 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %7, %swift.type* %4) #4 %9 = getelementptr inbounds i8*, i8** %6, i32 5 %10 = load i8*, i8** %9, align 8, !invariant.load !39 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %12 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %6, %swift.type* %4, %swift.protocol_requirement* getelementptr ( %swift.protocol_requirement, %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 9 ), i32 -1 ), %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 10 ) ) #9 %13 = extractvalue %swift.metadata_response %12, 0 %14 = getelementptr inbounds %Any, %Any* %0, i32 0, i32 1 store %swift.type* %13, %swift.type** %14, align 8 %15 = getelementptr inbounds %Any, %Any* %0, i32 0, i32 0 %16 = getelementptr inbounds %Any, %Any* %0, i32 0, i32 0 %17 = bitcast %Any* %0 to %__opaque_existential_type_0* %18 = call %swift.opaque* @__swift_allocate_boxed_opaque_existential_0(%__opaque_existential_type_0* %17) #4 call swiftcc void %11(%swift.opaque* noalias nocapture sret(%swift.opaque) %18, %swift.opaque* noalias nocapture swiftself %8, %swift.type* %4, i8** %6) ret void } 112

Slide 113

Slide 113 text

ϥϯλΠϜؔ਺Ͱ associatedtype A ͷਅͷܕΛऔΓग़͠ define hidden swiftcc void @"$s1d5callAyypAA1P_pF"( %Any* noalias nocapture sret(%Any) %0, %T1d1PP* noalias nocapture dereferenceable(40) %1 ) #0 { entry: %p.debug = alloca %T1d1PP*, align 8 %2 = bitcast %T1d1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 8, i1 false) store %T1d1PP* %1, %T1d1PP** %p.debug, align 8 %3 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 1 %4 = load %swift.type*, %swift.type** %3, align 8 %5 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 2 %6 = load i8**, i8*** %5, align 8 %7 = bitcast %T1d1PP* %1 to %__opaque_existential_type_1* %8 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %7, %swift.type* %4) #4 %9 = getelementptr inbounds i8*, i8** %6, i32 5 %10 = load i8*, i8** %9, align 8, !invariant.load !39 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %12 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %6, %swift.type* %4, %swift.protocol_requirement* getelementptr ( %swift.protocol_requirement, %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 9 ), i32 -1 ), %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 10 ) ) #9 %13 = extractvalue %swift.metadata_response %12, 0 %14 = getelementptr inbounds %Any, %Any* %0, i32 0, i32 1 store %swift.type* %13, %swift.type** %14, align 8 %15 = getelementptr inbounds %Any, %Any* %0, i32 0, i32 0 %16 = getelementptr inbounds %Any, %Any* %0, i32 0, i32 0 %17 = bitcast %Any* %0 to %__opaque_existential_type_0* %18 = call %swift.opaque* @__swift_allocate_boxed_opaque_existential_0(%__opaque_existential_type_0* %17) #4 call swiftcc void %11(%swift.opaque* noalias nocapture sret(%swift.opaque) %18, %swift.opaque* noalias nocapture swiftself %8, %swift.type* %4, i8** %6) ret void } 113

Slide 114

Slide 114 text

औΓग़ͨ͠ܕΛฦΓ஋ͷܕͱͯ͠ηοτɺଞಉ༷ define hidden swiftcc void @"$s1d5callAyypAA1P_pF"( %Any* noalias nocapture sret(%Any) %0, %T1d1PP* noalias nocapture dereferenceable(40) %1 ) #0 { entry: %p.debug = alloca %T1d1PP*, align 8 %2 = bitcast %T1d1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 8, i1 false) store %T1d1PP* %1, %T1d1PP** %p.debug, align 8 %3 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 1 %4 = load %swift.type*, %swift.type** %3, align 8 %5 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 2 %6 = load i8**, i8*** %5, align 8 %7 = bitcast %T1d1PP* %1 to %__opaque_existential_type_1* %8 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %7, %swift.type* %4) #4 %9 = getelementptr inbounds i8*, i8** %6, i32 5 %10 = load i8*, i8** %9, align 8, !invariant.load !39 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %12 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %6, %swift.type* %4, %swift.protocol_requirement* getelementptr ( %swift.protocol_requirement, %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 9 ), i32 -1 ), %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 10 ) ) #9 %13 = extractvalue %swift.metadata_response %12, 0 %14 = getelementptr inbounds %Any, %Any* %0, i32 0, i32 1 store %swift.type* %13, %swift.type** %14, align 8 %15 = getelementptr inbounds %Any, %Any* %0, i32 0, i32 0 %16 = getelementptr inbounds %Any, %Any* %0, i32 0, i32 0 %17 = bitcast %Any* %0 to %__opaque_existential_type_0* %18 = call %swift.opaque* @__swift_allocate_boxed_opaque_existential_0(%__opaque_existential_type_0* %17) #4 call swiftcc void %11(%swift.opaque* noalias nocapture sret(%swift.opaque) %18, %swift.opaque* noalias nocapture swiftself %8, %swift.type* %4, i8** %6) ret void } 114

Slide 115

Slide 115 text

func callB(_ p: any P) -> any BP { p.b() } 115

Slide 116

Slide 116 text

define hidden swiftcc void @"$s1d5callByAA2BP_pAA1P_pF"( %T1d2BPP* noalias nocapture sret(%T1d2BPP) %0, %T1d1PP* noalias nocapture dereferenceable(40) %1) #0 { entry: %p.debug = alloca %T1d1PP*, align 8 %2 = bitcast %T1d1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 8, i1 false) store %T1d1PP* %1, %T1d1PP** %p.debug, align 8 %3 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 1 %4 = load %swift.type*, %swift.type** %3, align 8 %5 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 2 %6 = load i8**, i8*** %5, align 8 %7 = bitcast %T1d1PP* %1 to %__opaque_existential_type_1* %8 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %7, %swift.type* %4) #4 %9 = getelementptr inbounds i8*, i8** %6, i32 6 %10 = load i8*, i8** %9, align 8, !invariant.load !39 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %12 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %6, %swift.type* %4, %swift.protocol_requirement* getelementptr ( %swift.protocol_requirement, %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 9 ), i32 -1 ), %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 11 ) ) #9 %13 = extractvalue %swift.metadata_response %12, 0 %14 = getelementptr inbounds %T1d2BPP, %T1d2BPP* %0, i32 0, i32 1 store %swift.type* %13, %swift.type** %14, align 8 %15 = call swiftcc i8** @swift_getAssociatedConformanceWitness( i8** %6, %swift.type* %4, %swift.type* %13, %swift.protocol_requirement* getelementptr ( %swift.protocol_requirement, %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 9 ), i32 -1 ), %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 9 ) ) #9 %16 = getelementptr inbounds %T1d2BPP, %T1d2BPP* %0, i32 0, i32 2 store i8** %15, i8*** %16, align 8 %17 = getelementptr inbounds %T1d2BPP, %T1d2BPP* %0, i32 0, i32 0 %18 = getelementptr inbounds %T1d2BPP, %T1d2BPP* %0, i32 0, i32 0 %19 = bitcast %T1d2BPP* %0 to %__opaque_existential_type_1* %20 = call %swift.opaque* @__swift_allocate_boxed_opaque_existential_1(%__opaque_existential_type_1* %19) #4 call swiftcc void %11( %swift.opaque* noalias nocapture sret(%swift.opaque) %20, %swift.opaque* noalias nocapture swiftself %8, %swift.type* %4, i8** %6 ) ret void } 116

Slide 117

Slide 117 text

ϥϯλΠϜؔ਺Ͱ associatedtype B ͷਅͷܕͷऔΓग़͠ define hidden swiftcc void @"$s1d5callByAA2BP_pAA1P_pF"( %T1d2BPP* noalias nocapture sret(%T1d2BPP) %0, %T1d1PP* noalias nocapture dereferenceable(40) %1) #0 { entry: %p.debug = alloca %T1d1PP*, align 8 %2 = bitcast %T1d1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 8, i1 false) store %T1d1PP* %1, %T1d1PP** %p.debug, align 8 %3 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 1 %4 = load %swift.type*, %swift.type** %3, align 8 %5 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 2 %6 = load i8**, i8*** %5, align 8 %7 = bitcast %T1d1PP* %1 to %__opaque_existential_type_1* %8 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %7, %swift.type* %4) #4 %9 = getelementptr inbounds i8*, i8** %6, i32 6 %10 = load i8*, i8** %9, align 8, !invariant.load !39 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %12 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %6, %swift.type* %4, %swift.protocol_requirement* getelementptr ( %swift.protocol_requirement, %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 9 ), i32 -1 ), %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 11 ) ) #9 %13 = extractvalue %swift.metadata_response %12, 0 %14 = getelementptr inbounds %T1d2BPP, %T1d2BPP* %0, i32 0, i32 1 store %swift.type* %13, %swift.type** %14, align 8 %15 = call swiftcc i8** @swift_getAssociatedConformanceWitness( i8** %6, %swift.type* %4, %swift.type* %13, %swift.protocol_requirement* getelementptr ( %swift.protocol_requirement, %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 9 ), i32 -1 ), %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 9 ) ) #9 %16 = getelementptr inbounds %T1d2BPP, %T1d2BPP* %0, i32 0, i32 2 store i8** %15, i8*** %16, align 8 %17 = getelementptr inbounds %T1d2BPP, %T1d2BPP* %0, i32 0, i32 0 %18 = getelementptr inbounds %T1d2BPP, %T1d2BPP* %0, i32 0, i32 0 %19 = bitcast %T1d2BPP* %0 to %__opaque_existential_type_1* %20 = call %swift.opaque* @__swift_allocate_boxed_opaque_existential_1(%__opaque_existential_type_1* %19) #4 call swiftcc void %11( %swift.opaque* noalias nocapture sret(%swift.opaque) %20, %swift.opaque* noalias nocapture swiftself %8, %swift.type* %4, i8** %6 ) ret void } 117

Slide 118

Slide 118 text

ϥϯλΠϜؔ਺Ͱ associatedtype B ͷ PB ͷ PWT ΛऔΓग़͠ɺҎԼಉ༷ define hidden swiftcc void @"$s1d5callByAA2BP_pAA1P_pF"( %T1d2BPP* noalias nocapture sret(%T1d2BPP) %0, %T1d1PP* noalias nocapture dereferenceable(40) %1) #0 { entry: %p.debug = alloca %T1d1PP*, align 8 %2 = bitcast %T1d1PP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 8, i1 false) store %T1d1PP* %1, %T1d1PP** %p.debug, align 8 %3 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 1 %4 = load %swift.type*, %swift.type** %3, align 8 %5 = getelementptr inbounds %T1d1PP, %T1d1PP* %1, i32 0, i32 2 %6 = load i8**, i8*** %5, align 8 %7 = bitcast %T1d1PP* %1 to %__opaque_existential_type_1* %8 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %7, %swift.type* %4) #4 %9 = getelementptr inbounds i8*, i8** %6, i32 6 %10 = load i8*, i8** %9, align 8, !invariant.load !39 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %12 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %6, %swift.type* %4, %swift.protocol_requirement* getelementptr ( %swift.protocol_requirement, %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 9 ), i32 -1 ), %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 11 ) ) #9 %13 = extractvalue %swift.metadata_response %12, 0 %14 = getelementptr inbounds %T1d2BPP, %T1d2BPP* %0, i32 0, i32 1 store %swift.type* %13, %swift.type** %14, align 8 %15 = call swiftcc i8** @swift_getAssociatedConformanceWitness( i8** %6, %swift.type* %4, %swift.type* %13, %swift.protocol_requirement* getelementptr ( %swift.protocol_requirement, %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 9 ), i32 -1 ), %swift.protocol_requirement* getelementptr inbounds ( <{ ... }>, <{ ... }>* @"$s1d1PMp", i32 0, i32 9 ) ) #9 %16 = getelementptr inbounds %T1d2BPP, %T1d2BPP* %0, i32 0, i32 2 store i8** %15, i8*** %16, align 8 %17 = getelementptr inbounds %T1d2BPP, %T1d2BPP* %0, i32 0, i32 0 %18 = getelementptr inbounds %T1d2BPP, %T1d2BPP* %0, i32 0, i32 0 %19 = bitcast %T1d2BPP* %0 to %__opaque_existential_type_1* %20 = call %swift.opaque* @__swift_allocate_boxed_opaque_existential_1(%__opaque_existential_type_1* %19) #4 call swiftcc void %11( %swift.opaque* noalias nocapture sret(%swift.opaque) %20, %swift.opaque* noalias nocapture swiftself %8, %swift.type* %4, i8** %6 ) ret void } 118

Slide 119

Slide 119 text

Existentialͷ੍ݶഇࢭͷ·ͱΊ • ͲΜͳprotocolͰ΋existentialʹ࢖͑ΔΑ͏ʹͳͬͨ • ࠔΔvarianceͷϝϯό͸࢖༻ෆೳʹͨ͠ • covarianceͰ͸upper boundʹแΜͩ • existentialͷܕͷ෦෼ΛઌʹຒΊΔͱɺ஋ͷ෦෼͸௨ৗͷ GenericsͱABIޓ׵ੑ͕͋Δ • associated typeͷ৘ใ͸ϥϯλΠϜؔ਺ͰऔΓग़ͤΔ 119

Slide 120

Slide 120 text

SE-0328: Structural opaque result types func ortOptional() -> (some P)? { S() } func ortTuple() -> (some P, some Q) { (S(), S()) } func ortArray() -> [some P] { [S(), S()] } func ortGeneric() -> C { C() } some ͕ฦΓ஋ͷܕύϥϝʔλ෦෼Ͱ࢖͑Δ 120

Slide 121

Slide 121 text

some P͸͋ΔҰͭͷܕΛҙຯ͢Δ func ortArray() -> [some P] { ... } // ؾ࣋ͪ func ortArray() -> [T] { ... } ഑ྻͰ͋Ε͹ɺཁૉͷܕ͸શͯಉҰɻ 121

Slide 122

Slide 122 text

࣮૷࿙Ε13 func ortFunc() -> () -> some P { { S() } } ఏҊॻʹΑΔͱ͜Ε΋Ͱ͖Δ͸ͣΒ͍͠ 13 https://github.com/apple/swift/blob/main/test/type/opaque_return_structural.swift 122

Slide 123

Slide 123 text

ฦؔ͢਺ͷύϥϝʔλ෦෼͸ବ໨ func ortFuncParam() -> (some P) -> () { ... } callerଆͰऔಘͨؔ͠਺͕ड͚औΔ some P Λ࡞Δํ๏͕ແ͍ɻ 14 14 https://github.com/apple/swift-evolution/blob/main/proposals/0341-opaque-parameters.md#opaque- parameters-in-consuming-positions-of-function-types 123

Slide 124

Slide 124 text

S-ORTͷ࣮૷ 124

Slide 125

Slide 125 text

func ortTuple() -> (some P, some Q) { (S(), S()) } func main() { let t = ortTuple() } 125

Slide 126

Slide 126 text

SILΛݟ͓ͯ͘ // ortTuple() sil @$s1e8ortTupleQr_QR_tyF : $@convention(thin) @substituted <τ_0_0, τ_0_1> () -> (@out τ_0_0, @out τ_0_1) for < @_opaqueReturnTypeOf("$s1e8ortTupleQr_QR_tyF", 0) __, @_opaqueReturnTypeOf("$s1e8ortTupleQr_QR_tyF", 1) __ > { ... } 126

Slide 127

Slide 127 text

define hidden swiftcc void @"$s1f4mainyyF"() #0 { entry: %t.debug = alloca i8*, align 8 %0 = bitcast i8** %t.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName( { i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD" ) #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !19 %t = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %t) %6 = bitcast i8* %t to <{}>* store i8* %t, i8** %t.debug, align 8 %.elt = bitcast <{}>* %6 to %swift.opaque* %7 = bitcast %swift.type* %1 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %6 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* call swiftcc void @"$s1e8ortTupleQr_QR_tyF"(%swift.opaque* noalias nocapture %.elt, %swift.opaque* noalias nocapture %.elt1) %11 = call <{}>* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tWOh"(<{}>* %6) %12 = bitcast <{}>* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 127

Slide 128

Slide 128 text

ฦΓ஋ͷϝλλΠϓΛऔಘ ; $s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD ---> ; demangling cache variable for type metadata for ( ; < (some, some)>>.0, ; < (some, some)>>.1 ; ) define hidden swiftcc void @"$s1f4mainyyF"() #0 { entry: %t.debug = alloca i8*, align 8 %0 = bitcast i8** %t.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName( { i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD" ) #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !19 %t = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %t) %6 = bitcast i8* %t to <{}>* store i8* %t, i8** %t.debug, align 8 %.elt = bitcast <{}>* %6 to %swift.opaque* %7 = bitcast %swift.type* %1 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %6 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* call swiftcc void @"$s1e8ortTupleQr_QR_tyF"(%swift.opaque* noalias nocapture %.elt, %swift.opaque* noalias nocapture %.elt1) %11 = call <{}>* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tWOh"(<{}>* %6) %12 = bitcast <{}>* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 128

Slide 129

Slide 129 text

VWTΛऔΓग़ͯ͠ฦΓ஋ͷλϓϧͷϝϞϦྖҬΛ֬อ define hidden swiftcc void @"$s1f4mainyyF"() #0 { entry: %t.debug = alloca i8*, align 8 %0 = bitcast i8** %t.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName( { i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD" ) #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !19 %t = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %t) %6 = bitcast i8* %t to <{}>* store i8* %t, i8** %t.debug, align 8 %.elt = bitcast <{}>* %6 to %swift.opaque* %7 = bitcast %swift.type* %1 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %6 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* call swiftcc void @"$s1e8ortTupleQr_QR_tyF"(%swift.opaque* noalias nocapture %.elt, %swift.opaque* noalias nocapture %.elt1) %11 = call <{}>* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tWOh"(<{}>* %6) %12 = bitcast <{}>* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 129

Slide 130

Slide 130 text

λϓϧͷ0൪ཁૉͷϙΠϯλΛऔಘ define hidden swiftcc void @"$s1f4mainyyF"() #0 { entry: %t.debug = alloca i8*, align 8 %0 = bitcast i8** %t.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName( { i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD" ) #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !19 %t = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %t) %6 = bitcast i8* %t to <{}>* store i8* %t, i8** %t.debug, align 8 %.elt = bitcast <{}>* %6 to %swift.opaque* %7 = bitcast %swift.type* %1 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %6 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* call swiftcc void @"$s1e8ortTupleQr_QR_tyF"(%swift.opaque* noalias nocapture %.elt, %swift.opaque* noalias nocapture %.elt1) %11 = call <{}>* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tWOh"(<{}>* %6) %12 = bitcast <{}>* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 130

Slide 131

Slide 131 text

λϓϧͷ1൪ཁૉͷΦϑηοτΛऔಘͯ͠ɺϙΠϯλΛܭࢉ define hidden swiftcc void @"$s1f4mainyyF"() #0 { entry: %t.debug = alloca i8*, align 8 %0 = bitcast i8** %t.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName( { i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD" ) #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !19 %t = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %t) %6 = bitcast i8* %t to <{}>* store i8* %t, i8** %t.debug, align 8 %.elt = bitcast <{}>* %6 to %swift.opaque* %7 = bitcast %swift.type* %1 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %6 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* call swiftcc void @"$s1e8ortTupleQr_QR_tyF"(%swift.opaque* noalias nocapture %.elt, %swift.opaque* noalias nocapture %.elt1) %11 = call <{}>* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tWOh"(<{}>* %6) %12 = bitcast <{}>* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 131

Slide 132

Slide 132 text

λϓϧͷ2ͭͷཁૉͷϙΠϯλΛҾ਺Ͱ౉ͯ͠ฦΓ஋Λऔಘ define hidden swiftcc void @"$s1f4mainyyF"() #0 { entry: %t.debug = alloca i8*, align 8 %0 = bitcast i8** %t.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName( { i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD" ) #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !19 %t = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %t) %6 = bitcast i8* %t to <{}>* store i8* %t, i8** %t.debug, align 8 %.elt = bitcast <{}>* %6 to %swift.opaque* %7 = bitcast %swift.type* %1 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %6 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* call swiftcc void @"$s1e8ortTupleQr_QR_tyF"(%swift.opaque* noalias nocapture %.elt, %swift.opaque* noalias nocapture %.elt1) %11 = call <{}>* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tWOh"(<{}>* %6) %12 = bitcast <{}>* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 132

Slide 133

Slide 133 text

औಘͨ͠λϓϧΛ࡟আ ; $s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tWOh ---> ; outlined destroy of ( ; < (some, some)>>.0, ; < (some, some)>>.1 ; ) define hidden swiftcc void @"$s1f4mainyyF"() #0 { entry: %t.debug = alloca i8*, align 8 %0 = bitcast i8** %t.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName( { i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD" ) #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !19 %t = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %t) %6 = bitcast i8* %t to <{}>* store i8* %t, i8** %t.debug, align 8 %.elt = bitcast <{}>* %6 to %swift.opaque* %7 = bitcast %swift.type* %1 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %6 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* call swiftcc void @"$s1e8ortTupleQr_QR_tyF"(%swift.opaque* noalias nocapture %.elt, %swift.opaque* noalias nocapture %.elt1) %11 = call <{}>* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tWOh"(<{}>* %6) %12 = bitcast <{}>* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 133

Slide 134

Slide 134 text

࡟আؔ਺ define linkonce_odr hidden <{}>* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tWOh"(<{}>* %0) #7 { entry: %.elt = bitcast <{}>* %0 to %swift.opaque* %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo_MD") #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 1 %5 = load i8*, i8** %4, align 8, !invariant.load !19 %destroy = bitcast i8* %5 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %.elt, %swift.type* %1) #9 %6 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD") #8 %7 = bitcast %swift.type* %6 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %0 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* %11 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo0_MD") #8 %12 = bitcast %swift.type* %11 to i8*** %13 = getelementptr inbounds i8**, i8*** %12, i64 -1 %.valueWitnesses2 = load i8**, i8*** %13, align 8, !invariant.load !19, !dereferenceable !20 %14 = getelementptr inbounds i8*, i8** %.valueWitnesses2, i32 1 %15 = load i8*, i8** %14, align 8, !invariant.load !19 %destroy3 = bitcast i8* %15 to void (%swift.opaque*, %swift.type*)* call void %destroy3(%swift.opaque* noalias %.elt1, %swift.type* %11) #9 ret <{}>* %0 } 134

Slide 135

Slide 135 text

ฦΓ஋ͷλϓϧͷ0൪ཁૉͷܕΛऔಘ define linkonce_odr hidden <{}>* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tWOh"(<{}>* %0) #7 { entry: %.elt = bitcast <{}>* %0 to %swift.opaque* %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo_MD") #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 1 %5 = load i8*, i8** %4, align 8, !invariant.load !19 %destroy = bitcast i8* %5 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %.elt, %swift.type* %1) #9 %6 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD") #8 %7 = bitcast %swift.type* %6 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %0 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* %11 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo0_MD") #8 %12 = bitcast %swift.type* %11 to i8*** %13 = getelementptr inbounds i8**, i8*** %12, i64 -1 %.valueWitnesses2 = load i8**, i8*** %13, align 8, !invariant.load !19, !dereferenceable !20 %14 = getelementptr inbounds i8*, i8** %.valueWitnesses2, i32 1 %15 = load i8*, i8** %14, align 8, !invariant.load !19 %destroy3 = bitcast i8* %15 to void (%swift.opaque*, %swift.type*)* call void %destroy3(%swift.opaque* noalias %.elt1, %swift.type* %11) #9 ret <{}>* %0 } 135

Slide 136

Slide 136 text

VWTΛ࢖ͬͯ0൪ཁૉΛ࡟আ define linkonce_odr hidden <{}>* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tWOh"(<{}>* %0) #7 { entry: %.elt = bitcast <{}>* %0 to %swift.opaque* %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo_MD") #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 1 %5 = load i8*, i8** %4, align 8, !invariant.load !19 %destroy = bitcast i8* %5 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %.elt, %swift.type* %1) #9 %6 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD") #8 %7 = bitcast %swift.type* %6 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %0 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* %11 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo0_MD") #8 %12 = bitcast %swift.type* %11 to i8*** %13 = getelementptr inbounds i8**, i8*** %12, i64 -1 %.valueWitnesses2 = load i8**, i8*** %13, align 8, !invariant.load !19, !dereferenceable !20 %14 = getelementptr inbounds i8*, i8** %.valueWitnesses2, i32 1 %15 = load i8*, i8** %14, align 8, !invariant.load !19 %destroy3 = bitcast i8* %15 to void (%swift.opaque*, %swift.type*)* call void %destroy3(%swift.opaque* noalias %.elt1, %swift.type* %11) #9 ret <{}>* %0 } 136

Slide 137

Slide 137 text

λϓϧͷܕΛऔಘ define linkonce_odr hidden <{}>* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tWOh"(<{}>* %0) #7 { entry: %.elt = bitcast <{}>* %0 to %swift.opaque* %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo_MD") #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 1 %5 = load i8*, i8** %4, align 8, !invariant.load !19 %destroy = bitcast i8* %5 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %.elt, %swift.type* %1) #9 %6 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD") #8 %7 = bitcast %swift.type* %6 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %0 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* %11 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo0_MD") #8 %12 = bitcast %swift.type* %11 to i8*** %13 = getelementptr inbounds i8**, i8*** %12, i64 -1 %.valueWitnesses2 = load i8**, i8*** %13, align 8, !invariant.load !19, !dereferenceable !20 %14 = getelementptr inbounds i8*, i8** %.valueWitnesses2, i32 1 %15 = load i8*, i8** %14, align 8, !invariant.load !19 %destroy3 = bitcast i8* %15 to void (%swift.opaque*, %swift.type*)* call void %destroy3(%swift.opaque* noalias %.elt1, %swift.type* %11) #9 ret <{}>* %0 } 137

Slide 138

Slide 138 text

λϓϧͷୈ1ཁૉͷϙΠϯλΛऔಘ define linkonce_odr hidden <{}>* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tWOh"(<{}>* %0) #7 { entry: %.elt = bitcast <{}>* %0 to %swift.opaque* %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo_MD") #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 1 %5 = load i8*, i8** %4, align 8, !invariant.load !19 %destroy = bitcast i8* %5 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %.elt, %swift.type* %1) #9 %6 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD") #8 %7 = bitcast %swift.type* %6 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %0 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* %11 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo0_MD") #8 %12 = bitcast %swift.type* %11 to i8*** %13 = getelementptr inbounds i8**, i8*** %12, i64 -1 %.valueWitnesses2 = load i8**, i8*** %13, align 8, !invariant.load !19, !dereferenceable !20 %14 = getelementptr inbounds i8*, i8** %.valueWitnesses2, i32 1 %15 = load i8*, i8** %14, align 8, !invariant.load !19 %destroy3 = bitcast i8* %15 to void (%swift.opaque*, %swift.type*)* call void %destroy3(%swift.opaque* noalias %.elt1, %swift.type* %11) #9 ret <{}>* %0 } 138

Slide 139

Slide 139 text

λϓϧͷୈ1ཁૉͷܕΛऔಘ define linkonce_odr hidden <{}>* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tWOh"(<{}>* %0) #7 { entry: %.elt = bitcast <{}>* %0 to %swift.opaque* %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo_MD") #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 1 %5 = load i8*, i8** %4, align 8, !invariant.load !19 %destroy = bitcast i8* %5 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %.elt, %swift.type* %1) #9 %6 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD") #8 %7 = bitcast %swift.type* %6 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %0 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* %11 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo0_MD") #8 %12 = bitcast %swift.type* %11 to i8*** %13 = getelementptr inbounds i8**, i8*** %12, i64 -1 %.valueWitnesses2 = load i8**, i8*** %13, align 8, !invariant.load !19, !dereferenceable !20 %14 = getelementptr inbounds i8*, i8** %.valueWitnesses2, i32 1 %15 = load i8*, i8** %14, align 8, !invariant.load !19 %destroy3 = bitcast i8* %15 to void (%swift.opaque*, %swift.type*)* call void %destroy3(%swift.opaque* noalias %.elt1, %swift.type* %11) #9 ret <{}>* %0 } 139

Slide 140

Slide 140 text

VWTΛ࢖ͬͯλϓϧͷୈ1ཁૉΛ࡟আ define linkonce_odr hidden <{}>* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tWOh"(<{}>* %0) #7 { entry: %.elt = bitcast <{}>* %0 to %swift.opaque* %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo_MD") #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 1 %5 = load i8*, i8** %4, align 8, !invariant.load !19 %destroy = bitcast i8* %5 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %.elt, %swift.type* %1) #9 %6 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD") #8 %7 = bitcast %swift.type* %6 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %0 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* %11 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo0_MD") #8 %12 = bitcast %swift.type* %11 to i8*** %13 = getelementptr inbounds i8**, i8*** %12, i64 -1 %.valueWitnesses2 = load i8**, i8*** %13, align 8, !invariant.load !19, !dereferenceable !20 %14 = getelementptr inbounds i8*, i8** %.valueWitnesses2, i32 1 %15 = load i8*, i8** %14, align 8, !invariant.load !19 %destroy3 = bitcast i8* %15 to void (%swift.opaque*, %swift.type*)* call void %destroy3(%swift.opaque* noalias %.elt1, %swift.type* %11) #9 ret <{}>* %0 } 140

Slide 142

Slide 142 text

શମͷܕ ; $s1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_GMD ---> ; demangling cache variable for type metadata for ; e.C e.C>>.0> define hidden swiftcc void @"$s1f5main1yyF"() #0 { entry: %0 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_GMD") #7 %1 = bitcast %swift.type* %0 to i8*** %2 = getelementptr inbounds i8**, i8*** %1, i64 -1 %.valueWitnesses = load i8**, i8*** %2, align 8, !invariant.load !24, !dereferenceable !25 %3 = bitcast i8** %.valueWitnesses to %swift.vwtable* %4 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %3, i32 0, i32 8 %size = load i64, i64* %4, align 8, !invariant.load !24 %5 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %5) %6 = bitcast i8* %5 to %T1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_G* %7 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e11ortGeneric1AA1CVyS2iQrGyFQOyQo_MD") #7 %8 = bitcast %swift.type* %7 to i8*** %9 = getelementptr inbounds i8**, i8*** %8, i64 -1 %.valueWitnesses1 = load i8**, i8*** %9, align 8, !invariant.load !24, !dereferenceable !25 %10 = bitcast i8** %.valueWitnesses1 to %swift.vwtable* %11 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %10, i32 0, i32 8 %size2 = load i64, i64* %11, align 8, !invariant.load !24 %12 = alloca i8, i64 %size2, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %12) %13 = bitcast i8* %12 to %swift.opaque* %14 = bitcast %T1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_G* %6 to %swift.opaque* call swiftcc void @"$s1e11ortGeneric1AA1CVyS2iQrGyF"(%swift.opaque* noalias nocapture sret(%swift.opaque) %14) %15 = bitcast %T1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_G* %6 to %T1e1CV* call swiftcc void @"$s1e1CV4getCq0_yF"(%swift.opaque* noalias nocapture sret(%swift.opaque) %13, %swift.type* %0, %T1e1CV* noalias nocapture swiftself %15) %16 = call %T1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_G* @"$s1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_GWOh"(%T1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_G* %6) %17 = getelementptr inbounds i8*, i8** %.valueWitnesses1, i32 1 %18 = load i8*, i8** %17, align 8, !invariant.load !24 %destroy = bitcast i8* %18 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %13, %swift.type* %7) #8 %19 = bitcast %swift.opaque* %13 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %19) %20 = bitcast %T1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_G* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %20) ret void } 142

Slide 143

Slide 143 text

opaque result typeͷ0൪ ; $s1e11ortGeneric1AA1CVyS2iQrGyFQOyQo_MD ---> ; demangling cache variable for type metadata for << ; opaque return type of e.ortGeneric1() -> e.C ; >>.0 define hidden swiftcc void @"$s1f5main1yyF"() #0 { entry: %0 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_GMD") #7 %1 = bitcast %swift.type* %0 to i8*** %2 = getelementptr inbounds i8**, i8*** %1, i64 -1 %.valueWitnesses = load i8**, i8*** %2, align 8, !invariant.load !24, !dereferenceable !25 %3 = bitcast i8** %.valueWitnesses to %swift.vwtable* %4 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %3, i32 0, i32 8 %size = load i64, i64* %4, align 8, !invariant.load !24 %5 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %5) %6 = bitcast i8* %5 to %T1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_G* %7 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e11ortGeneric1AA1CVyS2iQrGyFQOyQo_MD") #7 %8 = bitcast %swift.type* %7 to i8*** %9 = getelementptr inbounds i8**, i8*** %8, i64 -1 %.valueWitnesses1 = load i8**, i8*** %9, align 8, !invariant.load !24, !dereferenceable !25 %10 = bitcast i8** %.valueWitnesses1 to %swift.vwtable* %11 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %10, i32 0, i32 8 %size2 = load i64, i64* %11, align 8, !invariant.load !24 %12 = alloca i8, i64 %size2, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %12) %13 = bitcast i8* %12 to %swift.opaque* %14 = bitcast %T1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_G* %6 to %swift.opaque* call swiftcc void @"$s1e11ortGeneric1AA1CVyS2iQrGyF"(%swift.opaque* noalias nocapture sret(%swift.opaque) %14) %15 = bitcast %T1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_G* %6 to %T1e1CV* call swiftcc void @"$s1e1CV4getCq0_yF"(%swift.opaque* noalias nocapture sret(%swift.opaque) %13, %swift.type* %0, %T1e1CV* noalias nocapture swiftself %15) %16 = call %T1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_G* @"$s1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_GWOh"(%T1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_G* %6) %17 = getelementptr inbounds i8*, i8** %.valueWitnesses1, i32 1 %18 = load i8*, i8** %17, align 8, !invariant.load !24 %destroy = bitcast i8* %18 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %13, %swift.type* %7) #8 %19 = bitcast %swift.opaque* %13 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %19) %20 = bitcast %T1e1CVyS2iAA11ortGeneric1ACyS2iQrGyFQOyQo_G* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %20) ret void } 143

Slide 144

Slide 144 text

opaque return typeͷ3൪ ; $s1e11ortGeneric2AA1CVyQrQR__QR0_tQR1_GyFQOyQo2_MD ---> ; demangling cache variable for type metadata for << ; opaque return type of e.ortGeneric2() -> e.C ; >>.3 define hidden swiftcc void @"$s1f5main2yyF"() #0 { entry: %0 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e1CVyAA11ortGeneric2ACyQrQR__QR0_tQR1_GyFQOyQo_AadEyFQOyQo0__AadEyFQOyQo1_tAadEyFQOyQo2_GMD") #7 %1 = bitcast %swift.type* %0 to i8*** %2 = getelementptr inbounds i8**, i8*** %1, i64 -1 %.valueWitnesses = load i8**, i8*** %2, align 8, !invariant.load !24, !dereferenceable !25 %3 = bitcast i8** %.valueWitnesses to %swift.vwtable* %4 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %3, i32 0, i32 8 %size = load i64, i64* %4, align 8, !invariant.load !24 %5 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %5) %6 = bitcast i8* %5 to %T1e1CVyAA11ortGeneric2ACyQrQR__QR0_tQR1_GyFQOyQo_AadEyFQOyQo0__AadEyFQOyQo1_tAadEyFQOyQo2_G* %7 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e11ortGeneric2AA1CVyQrQR__QR0_tQR1_GyFQOyQo2_MD") #7 %8 = bitcast %swift.type* %7 to i8*** %9 = getelementptr inbounds i8**, i8*** %8, i64 -1 %.valueWitnesses1 = load i8**, i8*** %9, align 8, !invariant.load !24, !dereferenceable !25 %10 = bitcast i8** %.valueWitnesses1 to %swift.vwtable* %11 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %10, i32 0, i32 8 %size2 = load i64, i64* %11, align 8, !invariant.load !24 %12 = alloca i8, i64 %size2, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %12) %13 = bitcast i8* %12 to %swift.opaque* %14 = bitcast %T1e1CVyAA11ortGeneric2ACyQrQR__QR0_tQR1_GyFQOyQo_AadEyFQOyQo0__AadEyFQOyQo1_tAadEyFQOyQo2_G* %6 to %swift.opaque* call swiftcc void @"$s1e11ortGeneric2AA1CVyQrQR__QR0_tQR1_GyF"(%swift.opaque* noalias nocapture sret(%swift.opaque) %14) %15 = bitcast %T1e1CVyAA11ortGeneric2ACyQrQR__QR0_tQR1_GyFQOyQo_AadEyFQOyQo0__AadEyFQOyQo1_tAadEyFQOyQo2_G* %6 to %T1e1CV* call swiftcc void @"$s1e1CV4getCq0_yF"(%swift.opaque* noalias nocapture sret(%swift.opaque) %13, %swift.type* %0, %T1e1CV* noalias nocapture swiftself %15) %16 = call %T1e1CVyAA11ortGeneric2ACyQrQR__QR0_tQR1_GyFQOyQo_AadEyFQOyQo0__AadEyFQOyQo1_tAadEyFQOyQo2_G* @"$s1e1CVyAA11ortGeneric2ACyQrQR__QR0_tQR1_GyFQOyQo_AadEyFQOyQo0__AadEyFQOyQo1_tAadEyFQOyQo2_GWOh"( %T1e1CVyAA11ortGeneric2ACyQrQR__QR0_tQR1_GyFQOyQo_AadEyFQOyQo0__AadEyFQOyQo1_tAadEyFQOyQo2_G* %6 ) %17 = getelementptr inbounds i8*, i8** %.valueWitnesses1, i32 1 %18 = load i8*, i8** %17, align 8, !invariant.load !24 %destroy = bitcast i8* %18 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %13, %swift.type* %7) #8 %19 = bitcast %swift.opaque* %13 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %19) %20 = bitcast %T1e1CVyAA11ortGeneric2ACyQrQR__QR0_tQR1_GyFQOyQo_AadEyFQOyQo0__AadEyFQOyQo1_tAadEyFQOyQo2_G* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %20) ret void } 144

Slide 145

Slide 145 text

൪߸ͷҙຯ public func ortGeneric1() -> C { ... } public func ortGeneric2() -> C { ... } // ؾ࣋ͪ public func ortGeneric1() -> C { ... } // C.C͸T0 public func ortGeneric2() -> C { ... } // C.C͸T3 Reverse GenericsͰݟͨͱ͖ͷύϥϝʔλܕͷΠϯσοΫεʹରԠ͠ ͍ͯΔ? 145

Slide 146

Slide 146 text

S-ORT ·ͱΊ • ฦΓ஋ͰsomeΛ࢖͑Δܗ͕૿͑ͨ • ϥϯλΠϜؔ਺ͰsomeΛؚΉฦΓ஋ࣗମͷܕΛऔಘͰ͖Δ • ෳ਺ͷsomeΛؚΉ৔߹ɺͦΕͧΕͷsomeʹ൪߸͕෇͍͍ͯ ͯɺݸผͷܕͷऔಘ΋Ͱ͖Δ 146

Slide 147

Slide 147 text

Named Opaque Types Reverse Generics 147

Slide 148

Slide 148 text

࣮͸΋͏࣮૷͕͋ͬͯࢼͤΔɻ $ swiftc \ -Xfrontend -enable-experimental-named-opaque-types \ -emit-module i.swift 148

Slide 149

Slide 149 text

public protocol P {} struct S: P {} public func makeTuple() -> (T, T, U) { (S(), S(), S()) } func main() { let tuple = makeTuple() } ͜͏͢Ε͹ɺReverse Parameter͸2ͭɺopaque type͸3ͭͳͷ Ͱɺ൪߸෇͚ͷنଇ͕ௐ΂ΒΕΔɻ 149

Slide 150

Slide 150 text

define hidden swiftcc void @"$s1j4mainyyF"() #0 { entry: %tuple.debug = alloca i8*, align 8 %0 = bitcast i8** %tuple.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName( { i32, i32 }* @"$s1i9makeTupleQr_QrQR_tyFQOyQo__AcaBQr_QrQR_tyFQOyQo0_tMD") #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !19 %tuple = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %tuple) %6 = bitcast i8* %tuple to <{}>* store i8* %tuple, i8** %tuple.debug, align 8 %.elt = bitcast <{}>* %6 to %swift.opaque* %7 = bitcast %swift.type* %1 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %6 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* %11 = bitcast %swift.type* %1 to %swift.tuple_type* %12 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %11, i64 0, i32 3, i64 2, i32 1 %.2.offset = load i32, i32* %12, align 8 %13 = bitcast <{}>* %6 to i8* %14 = getelementptr inbounds i8, i8* %13, i32 %.2.offset %.elt2 = bitcast i8* %14 to %swift.opaque* call swiftcc void @"$s1i9makeTupleQr_QrQR_tyF"( %swift.opaque* noalias nocapture %.elt, %swift.opaque* noalias nocapture %.elt1, %swift.opaque* noalias nocapture %.elt2) %15 = call <{}>* @"$s1i9makeTupleQr_QrQR_tyFQOyQo__AcaBQr_QrQR_tyFQOyQo0_tWOh"(<{}>* %6) %16 = bitcast <{}>* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %16) ret void } 150

Slide 151

Slide 151 text

γάωνϟ͸ some ͕3ͭɻ ; $s1i9makeTupleQr_QrQR_tyF ---> i.makeTuple() -> (some, some, some) define hidden swiftcc void @"$s1j4mainyyF"() #0 { entry: %tuple.debug = alloca i8*, align 8 %0 = bitcast i8** %tuple.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName( { i32, i32 }* @"$s1i9makeTupleQr_QrQR_tyFQOyQo__AcaBQr_QrQR_tyFQOyQo0_tMD") #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !19 %tuple = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %tuple) %6 = bitcast i8* %tuple to <{}>* store i8* %tuple, i8** %tuple.debug, align 8 %.elt = bitcast <{}>* %6 to %swift.opaque* %7 = bitcast %swift.type* %1 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %6 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* %11 = bitcast %swift.type* %1 to %swift.tuple_type* %12 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %11, i64 0, i32 3, i64 2, i32 1 %.2.offset = load i32, i32* %12, align 8 %13 = bitcast <{}>* %6 to i8* %14 = getelementptr inbounds i8, i8* %13, i32 %.2.offset %.elt2 = bitcast i8* %14 to %swift.opaque* call swiftcc void @"$s1i9makeTupleQr_QrQR_tyF"( %swift.opaque* noalias nocapture %.elt, %swift.opaque* noalias nocapture %.elt1, %swift.opaque* noalias nocapture %.elt2) %15 = call <{}>* @"$s1i9makeTupleQr_QrQR_tyFQOyQo__AcaBQr_QrQR_tyFQOyQo0_tWOh"(<{}>* %6) %16 = bitcast <{}>* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %16) ret void } 151

Slide 152

Slide 152 text

ฦΓ஋ͷܕ৘ใΛऔಘ͢ΔՕॴ define hidden swiftcc void @"$s1j4mainyyF"() #0 { entry: %tuple.debug = alloca i8*, align 8 %0 = bitcast i8** %tuple.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %1 = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName( { i32, i32 }* @"$s1i9makeTupleQr_QrQR_tyFQOyQo__AcaBQr_QrQR_tyFQOyQo0_tMD") #8 %2 = bitcast %swift.type* %1 to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !19, !dereferenceable !20 %4 = bitcast i8** %.valueWitnesses to %swift.vwtable* %5 = getelementptr inbounds %swift.vwtable, %swift.vwtable* %4, i32 0, i32 8 %size = load i64, i64* %5, align 8, !invariant.load !19 %tuple = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %tuple) %6 = bitcast i8* %tuple to <{}>* store i8* %tuple, i8** %tuple.debug, align 8 %.elt = bitcast <{}>* %6 to %swift.opaque* %7 = bitcast %swift.type* %1 to %swift.tuple_type* %8 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %7, i64 0, i32 3, i64 1, i32 1 %.1.offset = load i32, i32* %8, align 8 %9 = bitcast <{}>* %6 to i8* %10 = getelementptr inbounds i8, i8* %9, i32 %.1.offset %.elt1 = bitcast i8* %10 to %swift.opaque* %11 = bitcast %swift.type* %1 to %swift.tuple_type* %12 = getelementptr inbounds %swift.tuple_type, %swift.tuple_type* %11, i64 0, i32 3, i64 2, i32 1 %.2.offset = load i32, i32* %12, align 8 %13 = bitcast <{}>* %6 to i8* %14 = getelementptr inbounds i8, i8* %13, i32 %.2.offset %.elt2 = bitcast i8* %14 to %swift.opaque* call swiftcc void @"$s1i9makeTupleQr_QrQR_tyF"( %swift.opaque* noalias nocapture %.elt, %swift.opaque* noalias nocapture %.elt1, %swift.opaque* noalias nocapture %.elt2) %15 = call <{}>* @"$s1i9makeTupleQr_QrQR_tyFQOyQo__AcaBQr_QrQR_tyFQOyQo0_tWOh"(<{}>* %6) %16 = bitcast <{}>* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %16) ret void } 152

Slide 153

Slide 153 text

$s1i9makeTupleQr_QrQR_tyFQOyQo__AcaBQr_QrQR_tyFQOyQo0_tMD ---> demangling cache variable for type metadata for ( < (some, some, some)>>.0, < (some, some, some)>>.0, < (some, some, some)>>.1 ) λϓϧͷܕ͸ (0, 0, 1) ͳͷͰɺopaque return typeͷ൪߸ ͸ɺReverse Generic ParameterͷฒͼʹରԠ͍ͯ͠ΔͱΘ͔ Δɻ 153

Slide 154

Slide 154 text

SE-0341: Opaque Parameter Declarations func f(p: some P) { ... } // ౳Ձ func f(p: T) { ... } someΛҾ਺Ͱ࢖͑ΔɻͦΕͧΕͷsome͕ݸผͷܕύϥϝʔλ ͱͳΔɻ 154

Slide 155

Slide 155 text

Structural func foo(_ a: (some P, some P)) {} ΋ͪΖΜλϓϧͳͲͷδΣωϦοΫύϥϝʔλͷதʹ࢖͏͜ͱ ΋Ͱ͖Δɻ 155

Slide 156

Slide 156 text

Ҿ਺ͷؔ਺ͷҾ਺෦෼͸ͩΊ func foo(_ f: (some P) -> Void) {} fooͷதͰfʹ౉͢ some P Λ࡞Δํ๏͕ͳ͍ 156

Slide 157

Slide 157 text

ίʔυੜ੒΁ͷӨڹ͸ͳ͍ func foo(_ a: (some P, some P)) {} define hidden swiftcc void @"$s1g3fooyyx_q_t_tAA1PRzAaCR_r0_lF"( %swift.opaque* noalias nocapture %0, %swift.opaque* noalias nocapture %1, %swift.type* %"", %swift.type* %"1", i8** %".P", i8** %".P2" ) { ... } ; $s1g3fooyyx_q_t_tAA1PRzAaCR_r0_lF ---> ; g.foo((A, B)) -> () σϚϯάϧ͢Ε͹௨ৗͷδΣωϦΫεʹͳ͍ͬͯΔࣄ͕֬ೝͰ͖Δ 157

Slide 158

Slide 158 text

SE-0346: Lightweight same-type requirements for primary associated types func readSyntaxHighlightedLines(_ file: String) -> some Sequence<[Token]> { ... } ϓϩτίϧ໊ͷޙΖʹࡾׅ֯ހͰύϥϝʔλࢦఆͯ͠ɺ associated typeͷ੍໿Λॻ͚Δ 158

Slide 159

Slide 159 text

એݴଆͰprimaryࢦఆ͢Δ protocol Sequence { associatedtype Element associatedtype Iterator : IteratorProtocol where Element == Iterator.Element ... } ϓϩτίϧ໊ͷޙΖʹࡾׅ֯ހͰύϥϝʔλએݴ͓ͯ͘͠ɻ associated typeͷ໊લΛॻ͘ɻ 159

Slide 160

Slide 160 text

Generic Protocolͱͷিಥճආ associated type͸protocol conformanceͷࡍʹݻఆ͢Δ಺෦ύϥϝʔλ͕ͩɺ ֎෦ύϥϝʔλ͝ͱʹҟͳΔconformanceͱΈͳ͢Generic Protocolͱ͍͏ΞΠσΞ͕͋Δɻ ࡾׅ֯ހ͸কདྷͦͷΑ͏ͳػೳʹ࢖͍ͦ͏͕ͩͬͨɺࠓճผͷ༻్ʹফඅͯ͠͠·ͬͨɻ ఏҊͰ͸ɺGeneric Protocolʹ͸ؙׅހͷҊ͕ࣔ͞Ε͍ͯΔɻ protocol Convertible(from: Self, to: Other) { static func convert(_: Self) -> Other } extension Convertible(from: String, to: Int) { static func convert(_: String) -> Int } extension Convertible(from: String, to: Double) { static func convert(_: String) -> Int } 160

Slide 162

Slide 162 text

ٙ໰: ORTͱγάωνϟ // $s1g3fooQryF ---> g.foo() -> some func foo() -> some P { ... } // $s1g3fooQryF ---> g.foo() -> some func foo() -> some Q { ... } // $s1g3fooQr_QR_tyF ---> g.foo() -> (some, some) func foo() -> (some Q, some Q) { ... } ORTͷδΣωϦοΫ੍໿෦෼͸ͦΕࣗମͷ੍໿(P)΍associated type(Int)ΛؚΊશ ͘γάωνϟʹ৐Βͳ͍ͷͰɺ ੍໿Ͱ͸ΦʔόʔϩʔυͰ͖ͳ͍͕ɺܗͰ͸ΦʔόʔϩʔυͰ͖Δɻ 162

Slide 163

Slide 163 text

SE-0352: Implicitly Opened Existentials protocol P { associatedtype A } func useSomeP(_ p: some P) {} func useAnyP(_ p: any P) { useSomeP(p) } existentialΛؔ਺ݺͼग़͠ͷͱ͖ʹopenͰ͖Δɻͭ·ΓɺanyΛsomeʹม׵Ͱ͖Δɻ 163

Slide 164

Slide 164 text

ϋοΫ͕ෆཁʹͳͬͨ extension P { func callUseSomeP() { useSomeP(self) } } func useAnyP(_ p: any P) { p.callUseSomeP(p) } ٕज़తʹ͸existentialʹΑΔopenͰͰ͖͍ͯͨࣄΛɺ Ͳ͜Ͱ΋खؒͳ͠Ͱ࢖͑ΔΑ͏ʹͳͬͨͱΈͳͤΔɻ 164

Slide 165

Slide 165 text

inoutʹ΋౉ͤΔ func useSomeP(_ p: inout some P) {} func useAnyP(_ p: any P) { var p = p useSomeP(&p) } 165

Slide 166

Slide 166 text

౉ͤͳ͍ྫ func cannotOpen1(_ array: [T]) { } func cannotOpen2(_ a: T, _ b: T) { } func cannotOpen3(_ values: T...) { } struct X { } func cannotOpen4(_ x: X) { } func cannotOpen5(_ x: T, _ a: T.A) { } func cannotOpen6(_ x: T?) { } func cannotOpenDemo( array: [any P], p1: any P, p2: any P, xp: X, pOpt: (any P)? ) { cannotOpen1(array) // ཁૉͷܕ͕ҟͳΔ͔΋͠Εͳ͍͠ɺۭ͔΋͠Εͳ͍ cannotOpen2(p1, p2) // p1ͱp2ͷܕ͕ҟͳΔ͔΋͠Εͳ͍ cannotOpen3(p1, p2) // p1ͱp2ͷܕ͕ҟͳΔ͔΋͠Εͳ͍ cannotOpen4(xp) // த਎ΛऔΓग़͢ํ๏͕ͳ͍ cannotOpen5(p1, p2.getA()) // p1ͱp2ͷܕ͕ҟͳΔ͔΋͠Εͳ͍ cannotOpen5(p1, p1.getA()) // p1ͱp1.getA()ͷܕͷؔ࿈͸௥੻͞Εͳ͍ cannotOpen6(pOpt) // த਎͕ͳ͍͔΋͠Εͳ͍ } open͢Δʹ͸ any P ͷத਎ͷਅͷ஋͕ඞཁɻ 166

Slide 167

Slide 167 text

Existential Metatype Container func useSomePType(_ t: T.Type) {} func useAnyPType(_ t: any P.Type) { useSomePType(t) } ϝλλΠϓͷexistential΋openͰ͖Δ 167

Slide 168

Slide 168 text

open݁Ռͷerase protocol P { associatedtype A: AP func getA() -> A } protocol AP {} func decompose(_ p: T) -> (T, T.A) { (p, p.getA()) } func useAnyP(_ p: any P) { let (p, a) = decompose(p) } 168

Slide 169

Slide 169 text

openͨؔ͠਺ͷฦΓ஋͸upper boundͷexistentialʹerase͞Ε Δɻ func useAnyP(_ p: any P) { let (p, a): (any P, any AP) = decompose(p) } 169

Slide 170

Slide 170 text

SE-0309ͷexistentialͷ੍ݶഉআͰಋೖ͞Εͨɺcovariantͳ associated value͕erase͞ΕΔͷͱಉ͡࢓૊Έɻ func useAnyP(_ p: any P) { let a: any AP = p.getA() } 170

Slide 171

Slide 171 text

contravariantͩͱopenͰ͖ͳ͍ func makeFunc(_ p: T) -> (T) -> () { return { (_) in } } func useAnyP(_ p: any P) { // error: type 'any P' cannot conform to 'P' makeFunc(p) } 171

Slide 172

Slide 172 text

invariant΋openͰ͖ͳ͍ struct X { var t: T } func wrapX(_ p: T) -> X { ... } func useAnyP(_ p: any P) { // error: type 'any P' cannot conform to 'P' wrapX(p) } Ϣʔβఆٛgenerics͸invariantͳͷͰcontravariant 172

Slide 173

Slide 173 text

Ҿ਺ͷҾ਺͸covariant func acceptValueAndFunction(_ value: T, body: (T) -> Void) { ... } func testContravariantErasure(p: any P) { acceptValueAndFunction(p) { (innerValue: any P) in ... } } 173

Slide 174

Slide 174 text

erase͠ͳ͍Ͱͦͷ··bind͢Δ func takeP(_: U) -> Void { ... } func implicitOpeningArguments(p: any P) { acceptValueAndFunction(p, body: takeP) } takePͷU͕௚઀pͷਅͷܕʹͳΔɻ erase͔ͯ͠Β࠶౓open͍ͯ͠Δͱ΋ݟ၏ͤΔɻ 174

Slide 175

Slide 175 text

erase࣌ͷ੍໿૕ࣦ໰୊ protocol P { associatedtype A } protocol Q { associatedtype B: P where B.A == Int } func getBFromQ(_ q: T) -> T.B { ... } func eraseQAssoc(q: any Q) { let b = getBFromQ(q) } getBFromQͷฦΓ஋ͷܕ͸ where P.A == Int ͕ͩɺ b ʹerase͢Δͱ͖ʹ any P ʹͳΓɺA == Int ͷ੍໿͕૕ࣦ͢Δɻ 175

Slide 176

Slide 176 text

͜ͷ໰୊͸existential੍͕໿Λ࣋ͯͳ͍ࣄʹىҼ͢Δɻ কདྷతʹղܾͨ͠৔߹ɺb ͷܕ͸ΑΓਖ਼֬ʹͳΔ͕ɺιʔεޓ׵ੑ͕յΕΔɻ // b: any P ͳΒͬͪ͜ func f(_: T) -> Int { 17 } // b: any P ͳΒͬͪ͜ func f(_: T) -> Double where T.A == Int { 3.14159 } func eraseQAssoc(q: any Q) { let b = getBFromQ(q) // Ͳͬͪʁ f(b) } 176

Slide 177

Slide 177 text

ͦ͜Ͱɺ੍໿͕૕ࣦ͢Δeraseʹ͸໌ࣔతͳasΛڧ੍͢Δɻ func eraseQAssoc(q: any Q) { let b = getBFromQ(q) as any P } 177

Slide 178

Slide 178 text

SE-0309΋ಉ͡໰୊͕͋ͬͨͷͰ໌ࣔతͳasΛڧ੍͢Δɻ extension Q { func getBFromQ() -> B { ... } } func eraseQAssocWithSE0309(q: any Q) { let b = q.getBFromQ() as any P } 178

Slide 179

Slide 179 text

Ҿ਺ͷධՁॱͱopenͷલޙॱ໰୊ extension Int: P { } func getP() -> any P { print("getP()") return 17 } func acceptFunctionStringAndValue(body: (T) -> Void, string: String, value: T) { ... } func hello() -> String { print("hello()") return "hello" } func implicitOpeningArgumentsBackwards() { acceptFunctionStringAndValue(body: takeP, string: hello(), value: getP()) } 179

Slide 180

Slide 180 text

acceptFunctionStringAndValue(body: takeP, string: hello(), value: getP()) takePΛධՁ͢ΔͨΊʹ͸ɺ ʹਅͷܕ͕ଋറ͞Εͳ͚Ε͹ͳ Βͳ͍ɻ ͔͠͠ɺ ͸ getP ͷฦΓ஋Λopen͠ͳ͚Ε͹ܾఆͰ͖ͳ͍ɻ ͦͷ݁ՌɺgetP() → takeP → hello() ͷॱʹධՁ͞Εɺ෭࡞༻ ͱͯ͠ҎԼ͕ग़ྗ͞ΕΔɻ getP() hello() ͜Ε͸Swiftͷࠨ͔ΒӈʹҾ਺ΛධՁ͢Δنଇͱໃ६͢Δɻ 180

Slide 181

Slide 181 text

ͦ͜Ͱɺ͢ͰʹࠨଆͰ࢖ΘΕͨδΣωϦοΫύϥϝʔλΛɺ ͦΕΑΓӈଆͰopen͢Δࣄ͸Ͱ͖ͳ͍ɺͱ͍͏ϧʔϧΛ௥Ճ͢ Δɻ // error: type 'any P' cannot conform to 'P' acceptFunctionStringAndValue(body: takeP, string: hello(), value: getP()) 181

Slide 182

Slide 182 text

openͷޓ׵ੑ໰୊ func acceptsBox(_ value: T) -> Any { [value] } func passBox(p: any P) { let result = acceptsBox(p) // ͜Ε·Ͱ͸ result: [any P] // ͜Ε͔Β͸ result: [open(any P)] } 182

Slide 183

Slide 183 text

ࣗݾ४ڌ͢Δexistential(Errorͱ@objc)΋໰୊ʹͳΔɻ func takeError(_ error: E) { ... } func passError(error: any Error) { takeError(error) // ͜Ε·Ͱ͸ E = any Error // ͜Ε͔Β͸ E = open(any Error) } 183

Slide 184

Slide 184 text

কདྷɺexistentialΛࣗݾ४ڌͤ͞Δจ๏͕௥Ճ͞ΕΔ৔߹ɺ͜Ε ʹ͍ͭͯ͸ޓ׵ੑͷ໰୊͸ੜ͡ͳ͍ͷͰopen͢Δɻ extension any P: P {} 184

Slide 185

Slide 185 text

طଘͷ໰୊ʹ͍ͭͯ͸ޓ׵ੑҡ࣋ͷͨΊɺSwift5Ͱ͸open͠ͳ ͍ࣄʹ͢Δɻ Swift6Ͱ͸ޓ׵ੑഁյͰ͖ΔͷͰɺopenͰ͖Δͱ͖͸open͢Δ Α͏ʹมߋ͢Δɻ 185

Slide 186

Slide 186 text

open཈੍ه๏ ໌ࣔతͳasʹΑͬͯɺopenΛ཈੍Ͱ͖Δɻ // (1) func f(_: T) { } // (2) func f(_: T) { } func test(p: any P) { // pΛopenͯ͠(2)ΛݺͿ f(p) // pͷopenΛ཈੍͢ΔͨΊ(1)ΛݺͿ f(p as any P) } 186

Slide 187

Slide 187 text

open཈੍ͷແޮԽه๏ ؙׅހΛ෇͚Δͱopenͷ཈੍ΛແޮԽͰ͖Δ func test(p: any P) { // openͷ཈੍ΛແޮԽ͢ΔͨΊɺopenͯ͠(1)ΛݺͿ f((p as any P)) } 187

Slide 188

Slide 188 text

੍໿૕ࣦ࣌ͷasͷ໌ࣔͱͷׯব protocol P { associatedtype A } protocol Q { associatedtype B: P where B.A == Int } func getP(_ p: T) func getBFromQ(_ q: T) -> T.B { ... } func eraseQAssoc(q: any Q) { // A == Int ͕૕ࣦ͢ΔͷͰ as any P ͕ඞཁ getP(getBFromQ(q)) // ੍໿૕ࣦ͕ڐ༰͞Ε͕ͨɺopen΋཈੍͢ΔͨΊgetP͕ݺͼग़ͤͳ͍ getP(getBFromQ(q) as any P) // ੍໿૕ࣦΛڐ༰͠ɺopenͷ཈੍ΛແޮԽͨ͠ͷͰɺgetP͕ݺͼग़ͤΔ getP((getBFromQ(q) as any P)) } 188

Slide 189

Slide 189 text

҉໧ͷopen·ͱΊ • ؔ਺ݺͼग़͠ͰopenͰ͖Δ • openͨ͠ܕ͕໭ͬͯ͘Δ৔߹erase͞ΕΔ • ཈੍ه๏΋͋Δ 189

Slide 190

Slide 190 text

SE-0353: Constrained Existential Types primary associated typeΛࢦఆͨ͠existential͕࢖͑Δ any Collection 190

Slide 191

Slide 191 text

upper bound΁ͷeraseͰͷ੍໿ͷ૕ࣦΛ๷͙ protocol P { associatedtype A } protocol Q { associatedtype B: P where B.A == Int } 191

Slide 192

Slide 192 text

ExistentialͷϝϯόʹΞΫηε͢Δ࣌ extension Q { func getB() -> B } func useQ(_ q: any Q) { let b: any P = q.getB() } 192

Slide 193

Slide 193 text

Open͢Δ࣌ func getB(_ q: T) -> T.B { ... } func useQ(_ q: any Q) { let b: any P = getB(q) } 193

Slide 194

Slide 194 text

Constrained Existential Typeͷ࣮ ૷ 194

Slide 196

Slide 196 text

define hidden swiftcc void @"$s1h7useIntPyyAA1P_pySiXPF"(%T1h1P_pySiXP* noalias nocapture dereferenceable(40) %0) #0 { entry: %p.debug = alloca %T1h1P_pySiXP*, align 8 %1 = bitcast %T1h1P_pySiXP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) %2 = alloca %TSi, align 8 %a.debug = alloca i64, align 8 %3 = bitcast i64* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %3, i8 0, i64 8, i1 false) store %T1h1P_pySiXP* %0, %T1h1P_pySiXP** %p.debug, align 8 %4 = getelementptr inbounds %T1h1P_pySiXP, %T1h1P_pySiXP* %0, i32 0, i32 1 %5 = load %swift.type*, %swift.type** %4, align 8 %6 = getelementptr inbounds %T1h1P_pySiXP, %T1h1P_pySiXP* %0, i32 0, i32 2 %7 = load i8**, i8*** %6, align 8 %8 = bitcast %T1h1P_pySiXP* %0 to %__opaque_existential_type_1* %9 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %8, %swift.type* %5) #5 %10 = bitcast %TSi* %2 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %10) %11 = getelementptr inbounds i8*, i8** %7, i32 2 %12 = load i8*, i8** %11, align 8, !invariant.load !21 %13 = bitcast i8* %12 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %14 = bitcast %TSi* %2 to %swift.opaque* call swiftcc void %13(%swift.opaque* noalias nocapture sret(%swift.opaque) %14, %swift.opaque* noalias nocapture swiftself %9, %swift.type* %5, i8** %7) %._value = getelementptr inbounds %TSi, %TSi* %2, i32 0, i32 0 %15 = load i64, i64* %._value, align 8 store i64 %15, i64* %a.debug, align 8 %16 = bitcast %TSi* %2 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %16) ret void } 196

Slide 197

Slide 197 text

; $s1h7useIntPyyAA1P_pySiXPF ---> h.useIntP(h.P) -> () %T1h1P_pySiXP = type { [24 x i8], %swift.type*, i8** } define hidden swiftcc void @"$s1h7useIntPyyAA1P_pySiXPF"(%T1h1P_pySiXP* noalias nocapture dereferenceable(40) %0) #0 { ... } 197

Slide 198

Slide 198 text

IntͷϝϞϦ֬อͱopaqueܕ΁ͷม׵ define hidden swiftcc void @"$s1h7useIntPyyAA1P_pySiXPF"(%T1h1P_pySiXP* noalias nocapture dereferenceable(40) %0) #0 { entry: %p.debug = alloca %T1h1P_pySiXP*, align 8 %1 = bitcast %T1h1P_pySiXP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) %2 = alloca %TSi, align 8 %a.debug = alloca i64, align 8 %3 = bitcast i64* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %3, i8 0, i64 8, i1 false) store %T1h1P_pySiXP* %0, %T1h1P_pySiXP** %p.debug, align 8 %4 = getelementptr inbounds %T1h1P_pySiXP, %T1h1P_pySiXP* %0, i32 0, i32 1 %5 = load %swift.type*, %swift.type** %4, align 8 %6 = getelementptr inbounds %T1h1P_pySiXP, %T1h1P_pySiXP* %0, i32 0, i32 2 %7 = load i8**, i8*** %6, align 8 %8 = bitcast %T1h1P_pySiXP* %0 to %__opaque_existential_type_1* %9 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %8, %swift.type* %5) #5 %10 = bitcast %TSi* %2 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %10) %11 = getelementptr inbounds i8*, i8** %7, i32 2 %12 = load i8*, i8** %11, align 8, !invariant.load !21 %13 = bitcast i8* %12 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %14 = bitcast %TSi* %2 to %swift.opaque* call swiftcc void %13(%swift.opaque* noalias nocapture sret(%swift.opaque) %14, %swift.opaque* noalias nocapture swiftself %9, %swift.type* %5, i8** %7) %._value = getelementptr inbounds %TSi, %TSi* %2, i32 0, i32 0 %15 = load i64, i64* %._value, align 8 store i64 %15, i64* %a.debug, align 8 %16 = bitcast %TSi* %2 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %16) ret void } 198

Slide 199

Slide 199 text

openͯ͠ܕɺPWTɺ஋ͷऔΓग़͠ define hidden swiftcc void @"$s1h7useIntPyyAA1P_pySiXPF"(%T1h1P_pySiXP* noalias nocapture dereferenceable(40) %0) #0 { entry: %p.debug = alloca %T1h1P_pySiXP*, align 8 %1 = bitcast %T1h1P_pySiXP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) %2 = alloca %TSi, align 8 %a.debug = alloca i64, align 8 %3 = bitcast i64* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %3, i8 0, i64 8, i1 false) store %T1h1P_pySiXP* %0, %T1h1P_pySiXP** %p.debug, align 8 %4 = getelementptr inbounds %T1h1P_pySiXP, %T1h1P_pySiXP* %0, i32 0, i32 1 %5 = load %swift.type*, %swift.type** %4, align 8 %6 = getelementptr inbounds %T1h1P_pySiXP, %T1h1P_pySiXP* %0, i32 0, i32 2 %7 = load i8**, i8*** %6, align 8 %8 = bitcast %T1h1P_pySiXP* %0 to %__opaque_existential_type_1* %9 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %8, %swift.type* %5) #5 %10 = bitcast %TSi* %2 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %10) %11 = getelementptr inbounds i8*, i8** %7, i32 2 %12 = load i8*, i8** %11, align 8, !invariant.load !21 %13 = bitcast i8* %12 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %14 = bitcast %TSi* %2 to %swift.opaque* call swiftcc void %13(%swift.opaque* noalias nocapture sret(%swift.opaque) %14, %swift.opaque* noalias nocapture swiftself %9, %swift.type* %5, i8** %7) %._value = getelementptr inbounds %TSi, %TSi* %2, i32 0, i32 0 %15 = load i64, i64* %._value, align 8 store i64 %15, i64* %a.debug, align 8 %16 = bitcast %TSi* %2 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %16) ret void } 199

Slide 200

Slide 200 text

PWT͔Βؔ਺ͷऔΓग़͠ define hidden swiftcc void @"$s1h7useIntPyyAA1P_pySiXPF"(%T1h1P_pySiXP* noalias nocapture dereferenceable(40) %0) #0 { entry: %p.debug = alloca %T1h1P_pySiXP*, align 8 %1 = bitcast %T1h1P_pySiXP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) %2 = alloca %TSi, align 8 %a.debug = alloca i64, align 8 %3 = bitcast i64* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %3, i8 0, i64 8, i1 false) store %T1h1P_pySiXP* %0, %T1h1P_pySiXP** %p.debug, align 8 %4 = getelementptr inbounds %T1h1P_pySiXP, %T1h1P_pySiXP* %0, i32 0, i32 1 %5 = load %swift.type*, %swift.type** %4, align 8 %6 = getelementptr inbounds %T1h1P_pySiXP, %T1h1P_pySiXP* %0, i32 0, i32 2 %7 = load i8**, i8*** %6, align 8 %8 = bitcast %T1h1P_pySiXP* %0 to %__opaque_existential_type_1* %9 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %8, %swift.type* %5) #5 %10 = bitcast %TSi* %2 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %10) %11 = getelementptr inbounds i8*, i8** %7, i32 2 %12 = load i8*, i8** %11, align 8, !invariant.load !21 %13 = bitcast i8* %12 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %14 = bitcast %TSi* %2 to %swift.opaque* call swiftcc void %13(%swift.opaque* noalias nocapture sret(%swift.opaque) %14, %swift.opaque* noalias nocapture swiftself %9, %swift.type* %5, i8** %7) %._value = getelementptr inbounds %TSi, %TSi* %2, i32 0, i32 0 %15 = load i64, i64* %._value, align 8 store i64 %15, i64* %a.debug, align 8 %16 = bitcast %TSi* %2 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %16) ret void } 200

Slide 201

Slide 201 text

ؔ਺ݺͼग़͠ define hidden swiftcc void @"$s1h7useIntPyyAA1P_pySiXPF"(%T1h1P_pySiXP* noalias nocapture dereferenceable(40) %0) #0 { entry: %p.debug = alloca %T1h1P_pySiXP*, align 8 %1 = bitcast %T1h1P_pySiXP** %p.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) %2 = alloca %TSi, align 8 %a.debug = alloca i64, align 8 %3 = bitcast i64* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %3, i8 0, i64 8, i1 false) store %T1h1P_pySiXP* %0, %T1h1P_pySiXP** %p.debug, align 8 %4 = getelementptr inbounds %T1h1P_pySiXP, %T1h1P_pySiXP* %0, i32 0, i32 1 %5 = load %swift.type*, %swift.type** %4, align 8 %6 = getelementptr inbounds %T1h1P_pySiXP, %T1h1P_pySiXP* %0, i32 0, i32 2 %7 = load i8**, i8*** %6, align 8 %8 = bitcast %T1h1P_pySiXP* %0 to %__opaque_existential_type_1* %9 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1(%__opaque_existential_type_1* %8, %swift.type* %5) #5 %10 = bitcast %TSi* %2 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %10) %11 = getelementptr inbounds i8*, i8** %7, i32 2 %12 = load i8*, i8** %11, align 8, !invariant.load !21 %13 = bitcast i8* %12 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %14 = bitcast %TSi* %2 to %swift.opaque* call swiftcc void %13(%swift.opaque* noalias nocapture sret(%swift.opaque) %14, %swift.opaque* noalias nocapture swiftself %9, %swift.type* %5, i8** %7) %._value = getelementptr inbounds %TSi, %TSi* %2, i32 0, i32 0 %15 = load i64, i64* %._value, align 8 store i64 %15, i64* %a.debug, align 8 %16 = bitcast %TSi* %2 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %16) ret void } 201

Slide 202

Slide 202 text

Constrained Existential Typeͷ·ͱΊ • ࡾׅ֯ހͰͷܕύϥϝʔλࢦఆΛexistentialʹ΋ద༻ͨ͠ • upper bound͕ΑΓਖ਼֬ʹͳΔ • ར༻ՕॴͷγάωνϟʹӨڹ͢Δ • ExistentialͷϨΠΞ΢τʹ͸มԽͳ͠ 202

Slide 203

Slide 203 text

৽ػೳ·ͱΊ • someͷ༻๏͕֦େͨ͠ • any͕ಋೖ͞Εɺ༻๏͕֦େͨ͠ • upper boundʹΑΔeraseͷ֓೦͕௥Ճ͞Εͨ • ࣗવͳopen͕Ͱ͖ΔΑ͏ʹͳͬͨ • primary associated type͕ಋೖ͞Εͨ 203

Slide 204

Slide 204 text

ࠓޙͷల๬ • ඇprimaryͳassociated typeͷexistential΁ͷࢦఆ • existentialͷࣗݾ४ڌจ๏ • Reverse GenericsʹΑΔࣗ༝ͳORT 204