[swift-evolution] [Manifesto] Ownership

Dave Abrahams dabrahams at apple.com
Mon Mar 6 19:53:41 CST 2017

on Mon Mar 06 2017, Karl Wagner <razielim-AT-gmail.com> wrote:

>> On 6 Mar 2017, at 22:30, Dave Abrahams via swift-evolution <swift-evolution at swift.org> wrote:
>> on Mon Mar 06 2017, John McCall <swift-evolution at swift.org> wrote:
>>>> On Mar 6, 2017, at 3:46 PM, Karl Wagner <razielim-Re5JQEeQqe8AvxtiuMwx3w at public.gane.org> wrote:
>>>> Thanks very much for writing this up, it’s very interesting.
>>>> The one thing which I think needs improvement is the Copyable protocol. I think that this is
>>> actually part of a larger problem in Swift, which is that we don’t expose enough information to
>>> generic code for it to operate safely. This goes back to people asking for a value-equivalent to the
>>> “class” or “AnyObject” magic protocols.
>>>> For example, often you would like to wrap a Collection and keep some information about what it contains. In order to do that generically, you need to ensure a client can hand you an exclusive view of a collection’s contents, so you know they will not mutate underneath your feet. 
>>>> Currently, that means you need a RangeReplaceableCollection because it includes an empty initialiser which allows you to create a unique copy of the Collection’s contents. It’s a workaround, but it means we have this unnecessary protocol requirement in the standard library, and in the implementation, which is making copies that may not be required. If my CollectionWrapper is initialised with something which has ValueSemantics, I don’t need to create a whole new instance with equal contents to ensure exclusivity of those contents. If this was an Array, for example, I could simply assign it and it would ensure the underlying contiguous buffer is never mutated.
>>>> struct CollectionWrapper<C: Collection> {
>>>>    var _underlying: C
>>>>    init(contentsOf other: C) where C: RangeReplaceableCollection { 
>>>>        _underlying = C();
>>>>        _underlying.replaceSubrange(_underlying.startIndex..<_underlying.endIndex, with: other) 
>>>>    }
>>>> }
>>>> // Would love to do this…
>>>> extension CollectionWrapper {
>>>>    init(contentsOf other: C) where C: ValueSemantics { 
>>>>        _underlying = other 
>>>>    }
>>>> }
>>>> As the proposal notes (with the File example), these are semantic
>>>> considerations which go beyond simple struct/class distinctions:
>>>> structs may have reference semantics, and classes may have value
>>>> semantics. Would it be possible to model Copyable/move-only in terms
>>>> of two new protocols, ValueSemantics and ReferenceSemantics, with
>>>> trivial types/non-trivial types given appropriate defaults
>>>> (overridable by the programmer, such as for “File”)?
>>> Class types have reference semantics and are still copyable; ownership
>>> is not going to change that.  More generally, I don't see how anything
>>> we can do in ownership could ever do something like eliminate the
>>> possibility of a reference-semantics collection from the language.
>> I think it might not be very related to ownership, but the use of the
>> word “Copyable” may be a problem.  For most programmers when applied to
>> reference types “Copyable” will connote “Clonable,” i.e. that the
>> referent (rather than the reference, which is what you're referring to
>> when you say class types are copyable) can be explicitly copied.  So I'm
>> betting Karl read “Copyable” and was led to this other topic which is of
>> concern to many people.  In that sense, claiming “Copyable” for
>> ownership without also addressing “Clonable” could be a problem.
>> The idea behind “Clonable” would be that it gives you a *generic* way to
>> create a logically *independent* copy of a value, that would work both
>> for value types and reference types.
>> -- 
>> -Dave
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> Part of it is the name; partly I was led there by the examples in the
> document. For example, a move-only struct with a deinitialiser looks
> an awful lot like it’s trying to express ReferenceSemantics, since it
> infers identity. How would using a move-only struct differ from using
> a class?

The distinction between value and reference semantics lies in what
happens when you copy or assign, and then mutate.  You can't observe
that distinction with move-only types because they have no copy or
assignment.  Similarly, you can't observe the difference between value
and reference types when types are immutable.  Both immutable and
move-only types eliminate half of the operations you need to be able to
see the distinction.  

The confusion about identity occurs because Swift (like most OOP
languages these days) tries hard to erase your ability to see the
difference between the reference and the thing it refers to.  References
(what John refers to as Class types above) don't have identity, but the
instances they refer to do.  So in that sense, move-only instances are
like class instances.

> I’ve been thinking that we could do with a collection of magic
> protocols to constrain generic code based on type layout in
> general. There is a lot of generic code which could benefit from
> optimised implementations if they know that T is trivial, for
> example. At a higher level, we often want to know whether a particular
> type (regardless of struct/class) has reference/value semantics
> because we care about exclusivity over its contents.
> Some of the constraints of the “law of exclusivity” sound like they
> are providing a kind of value semantic of contents at the
> variable-level (e.g. shared references are allowed as long as they do
> not change the contents). Several of the concepts in the document are
> new to me, but at some broad level there appear to be conceptual
> similarities.
> At the same time, while references to classes are “Copyable” in the
> ownership sense, those copies are very different from copies of
> structs. For classes, those copies are basically worthless to the
> optimiser because it can’t guarantee anything about who else has
> references to the instance. 

Except when it can, but yeah, it's harder.

> I’m not really sure classes actually benefit at all from being
> “Copyable”. Perhaps they should be some other, closely-related thing
> instead?

Class references have to be “Copyable” or the world falls apart :-)


More information about the swift-evolution mailing list