Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swift Attributes

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Swift Attributes

Avatar for Takuma Shimizu

Takuma Shimizu

May 31, 2024
Tweet

More Decks by Takuma Shimizu

Other Decks in Programming

Transcript

  1. w %FDMBSBUJPO"UUSJCVUFTˡࠓճ͸ͪ͜ΒΛѻ͏ w એݴʹద༻Մೳ w Ϋϥεɺߏ଄ମɺྻڍɺϓϩύςΟɺϝιουɺؔ਺ɺม਺ͳͲ w 5ZQF"UUSJCVUFT w ܕʹద༻Մೳ

    w ܕએݴͷ͜ͱͰ͸ͳ͘ɺϝιουͷҾ਺ͳͲͰॻ͘ܕͷ͜ͱ w !FTDBQJOH !4FOEBCMF !VOLOPXͳͲ ଐੑ "UUSJCVUFT 
  2. 01 public struct Inclusion<Value, Member: _Clusivity.Member>: Validator{ 02 public var

    value: Value? 03 04 @usableFromInline 05 var member: Member 06 07 @inlinable 08 public func validate() throws { 09 guard let value else { return } 10 11 let contains = if let collection = presenceValue as? any Collection<Member.Element> { 12 member.contains(collection) 13 } else if let element = presenceValue as? Member.Element { 14 member.contains(element) 15 } else { 16 preconditionFailure() 17 } 18 19 if !contains { 20 throw ValidationError(reasons: .inclusion) 21 } 22 } 23 }
  3. 01 public struct Inclusion<Value, Member: _Clusivity.Member>: Validator{ 02 public var

    value: Value? 03 04 @usableFromInline 05 var member: Member 06 07 @inlinable 08 public func validate() throws { 09 guard let value else { return } 10 11 let contains = if let collection = value as? any Collection<Member.Element> { 12 member.contains(collection) 13 } else if let element = value as? Member.Element { 14 member.contains(element) 15 } else { 16 preconditionFailure() 17 } 18 19 if !contains { 20 throw ValidationError(reasons: .inclusion) 21 } 22 } 23 }
  4. 01 public struct Inclusion<Value, Member: _Clusivity.Member>: Validator{ 02 public var

    value: Value? 03 04 @usableFromInline 05 var member: Member 06 07 @inlinable 08 public func validate() throws { 09 guard let value else { return } 10 11 let contains = if let collection = presenceValue as? any Collection<Member.Element> { 12 member.contains(collection) 13 } else if let element = presenceValue as? Member.Element { 14 member.contains(element) 15 } else { 16 preconditionFailure() 17 } 18 19 if !contains { 20 throw ValidationError(reasons: .inclusion) 21 } 22 } 23 }
  5. 01 public struct Inclusion<Value, Member: _Clusivity.Member>: Validator{ 02 public var

    value: Value? 03 04 // @usableFromInline 05 var member: Member 06 07 @inlinable 08 public func validate() throws { 09 guard let value else { return } 10 11 let contains = if let collection = presenceValue as? any Collection<Member.Element> { 12 // 🚫 Property 'member' is internal and cannot be referenced from an '@inlinable' function 13 member.contains(collection) 14 } else if let element = presenceValue as? Member.Element { 15 // 🚫 Property 'member' is internal and cannot be referenced from an '@inlinable' function 16 member.contains(element) 17 } else { 18 preconditionFailure() 19 } 20 21 if !contains { 22 throw ValidationError(reasons: .inclusion) 23 } 24 } 25 }
  6. extension ValidationErrors: MutableCollection { @inlinable @inline(__always) public var startIndex: Index

    { errors.startIndex } @inlinable @inline(__always) public var endIndex: Index { errors.endIndex } @inlinable @inline(__always) public func index(after i: Index) -> Index { errors.index(after: i) } @inlinable @inline(__always) public subscript(position: Index) -> Element { _read { yield errors[position] } _modify { yield &errors[position] } } }
  7. // Module A public struct A { @usableFromInline let val1

    = 1 @usableFromInline let val2 = 2 @inlinable @inline(__always) public func f1() -> Int { val1 + val2 } @inline(__always) public func f2() -> Int { val1 + val2 } @inlinable public func f3() -> Int { val1 + val2 } } // Module B import ModuleA public func g1() -> Int { A().f1() } public func g2() -> Int { A().f2() } public func g3() -> Int { A().f3() }
  8. public struct A { @usableFromInline @_hasInitialValue internal let val1: Swift.Int

    @usableFromInline @_hasInitialValue internal let val2: Swift.Int @_hasInitialValue internal let val3: Swift.Int @_hasInitialValue internal let val4: Swift.Int public init() @inlinable @inline(__always) public func f1() -> Swift.Int { val1 + val2 } @inline(__always) public func f2() -> Swift.Int @inlinable public func f3() -> Swift.Int { val1 + val2 } } Ϟδϡʔϧ"ͷϑΝΠϧΛTXJGUJOUFSGBDFϑΝΠϧͰग़ྗ
  9. // g1() sil @$s7ModuleB2g1SiyF : $@convention(thin) () -> Int {

    [global: read,write,copy,destroy,allocate,deinit_barrier] bb0: %0 = metatype $@thin A.Type // user: %2 // function_ref A.init() %1 = function_ref @$s7ModuleA1AVACycfC : $@convention(method) (@thin A.Type) -> A // user: %2 %2 = apply %1(%0) : $@convention(method) (@thin A.Type) -> A // users: %4, %3 %3 = struct_extract %2 : $A, #A.val1 // user: %5 %4 = struct_extract %2 : $A, #A.val2 // user: %6 %5 = struct_extract %3 : $Int, #Int._value // user: %8 %6 = struct_extract %4 : $Int, #Int._value // user: %8 %7 = integer_literal $Builtin.Int1, -1 // user: %8 %8 = builtin "sadd_with_overflow_Int64"(%5 : $Builtin.Int64, %6 : $Builtin.Int64, %7 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // users: %10, %9 %9 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 0 // user: %12 %10 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 1 // user: %11 cond_fail %10 : $Builtin.Int1, "arithmetic overflow" // id: %11 %12 = struct $Int (%9 : $Builtin.Int64) // user: %13 return %12 : $Int // id: %13 } // end sil function '$s7ModuleB2g1SiyF' H ΋ಉ༷ͷग़ྗ݁ՌͰ ΠϯϥΠϯԽ͞Ε͍ͯΔ͜ͱ͕֬ೝͰ͖Δ Ϟδϡʔϧ#ͷϑΝΠϧΛ4*-Ͱग़ྗ
  10. // g2() sil @$s7ModuleB2g2SiyF : $@convention(thin) () -> Int {

    [global: read,write,copy,destroy,allocate,deinit_barrier] bb0: %0 = metatype $@thin A.Type // user: %2 // function_ref A.init() %1 = function_ref @$s7ModuleA1AVACycfC : $@convention(method) (@thin A.Type) -> A // user: %2 %2 = apply %1(%0) : $@convention(method) (@thin A.Type) -> A // user: %4 // function_ref A.f2() %3 = function_ref @$s7ModuleA1AV2f2SiyF : $@convention(method) (A) -> Int // user: %4 %4 = apply %3(%2) : $@convention(method) (A) -> Int // user: %5 return %4 : $Int // id: %5 } // end sil function '$s7ModuleB2g2SiyF' H ͸ΠϯϥΠϯԽ͞Ε͍ͯͳ͍ Ϟδϡʔϧ#ͷϑΝΠϧΛ4*-Ͱग़ྗ
  11. public struct A { @usableFromInline let val1 = 1 @usableFromInline

    let val2 = 2 @inline(__always) public func f2() -> Int { val1 + val2 } func g() -> Int { f2() } }
  12. // A.g() sil hidden @$s7ModuleA1AV1gSiyF : $@convention(method) (A) -> Int

    { [global: ] // %0 "self" // users: %4, %3, %2, %1 bb0(%0 : $A): debug_value %0 : $A, let, name "self", argno 1, implicit // id: %1 debug_value %0 : $A, let, name "self", argno 1, implicit // id: %2 %3 = struct_extract %0 : $A, #A.val1 // user: %5 %4 = struct_extract %0 : $A, #A.val2 // user: %6 %5 = struct_extract %3 : $Int, #Int._value // user: %8 %6 = struct_extract %4 : $Int, #Int._value // user: %8 %7 = integer_literal $Builtin.Int1, -1 // user: %8 %8 = builtin "sadd_with_overflow_Int64"(%5 : $Builtin.Int64, %6 : $Builtin.Int64, %7 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) // users: %10, %9 %9 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 0 // user: %12 %10 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 1 // user: %11 cond_fail %10 : $Builtin.Int1, "arithmetic overflow" // id: %11 %12 = struct $Int (%9 : $Builtin.Int64) // user: %13 return %12 : $Int // id: %13 } // end sil function '$s7ModuleA1AV1gSiyF' Ϟδϡʔϧ"ͷϑΝΠϧΛ4*-Ͱग़ྗ ( ͕ΠϯϥΠϯԽ͞Ε͍ͯΔ͜ͱ͕֬ೝͰ͖Δ
  13. public protocol Validator { associatedtype Validation func validate() throws @ValidatorBuilder

    var validation: Validation { get } } extension Validator where Validation == Never { @_transparent public var validation: Validation { fatalError() } } @_transparent͋Γ @_transparentͳ͠ ϩάग़ྗ͸ͲͪΒ΋ಉ͡↓ Validations/Validator.swift:47: Fatal error
  14. public struct Inclusion: Validator, Sendable { @_disfavoredOverload public init<E: Equatable,

    S: Sequence<E>>( _ value: S.Element, in elements: S ) { ... } public init<E: Comparable, S: Sequence<E>, R: RangeExpression<E>>( _ value: S, in range: R ) { ... } } // Without @_disfavoredOverload. Inclusion(1, in: [1, 2]) // ✅ Use 'init(Array<Int>.Element, in: Array<Int>)' Inclusion(5, in: 4...) // 🚫 Ambiguous use of 'init(_:in:)' // With @_disfavoredOverload. Inclusion(1, in: [1, 2]) // ✅ Use 'init(Array<Int>.Element, in: Array<Int>)' Inclusion(5, in: 4...) // ✅ Use 'init(Int, in: PartialRangeFrom<Int>)'