Slide 1

Slide 1 text

SILΛಡ΋͏ @omochimetaru SwiftcKaigi #1 1

Slide 2

Slide 2 text

ࣗݾ঺հ • omochimetaru • ΞΠίϯˠ • Θ͍Θ͍swiftcͰ͠͹͠͹ ొஃ 2

Slide 3

Slide 3 text

SIL1 • Swift intermediate language • SILίʔυʹ͸SwiftίʔυΑΓ΋۩ମతͳڍಈ ͕ॻ͔Ε͍ͯΔ 1 https://github.com/apple/swift/blob/master/docs/SIL.rst 3

Slide 4

Slide 4 text

۩ମతͳڍಈͷྫ • ҉໧ͷܕม׵ • ࢀরΧ΢ϯτͷ૿ݮ • ϝιουͷݺͼग़͠ 4

Slide 5

Slide 5 text

҉໧ͷܕม׵ 5

Slide 6

Slide 6 text

func intToIntOptional(x: Int) -> Int? { return x } • Swiftతʹ͸ͦͷ··return͍ͯ͠Δ͕ɺCPUʹ ͱͬͯ͸Int͔ΒInt?΁ͷม׵Λ͍ͯ͠Δɻ 6

Slide 7

Slide 7 text

• swiftcίϚϯυͰSILΛग़ྗ͢Δ $ swiftc -emit-sil -parse-as-library code01.swift 7

Slide 8

Slide 8 text

sil_stage canonical import Builtin import Swift import SwiftShims func intToIntOptional(x: Int) -> Int? // intToIntOptional(x:) sil hidden @$s6code0116intToIntOptional1xSiSgSi_tF : $@convention(thin) (Int) -> Optional { // %0 // users: %2, %1 bb0(%0 : $Int): debug_value %0 : $Int, let, name "x", argno 1 // id: %1 %2 = enum $Optional, #Optional.some!enumelt.1, %0 : $Int // user: %3 return %2 : $Optional // id: %3 } // end sil function '$s6code0116intToIntOptional1xSiSgSi_tF' 8

Slide 9

Slide 9 text

Mangling2 // module: code01 func intToIntOptional(x: Int) -> Int? ↓ $s6code0116intToIntOptional1xSiSgSi_tF 2 https://github.com/apple/swift/blob/master/docs/ABI/Mangling.rst 9

Slide 10

Slide 10 text

• Ϟδϡʔϧ໊΍ܕ໊ΛࠞͥࠐΜͩ(mangle)໊લ Λ࡞Δ • swift demangleίϚϯυͰల։Ͱ͖Δ $ swift demangle '$s6code0116intToIntOptional1xSiSgSi_tF' $s6code0116intToIntOptional1xSiSgSi_tF ---> code01.intToIntOptional(x: Swift.Int) -> Swift.Int? 10

Slide 11

Slide 11 text

Demangling $s6code0116intToIntOptional1xSiSgSi_tF $s: Swift5 6: 6จࣈͷ୯ޠ code01 16: 16จࣈͷ୯ޠ intToIntOptional 1: 1จࣈͷ୯ޠ x Si: Int Sg: Optional Si: Int _: Ϧετͷ۠੾Γ t: λϓϧ F: ؔ਺ 11

Slide 12

Slide 12 text

// intToIntOptional(x:) sil hidden @$s6code0116intToIntOptional1xSiSgSi_tF : $@convention(thin) (Int) -> Optional { // %0 // users: %2, %1 bb0(%0 : $Int): debug_value %0 : $Int, let, name "x", argno 1 // id: %1 %2 = enum $Optional, #Optional.some!enumelt.1, %0 : $Int // user: %3 return %2 : $Optional // id: %3 } // end sil function '$s6code0116intToIntOptional1xSiSgSi_tF' 12

Slide 13

Slide 13 text

// intToIntOptional(x:) sil hidden @$s6code0116intToIntOptional1xSiSgSi_tF : $@convention(thin) (Int) -> Optional { // %0 // users: %2, %1 bb0(%0 : $Int): debug_value %0 : $Int, let, name "x", argno 1 // id: %1 %2 = enum $Optional, #Optional.some!enumelt.1, %0 : $Int // user: %3 return %2 : $Optional // id: %3 } // end sil function '$s6code0116intToIntOptional1xSiSgSi_tF' 13

