From 7cb8c18838498f2de9e22a7dc4bfd52f1dee6438 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 10 May 2018 09:01:30 -0700 Subject: [PATCH] SE-0210: improve documentation comments per @natecook1000's comments. --- stdlib/public/core/MemoryLayout.swift | 58 ++++++++++++++++++--------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/stdlib/public/core/MemoryLayout.swift b/stdlib/public/core/MemoryLayout.swift index a78dd132aa830..5de76febcc4e0 100644 --- a/stdlib/public/core/MemoryLayout.swift +++ b/stdlib/public/core/MemoryLayout.swift @@ -166,26 +166,22 @@ extension MemoryLayout { /// Returns the offset of an inline stored property of `T` within the /// in-memory representation of `T`. /// - /// If the given `key` refers to inline storage within the - /// in-memory representation of `T`, and the storage is directly - /// addressable (meaning that accessing it does not need to trigger any - /// `didSet` or `willSet` accessors, perform any representation changes - /// such as bridging or closure reabstraction, or mask the value out of - /// overlapping storage as for packed bitfields), then the return value - /// is a distance in bytes that can be added to a pointer of type `T` to - /// get a pointer to the storage accessed by `key`. If the return value is - /// non-nil, then these formulations are equivalent: - /// - /// var root: T, value: U - /// var key: WritableKeyPath - /// // Mutation through the key path... - /// root[keyPath: \.key] = value - /// // ...is exactly equivalent to mutation through the offset pointer... - /// withUnsafePointer(to: &root) { - /// (UnsafeMutableRawPointer($0) + MemoryLayout.offset(of: \.key)) - /// // ...which can be assumed to be bound to the target type - /// .assumingMemoryBound(to: U.self).pointee = value - /// } + /// If the given `key` refers to inline, directly addressable storage within + /// the in-memory representation of `T`, then the return value is a distance + /// in bytes that can be added to a pointer of type `T` to get a pointer to + /// the storage accessed by `key`. If the return value is non-nil, then these + /// formulations are equivalent: + /// + /// var root: T, value: U + /// var key: WritableKeyPath + /// // Mutation through the key path... + /// root[keyPath: key] = value + /// // ...is exactly equivalent to mutation through the offset pointer... + /// withUnsafeMutablePointer(to: &root) { + /// (UnsafeMutableRawPointer($0) + MemoryLayout.offset(of: key)) + /// // ...which can be assumed to be bound to the target type + /// .assumingMemoryBound(to: U.self).pointee = value + /// } /// /// - Parameter key: A key path referring to storage that can be accessed /// through a value of type `T`. @@ -194,6 +190,28 @@ extension MemoryLayout { /// such offset is available for the storage referenced by `key`, such as /// because `key` is computed, has observers, requires reabstraction, or /// overlaps storage with other properties. + /// + /// A property has inline, directly addressable storage when it is a stored + /// property for which no additional work is required to extract or set the + /// value. For example: + /// + /// struct ProductCategory { + /// var name: String // inline, directly-addressable + /// var updateCounter: Int // inline, directly-addressable + /// var productCount: Int { // computed properties are not directly addressable + /// return products.count + /// } + /// var products: [Product] { // didSet/willSet properties are not directly addressable + /// didSet { updateCounter += 1 } + /// } + /// } + /// + /// When using `offset(of:)` with a type imported from a library, don't assume + /// that future versions of the library will have the same behavior. If a + /// property is converted from a stored property to a computed property, the + /// result of `offset(of:)` changes to `nil`. That kind of conversion is + /// non-breaking in other contexts, but would trigger a runtime error if the + /// result of `offset(of:)` is force-unwrapped. @_inlineable // FIXME(sil-serialize-all) @_transparent public static func offset(of key: PartialKeyPath) -> Int? {