<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Wouldn't materializeForSet be good enough? I guess that's <i class="">one</i> extra copy if you don't want to rely on things not guaranteed by the language (i.e. "fields of classes have stable addresses").</div><div class=""><br class=""></div><div class="">Jordan</div><div class=""><br class=""></div><br class=""><div><blockquote type="cite" class=""><div class="">On Mar 10, 2016, at 7:43 , Arnold Schwaighofer <<a href="mailto:aschwaighofer@apple.com" class="">aschwaighofer@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Nice!<br class=""><br class="">As you have mentioned, unfortunately, this does not work on nested types without spurious copies (e.g. for foo.left.value.right.value = …). You would need to implement this with a mutableAddressor. Unfortunately, doing so requires Builtins and so this can’t currently be done outside of the standard library (without nasty flags).<br class=""><br class=""><span id="cid:E31920EA-99D2-47EC-AC60-6E50BD8FDB7A@localhost"><0001-A-copy-on-write-data-type.patch></span><br class=""><br class="">I agree with you that some interface forwarding would be an awesome language feature to have.<br class=""><br class="">It would allow for implementing an indirect storage wrapper without lots of boilerplate.<br class=""><br class="">Consider an example where you have value types that implement a protocol:<br class=""><br class=""><br class="">public _MyProtoWithoutAsscociatedType {<br class="">}<br class=""><br class="">public protocol MyProtocol : MyProtoWithoutAsscociatedType {<br class=""> associatedtype Assoc<br class=""><br class=""> public func doThis(v : Assoc)<br class=""> public func doThat()<br class=""><br class=""> public static func initAssocType() -> Assoc<br class=""><br class="">}<br class=""><br class="">struct MyProtocolImplementation : MyProtocol {<br class=""> typealias Assoc = Int<br class=""> var a : AReference<br class=""> var b : AReference<br class=""> var c : AReference<br class=""> var d : Double<br class=""><br class=""> func doThis(v: Assoc) {…}<br class=""> func doThat() {…}<br class=""><br class=""> static func initAssocType() -> Assoc {<br class=""> return 0<br class=""> }<br class="">}<br class=""><br class="">Your application passes those value types as existential values or as generic values because the architecture requires that. This can incur lots of allocations at every value copy for this example value type because we don’t fit in the inline buffer (three pointer words) which would be allocated inline (on the stack or as a stored property for existentials).<br class=""><br class="">One way to work around this is today is make your value type’s storage indirect via a wrapper such that it will always fit in inline storage.<br class=""><br class="">class _BoxStorage<T> {<br class=""> final var value: T<br class=""><br class=""> init(_ elt: T) {<br class=""> value = elt<br class=""> }<br class="">}<br class=""><br class="">public struct Indirect<V : MyProtocol> : MyProcotol {<br class=""><br class=""> public typealias Assoc = V.Assoc<br class=""><br class=""> final var _storage: _BoxStorage<V><br class=""><br class=""> public init(_ elt: V) {<br class=""> _storage = _BoxStorage(elt)<br class=""> }<br class=""><br class=""> internal var value: V {<br class=""> get {<br class=""> return _storage.value<br class=""> }<br class=""> mutableAddressWithNativeOwner {<br class=""> if !isUniquelyReferencedNonObjC(&_storage) {<br class=""> _storage = _BoxStorage(_storage.value)<br class=""> }<br class=""> return (<br class=""> UnsafeMutablePointer(Builtin.addressof(&_storage.value)),<br class=""> Builtin.castToNativeObject(_storage))<br class=""> }<br class=""> }<br class=""><br class=""> public static func initAssocType() -> Assoc {<br class=""> return Assoc.initAssocType()<br class=""> }<br class=""><br class=""> public func doThis(v: Assoc) {<br class=""> value.doThis(v)<br class=""> }<br class=""> public func doThat() {<br class=""> value.doThat()<br class=""> }<br class="">}<br class=""><br class="">Indeed, doing so would require a lot of boiler plate.<br class=""><br class=""><br class="">Instead the following would be much nicer:<br class=""><br class="">public struct Indirect<V : MyProtocol> : MyProcotol {<br class=""><br class=""> public typealias Assoc = V.Assoc<br class=""><br class=""> final var _storage: _BoxStorage<V><br class=""><br class=""> public init(_ elt: V) {<br class=""> _storage = _BoxStorage(elt)<br class=""> }<br class=""><br class=""> internal forwarding var value: V as MyProtocol {<br class=""> typealias Assoc = V.Assoc<br class=""><br class=""> get {<br class=""> return _storage.value<br class=""> }<br class=""> mutableAddressWithNativeOwner {<br class=""> if !isUniquelyReferencedNonObjC(&_storage) {<br class=""> _storage = _BoxStorage(_storage.value)<br class=""> }<br class=""> return (<br class=""> UnsafeMutablePointer(Builtin.addressof(&_storage.value)),<br class=""> Builtin.castToNativeObject(_storage))<br class=""> }<br class=""> }<br class=""><br class="">}<br class=""><br class=""><br class=""><br class=""><blockquote type="cite" class="">On Mar 9, 2016, at 9:53 AM, Jordan Rose via swift-dev <<a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a>> wrote:<br class=""><br class="">Ha, I remember this document, but forgot it included an implementation. Encouraging to see that it's pretty much identical.<br class=""><br class="">The concrete type forwarding logic is something we ought to be able to simplify somehow (with new language features).<br class=""><br class="">Jordan<br class=""><br class=""><br class=""><blockquote type="cite" class="">On Mar 9, 2016, at 9:50 , Nadav Rotem <<a href="mailto:nrotem@apple.com" class="">nrotem@apple.com</a>> wrote:<br class=""><br class="">HI Jordan, <br class=""><br class="">Very Nice! <br class=""><br class="">There is a similar implementation and discussion about performance here:<br class=""><br class=""><a href="https://github.com/apple/swift/blob/master/docs/OptimizationTips.rst#advice-use-copy-on-write-semantics-for-large-values" class="">https://github.com/apple/swift/blob/master/docs/OptimizationTips.rst#advice-use-copy-on-write-semantics-for-large-values</a><br class=""><br class="">-Nadav<br class=""><br class=""><br class=""><blockquote type="cite" class="">On Mar 9, 2016, at 9:39 AM, Jordan Rose via swift-dev <swift-dev@swift.org> wrote:<br class=""><br class="">Just for fun, I wrote a wrapper for COW types that don't need the flexible inline storage of ManagedBuffer. It turned out to be pretty straightforward, though I didn't bother with materializeForSet and thus am incurring the cost of many extra value copies on mutation. The major downside is having to forward all operations through, something I'm sure the implementers of Array and Dictionary are very used to!<br class=""><br class="">Disclaimer: This is not performant; don't use it in your app.<br class=""><br class="">Jordan<br class=""><br class=""><cow.swift><br class="">_______________________________________________<br class="">swift-dev mailing list<br class="">swift-dev@swift.org<br class="">https://lists.swift.org/mailman/listinfo/swift-dev<br class=""></blockquote><br class=""></blockquote><br class="">_______________________________________________<br class="">swift-dev mailing list<br class=""><a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-dev<br class=""></blockquote><br class=""></div></div></blockquote></div><br class=""></body></html>