Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
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
460
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 Updates - Learn Languages 2025
koher
2
680
Swiftのstructとイミュータビリティ
koher
4
750
Swift 6のTyped throwsとSwiftにおけるエラーハンドリングの全体像を学ぶ
koher
4
5.4k
Swift Concurrency時代のiOSアプリの作り方
koher
15
9.1k
Swift Zoomin' #8
koher
2
650
async/awaitやactorでiOSアプリ開発がどう変わるか Before & Afterの具体例で学ぶ
koher
9
7.4k
Swift Language Updates - Learn Languages 2021
koher
8
1.8k
先取り! Swift 6 の async/await
koher
15
4.1k
SwiftUIで勘違いした話
koher
1
2.9k
Other Decks in Programming
See All in Programming
Rubyで鍛える仕組み化プロヂュース力
muryoimpl
0
140
チームをチームにするEM
hitode909
0
340
ローターアクトEクラブ アメリカンナイト:川端 柚菜 氏(Japan O.K. ローターアクトEクラブ 会長):2720 Japan O.K. ロータリーEクラブ2025年12月1日卓話
2720japanoke
0
730
ハイパーメディア駆動アプリケーションとIslandアーキテクチャ: htmxによるWebアプリケーション開発と動的UIの局所的適用
nowaki28
0
430
Full-Cycle Reactivity in Angular: SignalStore mit Signal Forms und Resources
manfredsteyer
PRO
0
150
안드로이드 9년차 개발자, 프론트엔드 주니어로 커리어 리셋하기
maryang
1
120
20251212 AI 時代的 Legacy Code 營救術 2025 WebConf
mouson
0
190
モデル駆動設計をやってみようワークショップ開催報告(Modeling Forum2025) / model driven design workshop report
haru860
0
270
S3 VectorsとStrands Agentsを利用したAgentic RAGシステムの構築
tosuri13
6
320
Github Copilotのチャット履歴ビューワーを作りました~WPF、dotnet10もあるよ~ #clrh111
katsuyuzu
0
110
AI時代を生き抜く 新卒エンジニアの生きる道
coconala_engineer
1
290
複数人でのCLI/Infrastructure as Codeの暮らしを良くする
shmokmt
5
2.3k
Featured
See All Featured
A Tale of Four Properties
chriscoyier
162
23k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
34k
Faster Mobile Websites
deanohume
310
31k
Optimising Largest Contentful Paint
csswizardry
37
3.5k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.6k
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
How STYLIGHT went responsive
nonsquared
100
6k
[SF Ruby Conf 2025] Rails X
palkan
0
540
The Language of Interfaces
destraynor
162
25k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
1.3k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.3k
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
͓͠·͍