On the topic of ValueSemantic vs UnsafeValueSemantic, maybe we can have them both by making ValueSemantic a subset of UnsafeValueSemantic.
As far as I can see, there are 2 situations where conformance to ValueSemantic is unsafe:
-
When the conforming type is a reference type.
-
When the conforming type is a value type, but it's not composed of only ValueSemantic types.
Situation 2 can be addressed by an error message when the compiler cannot auto-synthesise the conformance. Situation 1 can be addressed if we have a way to mark value types like how we mark reference types with AnyObject:
Maybe we can introduce another new protocol AnyValue (or ValueType or something else, bikesheddable) opposite to AnyObject, and have all value types (structs, enums, tuples) implicitly conform to it. Then, we can allow UnsafeValueSemantic written as ValueSemantic when the conforming type is a reference type:
typealias ValueSemantic = UnsafeValueSemantic where Self: AnyValue
^ This expression isn't possible in Swift today, though. So some additional compiler magic might be needed.
Alternatively, it might be more workable if ValueSemantic inherits from both AnyValue and UnsafeValueSemantic:
protocol ValueSemantic: AnyValue, UnsafeValueSemantic {}
class Foo: ValueSemantic { // error: Non-value-type 'Foo' cannot conform to value-type protocol 'ValueSemantic'
// fix-it: replace 'ValueSemantic' with 'UnsafeValueSemantic'
let bar: Int
}
Or, a third option, make ValueSemantic a composition of AnyValue and UnsafeValueSemantic:
typealias ValueSemantic = AnyValue & UnsafeValueSemantic
class Foo: ValueSemantic { // error: Inheritance from non-protocol type 'ValueSemantic' (aka 'AnyValue & UnsafeValueSemantic')
// fix-it: replace 'ValueSemantic' with 'UnsafeValueSemantic'
let bar: Int
}
^ These latter 2 options also need some additional compiler magic, but it's precedented by AnyObject.