Slide 14

Slide 14 text

%2 = enum $Optional, #Optional.some!enumelt.1, %0 : $Int // user: %3 %2 =: ݁ՌΛ%2ʹ୅ೖ enum: enumͷ஋Λߏங $Optional: ܕ͸Optional $Optional.some!enumelt.1: case͸some %0: associated value͸%0 : $Int: $0ͷܕ͸Int //: ίϝϯτ user: %3: ݁Ռ͸໋ྩ%3Ͱ࢖͏ 14

Slide 15

Slide 15 text

ࢀরΧ΢ϯτͷ૿ݮ 15

Slide 16

Slide 16 text

ࢀরΧ΢ϯτ • Swift͸ΫϥεΠϯελϯεͷϝϞϦ؅ཧʹࢀর Χ΢ϯτΛ࢖͏ 16

Slide 17

Slide 17 text

• ॳظ஋1 • 0ʹͳͬͨΒղ์ • ม਺୅ೖ: ݹ͍Πϯελϯε͸release(-1) • ม਺ഁغ: ॴ࣋͢ΔΠϯελϯεΛrelease • ؔ਺ݺͼग़͠: ࣮Ҿ਺Λretain(+1), ݺͼग़͠ޙ ʹrelease 17

Slide 18

Slide 18 text

class Cat {} func useCat(_ cat: Cat) { } func changeCat(_ cat: Cat) -> Cat { return Cat() } func main() { var cat = Cat() useCat(cat) cat = changeCat(cat) } 18

Slide 19

Slide 19 text

