I think we can do better than that by formalizing the type's set of basis operations. UnsafePointer
can only be said to have value semantics if dereferencing is not classified as a basis operation. I don't think that would be a very useful way to define UnsafePointer
's basis, though.
For the purposes of reasoning about multithreading and providing other guarantees related to value semantics (for example, there are some default implementations in RangeReplaceableCollection
that only work if the collection has value semantics), it is sufficient to choose one view of what constitutes any type's basis. Then if we want to use just a subset of the type's basis operations, we can either:
- put it in a subsetting wrapper type, or
- reason about behavior in terms of the guarantees provided for a hypothetical subsetting wrapper type without actually creating one.
I think there are probably a set of default rules we can follow that minimize the amount of explicit specification needed for the basis operations, e.g., every public method is a basis operation, every property and subscript is either 1 or 2 basis operations, depending on whether it's writable. But these are just defaults; to cover the range of possible APIs, a type's author may need to include arbitrary other operations in the type's basis. Outside the defining file, and certainly outside the defining module, all safe operations must be defined in terms of the basis, and can't introduce any new reference semantics.
Aside
Does
String
have value or reference semantics? It depends on if you look at it as some text, or as an obj-c selector that references a method.
I don't understand, but it might just be my ignorance of ObjC details. IIUC a method or selector, without an instance, has no mutable state, so there's no possibility of reference semantics.