Description
I was once convinced that we could restrict mutation to &mut self
methods, but after having battled with AppKit and seen how Swift does it, I'm beginning to doubt that this is the best way.
NSString
is immutable while NSMutableString
is, naturally, mutable. Since our current implementation only allows mutation of NSMutableString
through &mut self
, it is safe to make both of these Send + Sync
; all is well and Rusty.
Now, remember that &NSMutableString -> &NSString
and Id<NSMutableString, O> -> Id<NSString, O>
is safe - so if we were to make mutation of NSMutableString
possible through &self
, not only would NSMutableString
be !Sync
, but so would NSString
! (They could still be Send
, that would simply allow moving them via. Id<T, Owned>
to a different thread - quite similar to std::cell::Cell
)
That's the primary downside: Our objects can no longer be shared across threads. Downsides that usually apply to Rust code (aliasing optimizations, ...) are void in our case, since NSString
is already UnsafeCell
.
On the other hand, if we were to remove mutability we could:
- Make
NSArray<T>
,NSDictionary<K, V>
and such collection types simpler - Since most frameworks use interior mutability and/or are not thread safe anyhow, the usage of the Foundation framework would match the usage of these.
- It would be possible for users to inherit
NSString
, without them having to ensure that their object wasSync
Id::retain
could be made safe(r?)- automatic bindings would be simpler
- Using
NSMutableString
inside adeclare_class!
that is not meant to be thread-safe anyhow is easier (e.g. means we won't have to use&mut
inwinit
)
So... Yeah, will think about this a bit, but I think we may have to sacrifice being able to use Objective-C classes across threads (exactly the same compromise Swift does, their String
is Sendable
but NSString
is not).