Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Generalized existentialが内部的にすでに存在しているか調べてみた / A...
Search
Yuta Koshizawa
August 03, 2018
Programming
2
410
Generalized existentialが内部的にすでに存在しているか調べてみた / A Dive to Find Inner Generalized Existential Containers
わいわいswiftc #4
Yuta Koshizawa
August 03, 2018
Tweet
Share
More Decks by Yuta Koshizawa
See All by Yuta Koshizawa
Swiftのstructとイミュータビリティ
koher
4
700
Swift 6のTyped throwsとSwiftにおけるエラーハンドリングの全体像を学ぶ
koher
4
4.9k
Swift Concurrency時代のiOSアプリの作り方
koher
15
8.7k
Swift Zoomin' #8
koher
2
630
async/awaitやactorでiOSアプリ開発がどう変わるか Before & Afterの具体例で学ぶ
koher
9
7.1k
Swift Language Updates - Learn Languages 2021
koher
8
1.7k
先取り! Swift 6 の async/await
koher
15
4k
SwiftUIで勘違いした話
koher
1
2.9k
iOSエンジニアのための、SwiftからPythonのライブラリを使って機械学習する方法 / Machine Learning using Python from Swift for iOS Engineer
koher
5
14k
Other Decks in Programming
See All in Programming
Vibe coding コードレビュー
kinopeee
0
460
Constant integer division faster than compiler-generated code
herumi
2
690
The State of Fluid (2025)
s2b
0
190
TDD 実践ミニトーク
contour_gara
0
140
AHC051解法紹介
eijirou
0
620
CSC305 Summer Lecture 04
javiergs
PRO
1
100
Microsoft Orleans, Daprのアクターモデルを使い効率的に開発、デプロイを行うためのSekibanの試行錯誤 / Sekiban: Exploring Efficient Development and Deployment with Microsoft Orleans and Dapr Actor Models
tomohisa
0
210
Langfuseと歩む生成AI活用推進
licux
3
290
TanStack DB ~状態管理の新しい考え方~
bmthd
2
310
CEDEC2025 長期運営ゲームをあと10年続けるための0から始める自動テスト ~4000項目を50%自動化し、月1→毎日実行にした3年間~
akatsukigames_tech
0
150
新世界の理解
koriym
0
140
Honoアップデート 2025年夏
yusukebe
1
840
Featured
See All Featured
Visualization
eitanlees
146
16k
A Modern Web Designer's Workflow
chriscoyier
695
190k
How to Think Like a Performance Engineer
csswizardry
25
1.8k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
1.4k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
16k
Speed Design
sergeychernyshev
32
1.1k
The Invisible Side of Design
smashingmag
301
51k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
18
1.1k
Agile that works and the tools we love
rasmusluckow
329
21k
Side Projects
sachag
455
43k
StorybookのUI Testing Handbookを読んだ
zakiyama
30
6k
Java REST API Framework Comparison - PWX 2021
mraible
33
8.8k
Transcript
Generalized existen.al͕෦తʹ͢ Ͱʹଘࡏ͍ͯ͠Δ͔ௐͯΈͨ Yuta Koshizawa @koher
① ٙʹࢥͬͨ͜ͱ
͜ͷίʔυͷ S ͕ಛघԽ͞Εͳ͍߹ɺ sequence ͷ࣮ߦ࣌ͷ෦తදݱͲ͏ͳͬͯΔʁ func sum<S: Sequence>(of sequence: S)
-> Int where S.Element == Int { return sequence.reduce(0, +) }
ͬͱஸೡʹ
associatedtype Λ࣋ͨͳ͍ϓϩτίϧ protocol Animal {} struct Cat: Animal {} let
cat: Cat = Cat() let animal: Animal = cat // OK
ϓϩτίϧܕมͷαΠζ protocol Animal {} struct Cat: Animal { let a:
Int8 } struct Dog: Animal { let b: Int32 } let cat: Cat = Cat(a: 2) // 1 όΠτ let dog: Dog = Dog(b: 3) // 4 όΠτ // ԿόΠτʁ ! let animal: Animal = Bool.random() ? cat : dog
ܕͱϓϩτίϧܕͱσΟεύον protocol Animal { func foo() -> Int } struct
Cat: Animal { func foo() -> Int { return 2 } } struct Dog: Animal { func foo() -> Int { return 3 } } let cat: Cat = Cat() let dog: Dog = Dog() _ = cat.foo() // 2 : ੩తσΟεύον _ = dog.foo() // 3 : ੩తσΟεύον
ܕͱϓϩτίϧܕͱσΟεύον protocol Animal { func foo() -> Int } struct
Cat: Animal { func foo() -> Int { return 2 } } struct Dog: Animal { func foo() -> Int { return 3 } } let cat: Cat = Cat() let dog: Dog = Dog() let animal: Animal = Bool.random() ? cat : dog _ = animal.foo() // 2 or 3 : ಈతσΟεύον
Existen(al containers 1 struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type;
WitnessTable *witnessTables[NUM_WITNESS_TABLES]; }; 1 h$ps:/ /github.com/apple/swi6/blob/master/docs/ABI/TypeLayout.rst#existenBal-container-layout
ෳͷ Witness table Λ࣋ͭ߹ protocol P {} protocol Q {}
struct S : P, Q {} let pq: P & Q = S()
! Existen(al container ͷ͓͔͛Ͱ நతͳϓϩτίϧܕͱͯ͠ѻ͑Δ
associatedtype Λ࣋ͭϓϩτίϧ protocol Animal { associatedtype Value } struct Cat:
Animal { typealias Value = Int } let cat: Cat = Cat() let animal: Animal = cat // NG
Generalized existen.als 2 let strings : Any<Sequence where .Iterator.Element ==
String> = ["a", "b", "c"] 2 h$ps:/ /github.com/apple/swi6/blob/master/docs/GenericsManifesto.md#generalized-existenAals
associatedtype Λ࣋ͭϓϩτίϧ protocol Animal { associatedtype Value } struct Cat:
Animal { typealias Value = Int } let cat: Cat = Cat() let animal: Any<Animal where .Value == Int> = cat // Generalized existential Ͱ͜Ε͕Ͱ͖ΔΑ͏ʹͳΔ͔
! Generalized existen.al ͕ͳ͍ͷͰ associatedype ͕͋Δͱ ϓϩίτϧܕͱͯ͠ѻ͑ͳ͍
Ͱɺ͜ΕͰ͖Δ protocol Animal { associatedtype Value } struct Cat: Animal
{ typealias Value = Int } func useAnimal<A: Animal>(_ animal: A) -> Int where A.Value == Int { ... } useAnimal(Cat()) // ✅ OK
A ͕ Cat ʹಛघԽ͞ΕΔͱ͜͏ͳΔ protocol Animal { associatedtype Value }
struct Cat: Animal { typealias Value = Int } func useAnimal(_ animal: Cat) -> Int { ... } useAnimal(Cat()) // ✅ OK
ಛघԽ͞Εͳ͍ͱͲ͏ͳΔʁ protocol Animal { associatedtype Value } struct Cat: Animal
{ typealias Value = Int } func useAnimal<A: Animal>(_ animal: A) -> Int where A.Value == Int { ... } useAnimal(Cat()) // `Cat` ͲͷΑ͏ʹѻΘΕΔʁ
! ͔ͯ͠͠෦తʹ Existen(al ʹͳ͍ͬͯΔͷͰʁ
② LLVM IR Ͱ෦తදݱΛௐࠪ
associatedtype ͕ ͳ͍ ͱ͖
associatedtype ͕ ͳ͍ ͱ͖ protocol Animal { func foo() ->
Int } struct Cat: Animal { var value: Int = 42 func foo() -> Int { return value } }
associatedtype ͕ ͳ͍ ͱ͖ func useAnimal(_ animal: Animal) -> Int
{ return animal.foo() } func useCat(_ cat: Cat) -> Int { return useAnimal(cat) } print(useCat(Cat()))
associatedtype ͕ ͳ͍ ͱ͖ func useAnimal(_ animal: Animal) -> Int
{ return animal.foo() } func useCat(_ cat: Cat) -> Int { return useAnimal(cat) } print(useCat(Cat()))
swiftc -emit-ir foo.swift
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 }
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } $S4main9useAnimalySiAA0C0_pF ʹϚϯάϦϯά͞ΕͯΔ
swift demangle S4main9useAnimalySiAA0C0_pF
σϚϯάϦϯάͷ݁Ռ $ swift demangle S4main9useAnimalySiAA0C0_pF $S4main9useAnimalySiAA0C0_pF ---> main.useAnimal(main.Animal) -> Swift.Int
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } ͜Ε main.useAnimal(main.Animal) -> Swift.Int
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } %T4main6AnimalP* ܕͷҾ͕Ұͭ
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** }
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTables[NUM_WITNESS_TABLES]; };
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTables[NUM_WITNESS_TABLES]; };
Witness tables ͱϙΠϯλܕ • i8* : witness table ͷཁૉ •
i8** : witness table • i8*** : witness table ͷू·Γ = witnessTables
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTables[NUM_WITNESS_TABLES]; };
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTable; };
ෳͷ Witness table Λ࣋ͭ߹ protocol P {} protocol Q {}
struct S : P, Q {} let pq: P & Q = S() ↓ LLVM IR ( P & Q ) %T4main1P_AA1Qp = type { [24 x i8], %swift.type*, i8**, i8** }
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } Ҿͱͯ͠ Existen)al container Λड͚औ͍ͬͯΔ
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { // 40 όΠτ void *fixedSizeBuffer[3]; // 24 όΠτ Metadata *type; // 8 όΠτ WitnessTable *witnessTable; // 8 όΠτ };
Existen(al container ͷαΠζ protocol P {} protocol Q {} print(MemoryLayout<P>.size)
// 40 print(MemoryLayout<P & Q>.size) // 48
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } Ҿͱͯ͠ 40 όΠτͷ Existen+al container Λड͚औ͍ͬͯΔ
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } getelementptr ͱʁ
getelementptr 3 <result> = getelementptr <ty>, <ty>* <ptrval>{, [inrange] <ty>
<idx>}* <result> = getelementptr inbounds <ty>, <ty>* <ptrval>{, [inrange] <ty> <idx>}* 3 h$p:/ /llvm.org/docs/LangRef.html#getelementptr-instruc=on
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 // getelementptr inbounds <ty>, <ty>* <ptrval>, <ty> <idx>, <ty> <idx> %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } 0 ൪ͷ %T4main6AnimalP ͷ 1 ൪ͷϝϯόͷϙΠϯλΛऔಘ
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTable; };
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } type ͷϙΠϯλΛऔಘ
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } type Λϩʔυ
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } 0 ൪ͷ %T4main6AnimalP ͷ 2 ൪ͷϝϯόͷϙΠϯλΛऔಘ
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTable; };
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } witnessTable ͷϙΠϯλΛऔಘ
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } witnessTable Λϩʔυ
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } 0 ൪ͷ %T4main6AnimalP ͷ 0 ൪ͷϝϯόͷϙΠϯλΛऔಘ
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTable; };
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } fixedSizeBuffer ͷϙΠϯλΛऔಘ
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } fixedSizeBuffer ͷ࣮ମͷϙΠϯλΛऔಘ
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } witnessTable ͔Β 1 ൪ͷཁૉͷϙΠϯλΛऔಘ
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } witnessTable ͷ 1 ൪ͷཁૉΛϩʔυ
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } foo Λදؔ͢ܕϙΠϯλʹΩϟετ
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } foo Λίʔϧ
associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias
nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } foo ͷΓΛ return
associatedtype ͕ ͋Δ ͱ͖
associatedtype ͕ ͋Δ ͱ͖ protocol Animal { associatedtype Value func
foo() -> Value } struct Cat: Animal { var value: Int = 42 func foo() -> Int { return value } }
associatedtype ͕ ͋Δ ͱ͖ func useAnimal<A: Animal>(_ animal: A) ->
Int where A.Value == Int { return animal.foo() } func useCat(_ cat: Cat) -> Int { return useAnimal(cat) } print(useCat(Cat()))
associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias
nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 }
associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias
nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 } ࡾͭͷҾ: Existen*al container Ͱͳ͘࠷ॳ͔Βղ͞ΕͯΔ
associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias
nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 } ಉ͡Α͏ʹࡾͭΛ༩͑ͯؔΛίʔϧ
associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias
nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 } %5 Witness table ͔ΒऔΓग़͞Εͨ foo Λදؔ͢ϙΠϯλ
associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias
nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 } %6 ͜ͷؔͰ֬อ͞ΕͨະॳظԽͷ Int → ݁ՌΛ֨ೲ
associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias
nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 } %1 %7 Λհͯ͠ return ͞ΕΔ
associatedtype ͕ ͋Δ ͱ͖ protocol Animal { associatedtype Value func
foo() -> Value } struct Cat: Animal { var value: Int = 42 func foo() -> Int { return value } }
associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias
nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 } Γͷܕ͕ܾ·ͬͯͳ͍ͷͰ opaque ϙΠϯλΛհͯ݁͠ՌΛ ฦ͢ඞཁ͕͋ͬͨʢͱࢥΘΕΔʣ
associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias
nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 } %A.Animal ຊʹ Witness table ʁ
associatedtype ͕ ͋Δ ͱ͖ func useAnimal<A: Animal>(_ animal: A) ->
Int where A.Value == Int { return animal.foo() } func useCat(_ cat: Cat) -> Int { return useAnimal(cat) } print(useCat(Cat()))
associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main6useCatySiAA0C0VF"(i64) #0
{ entry: %1 = alloca %T4main3CatV, align 8 %2 = bitcast %T4main3CatV* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %.value = getelementptr inbounds %T4main3CatV, %T4main3CatV* %1, i32 0, i32 0 %.value._value = getelementptr inbounds %TSi, %TSi* %.value, i32 0, i32 0 store i64 %0, i64* %.value._value, align 8 %3 = bitcast %T4main3CatV* %1 to %swift.opaque* %4 = call swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"( %swift.opaque* noalias nocapture %3, %swift.type* bitcast ( i64* getelementptr inbounds ( <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>, <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>* @"$S4main3CatVMf", i32 0, i32 1 ) to %swift.type* ), i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @"$S4main3CatVAA6AnimalAAWP", i32 0, i32 0) ) %5 = bitcast %T4main3CatV* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %5) ret i64 %4 } useCat ͷ LLVM IR
associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main6useCatySiAA0C0VF"(i64) #0
{ entry: %1 = alloca %T4main3CatV, align 8 %2 = bitcast %T4main3CatV* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %.value = getelementptr inbounds %T4main3CatV, %T4main3CatV* %1, i32 0, i32 0 %.value._value = getelementptr inbounds %TSi, %TSi* %.value, i32 0, i32 0 store i64 %0, i64* %.value._value, align 8 %3 = bitcast %T4main3CatV* %1 to %swift.opaque* %4 = call swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"( %swift.opaque* noalias nocapture %3, %swift.type* bitcast ( i64* getelementptr inbounds ( <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>, <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>* @"$S4main3CatVMf", i32 0, i32 1 ) to %swift.type* ), i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @"$S4main3CatVAA6AnimalAAWP", i32 0, i32 0) ) %5 = bitcast %T4main3CatV* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %5) ret i64 %4 } ͜͜Ͱ useAnimal Λίʔϧ
associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main6useCatySiAA0C0VF"(i64) #0
{ entry: %1 = alloca %T4main3CatV, align 8 %2 = bitcast %T4main3CatV* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %.value = getelementptr inbounds %T4main3CatV, %T4main3CatV* %1, i32 0, i32 0 %.value._value = getelementptr inbounds %TSi, %TSi* %.value, i32 0, i32 0 store i64 %0, i64* %.value._value, align 8 %3 = bitcast %T4main3CatV* %1 to %swift.opaque* %4 = call swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"( %swift.opaque* noalias nocapture %3, %swift.type* bitcast ( i64* getelementptr inbounds ( <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>, <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>* @"$S4main3CatVMf", i32 0, i32 1 ) to %swift.type* ), i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @"$S4main3CatVAA6AnimalAAWP", i32 0, i32 0) ) %5 = bitcast %T4main3CatV* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %5) ret i64 %4 } ୈ 3 Ҿ
S4main3CatVAA6AnimalAAWP ΛσϚϯάϦϯά $ swift demangle S4main3CatVAA6AnimalAAWP $S4main3CatVAA6AnimalAAWP ---> protocol witness
table for main.Cat : main.Animal in main
S4main3CatVAA6AnimalAAWP ΛσϚϯάϦϯά $ swift demangle S4main3CatVAA6AnimalAAWP $S4main3CatVAA6AnimalAAWP ---> protocol witness
table for main.Cat : main.Animal in main ^^^^^^^^^^^^^^^^^^^^^^^^^^
associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main6useCatySiAA0C0VF"(i64) #0
{ entry: %1 = alloca %T4main3CatV, align 8 %2 = bitcast %T4main3CatV* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %.value = getelementptr inbounds %T4main3CatV, %T4main3CatV* %1, i32 0, i32 0 %.value._value = getelementptr inbounds %TSi, %TSi* %.value, i32 0, i32 0 store i64 %0, i64* %.value._value, align 8 %3 = bitcast %T4main3CatV* %1 to %swift.opaque* %4 = call swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"( %swift.opaque* noalias nocapture %3, %swift.type* bitcast ( i64* getelementptr inbounds ( <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>, <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>* @"$S4main3CatVMf", i32 0, i32 1 ) to %swift.type* ), i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @"$S4main3CatVAA6AnimalAAWP", i32 0, i32 0) ) %5 = bitcast %T4main3CatV* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %5) ret i64 %4 } ୈ 3 Ҿʹ Witness table Λ͢
associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias
nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 } ࡾͭͷҾ Existen)al container ͱՁ
! Existen(al container Ͱ ͞ͳ͍ͷͳͥʁ
associatedtype ͕ ͋Δ ͱ͖ func useAnimal<A: Animal>(_ animal: A) ->
Int where A.Value == Int { return animal.foo() } func useCat(_ cat: Cat) -> Int { return useAnimal(cat) } print(useCat(Cat()))
A ܕ useCat ͷத͚ͩͷܕ
! useCat ͷϩʔΧϧείʔϓͰ औΓѻ͑Εྑ͍
! Existen(al container Ͱ औΓճ͢ඞཁͳ͍
! Existen(al container Ͱ แΜͩΓղͨ͠Γ͢Δͱ Φʔόʔϔου͕ൃੜ
! ͦΕͳΒ Existen)al ʹͤͣ ࠷ॳ͔ΒΒΒʹѻ͓͏ ʢͱ͍͏͜ͱͰʁʣ
ʲॳͷٙʳ ͔ͯ͠͠෦తʹ Existen(al ʹͳ͍ͬͯΔͷͰʁ
! Generalized existen.al ෦తʹଘࡏ͠ͳ͔ͬͨ
! Ͱ useCat<A:Animal>(_:) Existen(al ͱࣅͨΈͰಈ͍ͯͨ
None
΄΅ಉ͜͡ͱ͕͔֬ΊΒΕͯͨ 4 4 h$ps:/ /qiita.com/omochimetaru/items/b41e7699ea25a324aefa
͓͠·͍