func main() { // ॳظԽ var cat = Cat() // ݺͼग़͠લʹҾ਺ͷretain useCat(cat) // ݺͼग़͠ޙʹҾ਺ͷrelease // ݺͼग़͠લʹҾ਺ͷretain cat = changeCat(cat) // ݺͼग़͠ޙʹҾ਺ͷrelease // ݹ͍஋Λrelease // ม਺ͷ஋Λrelease } 19

Slide 20

Slide 20 text

// main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> () { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' 20

Slide 21

Slide 21 text

// main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> () { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' • ม਺catΛੜ੒(%0) 21

Slide 22

Slide 22 text

// main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> () { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' • ม਺cat(%0)Λղ์ 22

Slide 23

Slide 23 text

// main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> () { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' • Cat.initͷݺͼग़͠(%3)ɺม਺cat(%0)ʹอଘ 23

Slide 24

Slide 24 text

// main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> () { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' • useCatͷݺͼग़͠Ͱ%3Λ౉͢ 24

Slide 25

Slide 25 text

// main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> () { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' • useCatͷݺͼग़͠લޙͰ%3Λretain, release 25

Slide 26

Slide 26 text

// main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> () { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' • changeCatͷݺͼग़͠(%15)ɺҾ਺ʹ%3 26

Slide 27

Slide 27 text

// main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> () { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' • changeCatͷݺͼग़͠લޙͰ%3Λretain, release 27

Slide 28

Slide 28 text

// main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> () { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' • changeCatͷ݁Ռ(%15)Λม਺cat(%17=%0)ʹ୅ೖɺ ݹ͍஋(%3)Λrelease 28

Slide 29

Slide 29 text

ϝιουݺͼग़͠ 29

Slide 30

Slide 30 text

ϓϩτίϧͷσϑΥϧτ࣮૷ͱΫϥε ܧঝͷؔ܎͸΍΍͍͜͠ • Swift Forum: Default Protocol Implementation Inheritance Behaviour - The current situation and what/if anything should be done about it 3 2019/08/20 3 https://forums.swift.org/t/default-protocol-implementation-inheritance-behaviour-the-current- situation-and-what-if-anything-should-be-done-about-it/28049 30

Slide 31

Slide 31 text

31

Slide 32

Slide 32 text

• ఆظతʹ۷Γฦ͞ΕΔ࿩୊ • ͜ͷ౤ߘͰ΋Πγϡʔνέοτ4 2015/12/7 ΁ ͷݴٴ͋Γ 4 https://bugs.swift.org/browse/SR-103 32

Slide 33

Slide 33 text

33

Slide 34

Slide 34 text

protocol P { func f() } extension P { func f() { print("P.f") } } class A: P { func f() { print("A.f") } } class B: A { override func f() { print("B.f") } } class C: P { } class D: C { func f() { print("D.f") } } func main() { A().f() // A.f B().f() // B.f (B() as A).f() // B.f C().f() // P.f D().f() // D.f (D() as C).f() // P.f } main() 34

Slide 35

Slide 35 text

• B͸AΛܧঝ͍ͯ͠Δͷ͔ͩΒɺBͷfΛͦͷ· ·ݺΜͰ΋ɺAʹΞοϓΩϟετ͔ͯ͠ΒݺΜ Ͱ΋ಉ͡ ! • D͸CΛܧঝ͍ͯ͠ΔͷʹɺDͷfΛͦͷ··ݺ ͿͷͱɺCʹΞοϓΩϟετ͔ͯ͠ΒݺͿͷͰ ݁Ռ͕ҧ͏ " 35

Slide 36

Slide 36 text

ܗࣜతͳճ౴ • A.fͱB.f͸Ϋϥεϝιουݺͼग़͠ͳͷͰɺ ΦʔόʔϥΠυ͞Ε࣮ͨ૷͕ݺ͹ΕΔ • C.f͸witnessϝιουݺͼग़͠ɺD.f͸Ϋϥεϝ ιουݺͼग़͠ͳͷͰɺΦʔόʔϥΠυؔ܎͸ ͳ͍ 36

Slide 37

Slide 37 text

Swiftͷ2ͭͷϝιουݺͼग़͠ • Ϋϥεϝιουݺͼग़͠: ͋ΔΫϥεʹରԠ͢ Δvtable͔ΒϝιουΛҾ͘ • witnessϝιουݺͼग़͠: ͋Δϓϩτίϧʹର Ԡ͢Δwitness table͔ΒϝιουΛҾ͘ 37

Slide 38

Slide 38 text

࣮૷͞Εͨؔ਺6ͭ // P.f() sil hidden @$s6code031PPAAE1fyyF : $@convention(method) (@in_guaranteed Self) -> () { ... } // A.f() sil hidden @$s6code031AC1fyyF : $@convention(method) (@guaranteed A) -> () { ... } // protocol witness for P.f() in conformance A sil private [transparent] [thunk] @$s6code031ACAA1PA2aDP1fyyFTW : $@convention(witness_method: P) (@in_guaranteed A) -> () { ... } // B.f() sil hidden @$s6code031BC1fyyF : $@convention(method) (@guaranteed B) -> () { ... } // protocol witness for P.f() in conformance C sil private [transparent] [thunk] @$s6code031CCAA1PA2aDP1fyyFTW : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : C> (@in_guaranteed τ_0_0) -> () { ... } // D.f() sil hidden @$s6code031DC1fyyF : $@convention(method) (@guaranteed D) -> () { ... } 38

Slide 39

Slide 39 text

ੜ੒͞Εͨςʔϒϧ6ͭ sil_vtable A { #A.f!1: (A) -> () -> () : @$s6code031AC1fyyF // A.f() #A.init!allocator.1: (A.Type) -> () -> A : @$s6code031ACACycfC // A.__allocating_init() #A.deinit!deallocator.1: @$s6code031ACfD // A.__deallocating_deinit } sil_vtable B { #A.f!1: (A) -> () -> () : @$s6code031BC1fyyF [override] // B.f() #A.init!allocator.1: (A.Type) -> () -> A : @$s6code031BCACycfC [override] // B.__allocating_init() #B.deinit!deallocator.1: @$s6code031BCfD // B.__deallocating_deinit } sil_vtable C { #C.init!allocator.1: (C.Type) -> () -> C : @$s6code031CCACycfC // C.__allocating_init() #C.deinit!deallocator.1: @$s6code031CCfD // C.__deallocating_deinit } sil_vtable D { #C.init!allocator.1: (C.Type) -> () -> C : @$s6code031DCACycfC [override] // D.__allocating_init() #D.f!1: (D) -> () -> () : @$s6code031DC1fyyF // D.f() #D.deinit!deallocator.1: @$s6code031DCfD // D.__deallocating_deinit } sil_witness_table hidden A: P module code03 { method #P.f!1: (Self) -> () -> () : @$s6code031ACAA1PA2aDP1fyyFTW // protocol witness for P.f() in conformance A } sil_witness_table hidden C: P module code03 { method #P.f!1: (Self) -> () -> () : @$s6code031CCAA1PA2aDP1fyyFTW // protocol witness for P.f() in conformance C } 39

Slide 40

Slide 40 text

// main() sil hidden @$s6code034mainyyF : $@convention(thin) () -> () { bb0: %0 = metatype $@thick A.Type // user: %2 // function_ref A.__allocating_init() %1 = function_ref @$s6code031ACACycfC : $@convention(method) (@thick A.Type) -> @owned A // user: %2 %2 = apply %1(%0) : $@convention(method) (@thick A.Type) -> @owned A // users: %5, %4, %3 %3 = class_method %2 : $A, #A.f!1 : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () // user: %4 %4 = apply %3(%2) : $@convention(method) (@guaranteed A) -> () strong_release %2 : $A // id: %5 %6 = metatype $@thick B.Type // user: %8 // function_ref B.__allocating_init() %7 = function_ref @$s6code031BCACycfC : $@convention(method) (@thick B.Type) -> @owned B // user: %8 %8 = apply %7(%6) : $@convention(method) (@thick B.Type) -> @owned B // users: %11, %10, %9 %9 = class_method %8 : $B, #B.f!1 : (B) -> () -> (), $@convention(method) (@guaranteed B) -> () // user: %10 %10 = apply %9(%8) : $@convention(method) (@guaranteed B) -> () strong_release %8 : $B // id: %11 %12 = metatype $@thick B.Type // user: %14 // function_ref B.__allocating_init() %13 = function_ref @$s6code031BCACycfC : $@convention(method) (@thick B.Type) -> @owned B // user: %14 %14 = apply %13(%12) : $@convention(method) (@thick B.Type) -> @owned B // user: %15 %15 = upcast %14 : $B to $A // users: %18, %17, %16 %16 = class_method %15 : $A, #A.f!1 : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () // user: %17 %17 = apply %16(%15) : $@convention(method) (@guaranteed A) -> () strong_release %15 : $A // id: %18 %19 = metatype $@thick C.Type // user: %21 // function_ref C.__allocating_init() %20 = function_ref @$s6code031CCACycfC : $@convention(method) (@thick C.Type) -> @owned C // user: %21 %21 = apply %20(%19) : $@convention(method) (@thick C.Type) -> @owned C // user: %23 %22 = alloc_stack $C // users: %23, %27, %26, %25 store %21 to %22 : $*C // id: %23 // function_ref P.f() %24 = function_ref @$s6code031PPAAE1fyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %25 %25 = apply %24(%22) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () destroy_addr %22 : $*C // id: %26 dealloc_stack %22 : $*C // id: %27 %28 = metatype $@thick D.Type // user: %30 // function_ref D.__allocating_init() %29 = function_ref @$s6code031DCACycfC : $@convention(method) (@thick D.Type) -> @owned D // user: %30 %30 = apply %29(%28) : $@convention(method) (@thick D.Type) -> @owned D // users: %33, %32, %31 %31 = class_method %30 : $D, #D.f!1 : (D) -> () -> (), $@convention(method) (@guaranteed D) -> () // user: %32 %32 = apply %31(%30) : $@convention(method) (@guaranteed D) -> () strong_release %30 : $D // id: %33 %34 = metatype $@thick D.Type // user: %36 // function_ref D.__allocating_init() %35 = function_ref @$s6code031DCACycfC : $@convention(method) (@thick D.Type) -> @owned D // user: %36 %36 = apply %35(%34) : $@convention(method) (@thick D.Type) -> @owned D // user: %37 %37 = upcast %36 : $D to $C // user: %39 %38 = alloc_stack $C // users: %39, %43, %42, %41 store %37 to %38 : $*C // id: %39 // function_ref P.f() %40 = function_ref @$s6code031PPAAE1fyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %41 %41 = apply %40<(C)>(%38) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () destroy_addr %38 : $*C // id: %42 dealloc_stack %38 : $*C // id: %43 %44 = tuple () // user: %45 return %44 : $() // id: %45 } // end sil function '$s6code034mainyyF' 40

Slide 41

Slide 41 text

ؔ਺ͷ಺༁ • P.f(): $s6code031PPAAE1fyyF • A.f(): $s6code031AC1fyyF • protocol witness for P.f() in conformance A: $s6code031ACAA1PA2aDP1fyyFTW • B.f(): $s6code031BC1fyyF • protocol witness for P.f() in conformance C: $s6code031CCAA1PA2aDP1fyyFTW • D.f(): $s6code031DC1fyyF 41

Slide 42

Slide 42 text

• A.fʹؔͯ͠͸Ϋϥεϝιουͱɺwitnessϝ ιουͷ2͕ͭੜ੒͞Ε͍ͯΔ class A: P { func f() { print("A.f") } } 42

Slide 43

Slide 43 text

• C.fʹؔͯ͠͸witnessϝιου͚͕ͩੜ੒͞Ε ͍ͯͯɺΫϥεϝιου͸ͳ͍ class C: P { } 43

Slide 44

Slide 44 text

A.fͷwitnessϝιουͷ࣮૷ // protocol witness for P.f() in conformance A sil private [transparent] [thunk] @$s6code031ACAA1PA2aDP1fyyFTW : $@convention(witness_method: P) (@in_guaranteed A) -> () { // %0 // user: %1 bb0(%0 : $*A): %1 = load %0 : $*A // users: %2, %3 %2 = class_method %1 : $A, #A.f!1 : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () // user: %3 %3 = apply %2(%1) : $@convention(method) (@guaranteed A) -> () %4 = tuple () // user: %5 return %4 : $() // id: %5 } // end sil function '$s6code031ACAA1PA2aDP1fyyFTW' 44

Slide 45

Slide 45 text

// protocol witness for P.f() in conformance A sil private [transparent] [thunk] @$s6code031ACAA1PA2aDP1fyyFTW : $@convention(witness_method: P) (@in_guaranteed A) -> () { // %0 // user: %1 bb0(%0 : $*A): %1 = load %0 : $*A // users: %2, %3 %2 = class_method %1 : $A, #A.f!1 : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () // user: %3 %3 = apply %2(%1) : $@convention(method) (@guaranteed A) -> () %4 = tuple () // user: %5 return %4 : $() // id: %5 } // end sil function '$s6code031ACAA1PA2aDP1fyyFTW' • class_method໋ྩͰvtable͔Βؔ਺ΛऔΓग़ ͠ɺݺͼग़͢ɻ 45

Slide 46

Slide 46 text

C.fͷwitnessϝιουͷ࣮૷ // protocol witness for P.f() in conformance C sil private [transparent] [thunk] @$s6code031CCAA1PA2aDP1fyyFTW : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : C> (@in_guaranteed τ_0_0) -> () { // %0 // user: %2 bb0(%0 : $*τ_0_0): // function_ref P.f() %1 = function_ref @$s6code031PPAAE1fyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %2 %2 = apply %1<τ_0_0>(%0) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () %3 = tuple () // user: %4 return %3 : $() // id: %4 } // end sil function '$s6code031CCAA1PA2aDP1fyyFTW' 46

Slide 47

Slide 47 text

// protocol witness for P.f() in conformance C sil private [transparent] [thunk] @$s6code031CCAA1PA2aDP1fyyFTW : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : C> (@in_guaranteed τ_0_0) -> () { // %0 // user: %2 bb0(%0 : $*τ_0_0): // function_ref P.f() %1 = function_ref @$s6code031PPAAE1fyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %2 %2 = apply %1<τ_0_0>(%0) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () %3 = tuple () // user: %4 return %3 : $() // id: %4 } // end sil function '$s6code031CCAA1PA2aDP1fyyFTW' • P.fͷσϑΥϧτ࣮૷Λݺͼग़͢ɻvtable͸ࢀর ͠ͳ͍ɻ 47

Slide 48

Slide 48 text

AͱBͷvtable sil_vtable A { #A.f!1: (A) -> () -> () : @$s6code031AC1fyyF // A.f() #A.init!allocator.1: (A.Type) -> () -> A : @$s6code031ACACycfC // A.__allocating_init() #A.deinit!deallocator.1: @$s6code031ACfD // A.__deallocating_deinit } sil_vtable B { #A.f!1: (A) -> () -> () : @$s6code031BC1fyyF [override] // B.f() #A.init!allocator.1: (A.Type) -> () -> A : @$s6code031BCACycfC [override] // B.__allocating_init() #B.deinit!deallocator.1: @$s6code031BCfD // B.__deallocating_deinit } • BͷςʔϒϧͷA.fͷཝ͕B.f() ($s6code031BC1fyyF)ͰΦʔόϥΠυ͞Ε͍ͯ Δ 48

Slide 49

Slide 49 text

CͱDͷvtable sil_vtable C { #C.init!allocator.1: (C.Type) -> () -> C : @$s6code031CCACycfC // C.__allocating_init() #C.deinit!deallocator.1: @$s6code031CCfD // C.__deallocating_deinit } sil_vtable D { #C.init!allocator.1: (C.Type) -> () -> C : @$s6code031DCACycfC [override] // D.__allocating_init() #D.f!1: (D) -> () -> () : @$s6code031DC1fyyF // D.f() #D.deinit!deallocator.1: @$s6code031DCfD // D.__deallocating_deinit } • CͷςʔϒϧʹC.fͷཝ͕ͳ͍ɻDͷςʔϒϧͰ ৽نͷD.fͱͯ͠ొ࿥͞Ε͍ͯΔɻ 49

Slide 50

Slide 50 text

AͱCͷwitness table sil_witness_table hidden A: P module code03 { method #P.f!1: (Self) -> () -> () : @$s6code031ACAA1PA2aDP1fyyFTW // protocol witness for P.f() in conformance A } sil_witness_table hidden C: P module code03 { method #P.f!1: (Self) -> () -> () : @$s6code031CCAA1PA2aDP1fyyFTW // protocol witness for P.f() in conformance C } • AͱCͷwitnessϝιου͕ͦΕͧΕొ࿥͞Εͯ ͍Δɻ • BͱDͷwitness table͸ͳ͍ɻ 50

Slide 51

Slide 51 text

A().f()ͷݺͼग़͠ %0 = metatype $@thick A.Type // user: %2 // function_ref A.__allocating_init() %1 = function_ref @$s6code031ACACycfC : $@convention(method) (@thick A.Type) -> @owned A // user: %2 %2 = apply %1(%0) : $@convention(method) (@thick A.Type) -> @owned A // users: %5, %4, %3 %3 = class_method %2 : $A, #A.f!1 : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () // user: %4 %4 = apply %3(%2) : $@convention(method) (@guaranteed A) -> () strong_release %2 : $A // id: %5 51

Slide 52

Slide 52 text

%0 = metatype $@thick A.Type // user: %2 // function_ref A.__allocating_init() %1 = function_ref @$s6code031ACACycfC : $@convention(method) (@thick A.Type) -> @owned A // user: %2 %2 = apply %1(%0) : $@convention(method) (@thick A.Type) -> @owned A // users: %5, %4, %3 %3 = class_method %2 : $A, #A.f!1 : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () // user: %4 %4 = apply %3(%2) : $@convention(method) (@guaranteed A) -> () strong_release %2 : $A // id: %5 • class_method໋ྩͰA.fͷΤϯτϦΛऔΓग़ ͯ͠ݺͼग़͠ 52

Slide 53

Slide 53 text

B().f()ͷݺͼग़͠ %6 = metatype $@thick B.Type // user: %8 // function_ref B.__allocating_init() %7 = function_ref @$s6code031BCACycfC : $@convention(method) (@thick B.Type) -> @owned B // user: %8 %8 = apply %7(%6) : $@convention(method) (@thick B.Type) -> @owned B // users: %11, %10, %9 %9 = class_method %8 : $B, #B.f!1 : (B) -> () -> (), $@convention(method) (@guaranteed B) -> () // user: %10 %10 = apply %9(%8) : $@convention(method) (@guaranteed B) -> () strong_release %8 : $B // id: %11 53

Slide 54

Slide 54 text

%6 = metatype $@thick B.Type // user: %8 // function_ref B.__allocating_init() %7 = function_ref @$s6code031BCACycfC : $@convention(method) (@thick B.Type) -> @owned B // user: %8 %8 = apply %7(%6) : $@convention(method) (@thick B.Type) -> @owned B // users: %11, %10, %9 %9 = class_method %8 : $B, #B.f!1 : (B) -> () -> (), $@convention(method) (@guaranteed B) -> () // user: %10 %10 = apply %9(%8) : $@convention(method) (@guaranteed B) -> () strong_release %8 : $B // id: %11 • class_method໋ྩͰB.fͷΤϯτϦΛऔΓग़ ͯ͠ݺͼग़͠ • A.fͰ͸ͳ͍ͷͰಛʹΦʔόϥΠυ͸ແؔ܎ 54

Slide 55

Slide 55 text

(B() as A).f()ͷݺͼग़͠ %12 = metatype $@thick B.Type // user: %14 // function_ref B.__allocating_init() %13 = function_ref @$s6code031BCACycfC : $@convention(method) (@thick B.Type) -> @owned B // user: %14 %14 = apply %13(%12) : $@convention(method) (@thick B.Type) -> @owned B // user: %15 %15 = upcast %14 : $B to $A // users: %18, %17, %16 %16 = class_method %15 : $A, #A.f!1 : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () // user: %17 %17 = apply %16(%15) : $@convention(method) (@guaranteed A) -> () strong_release %15 : $A // id: %18 55

Slide 56

Slide 56 text

%12 = metatype $@thick B.Type // user: %14 // function_ref B.__allocating_init() %13 = function_ref @$s6code031BCACycfC : $@convention(method) (@thick B.Type) -> @owned B // user: %14 %14 = apply %13(%12) : $@convention(method) (@thick B.Type) -> @owned B // user: %15 %15 = upcast %14 : $B to $A // users: %18, %17, %16 %16 = class_method %15 : $A, #A.f!1 : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () // user: %17 %17 = apply %16(%15) : $@convention(method) (@guaranteed A) -> () strong_release %15 : $A // id: %18 • Bͷ஋ΛAʹupcast໋ྩͰΞοϓΩϟετͨ͠ ޙɺclass_method໋ྩͰA.fͷΤϯτϦΛऔ Γग़ͯ͠ݺͼग़͠ • ςʔϒϧͷͦͷཝʹొ࿥͞Ε͍ͯΔB.f͕ݺ͹ ΕΔ 56

Slide 57

Slide 57 text

C().f()ͷݺͼग़͠ %19 = metatype $@thick C.Type // user: %21 // function_ref C.__allocating_init() %20 = function_ref @$s6code031CCACycfC : $@convention(method) (@thick C.Type) -> @owned C // user: %21 %21 = apply %20(%19) : $@convention(method) (@thick C.Type) -> @owned C // user: %23 %22 = alloc_stack $C // users: %23, %27, %26, %25 store %21 to %22 : $*C // id: %23 // function_ref P.f() %24 = function_ref @$s6code031PPAAE1fyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %25 %25 = apply %24(%22) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () destroy_addr %22 : $*C // id: %26 dealloc_stack %22 : $*C // id: %27 57

Slide 58

Slide 58 text

%19 = metatype $@thick C.Type // user: %21 // function_ref C.__allocating_init() %20 = function_ref @$s6code031CCACycfC : $@convention(method) (@thick C.Type) -> @owned C // user: %21 %21 = apply %20(%19) : $@convention(method) (@thick C.Type) -> @owned C // user: %23 %22 = alloc_stack $C // users: %23, %27, %26, %25 store %21 to %22 : $*C // id: %23 // function_ref P.f() %24 = function_ref @$s6code031PPAAE1fyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %25 %25 = apply %24(%22) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () destroy_addr %22 : $*C // id: %26 dealloc_stack %22 : $*C // id: %27 • P.fͷσϑΥϧτ࣮૷Λ௚઀ݺͼग़͠ • witnessςʔϒϧ͸ࢀর͠ͳ͍ 58

Slide 59

Slide 59 text

D().f()ͷݺͼग़͠ %28 = metatype $@thick D.Type // user: %30 // function_ref D.__allocating_init() %29 = function_ref @$s6code031DCACycfC : $@convention(method) (@thick D.Type) -> @owned D // user: %30 %30 = apply %29(%28) : $@convention(method) (@thick D.Type) -> @owned D // users: %33, %32, %31 %31 = class_method %30 : $D, #D.f!1 : (D) -> () -> (), $@convention(method) (@guaranteed D) -> () // user: %32 %32 = apply %31(%30) : $@convention(method) (@guaranteed D) -> () strong_release %30 : $D // id: %33 59

Slide 60

Slide 60 text

%28 = metatype $@thick D.Type // user: %30 // function_ref D.__allocating_init() %29 = function_ref @$s6code031DCACycfC : $@convention(method) (@thick D.Type) -> @owned D // user: %30 %30 = apply %29(%28) : $@convention(method) (@thick D.Type) -> @owned D // users: %33, %32, %31 %31 = class_method %30 : $D, #D.f!1 : (D) -> () -> (), $@convention(method) (@guaranteed D) -> () // user: %32 %32 = apply %31(%30) : $@convention(method) (@guaranteed D) -> () strong_release %30 : $D // id: %33 • class_method໋ྩͰD.fΛݺͼग़͠ • C.fͰ͸ແ͍ͷͰΦʔόʔϥΠυ͸ແؔ܎(ͦ΋ ͦ΋͞Ε͍ͯͳ͍) 60

Slide 61

Slide 61 text

(D() as C).f()ͷݺͼग़͠ %34 = metatype $@thick D.Type // user: %36 // function_ref D.__allocating_init() %35 = function_ref @$s6code031DCACycfC : $@convention(method) (@thick D.Type) -> @owned D // user: %36 %36 = apply %35(%34) : $@convention(method) (@thick D.Type) -> @owned D // user: %37 %37 = upcast %36 : $D to $C // user: %39 %38 = alloc_stack $C // users: %39, %43, %42, %41 store %37 to %38 : $*C // id: %39 // function_ref P.f() %40 = function_ref @$s6code031PPAAE1fyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %41 %41 = apply %40<(C)>(%38) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () destroy_addr %38 : $*C // id: %42 dealloc_stack %38 : $*C // id: %43 61

Slide 62

Slide 62 text

%34 = metatype $@thick D.Type // user: %36 // function_ref D.__allocating_init() %35 = function_ref @$s6code031DCACycfC : $@convention(method) (@thick D.Type) -> @owned D // user: %36 %36 = apply %35(%34) : $@convention(method) (@thick D.Type) -> @owned D // user: %37 %37 = upcast %36 : $D to $C // user: %39 %38 = alloc_stack $C // users: %39, %43, %42, %41 store %37 to %38 : $*C // id: %39 // function_ref P.f() %40 = function_ref @$s6code031PPAAE1fyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %41 %41 = apply %40<(C)>(%38) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () destroy_addr %38 : $*C // id: %42 dealloc_stack %38 : $*C // id: %43 • upcast໋ྩͰDΛCʹΞοϓΩϟετͨ͠ޙɺ P.fͷσϑΥϧτ࣮૷Λ௚઀ݺͼग़͠ 62

Slide 63

Slide 63 text

witnessςʔϒϧͷࢀর func invokeP(_ x: X) { x.f() } 63