-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The deal with mutability #265
Comments
rust-windowing/winit#2457 highlighted an issue: We'd have to return |
Instead, making it Note that this is not currently possible because the layout of |
Even ignoring thread safety, a problem arises with methods that return references to internal data. For example, the following fails at compile-time because let mut data = NSMutableData::with_bytes(b"abc");
let b = data.bytes();
data.set_bytes(b"def");
assert_eq!(b, b"abc"); Similarly for Swift "solves" this by just returning import Foundation
var arr = NSMutableArray(array: [1, 2, 3])
for elem in arr {
arr.add(4)
print("test", elem)
} So yeah, I'm quite conflicted as to how we should do mutability; perhaps things will be clearer once I've done more of #264, and get to see if there are parts other than Foundation that would benefit from mutability. |
Another solution: Just keep every mutating method |
Would maybe make sense to take the |
Truth be told, I'm fine with having a standard class that's |
Yeah if it was only thread safety that was the issue, then I would agree, but as noted in #265 (comment), that still won't allow us to make mutating methods like |
An update: More importantly, Swift recently implemented a better concept of sendability, see But, even more importantly, we can automatically mark if method.return_type.includes_ns_swift_ui_actor() {
if method.receiver.is_ns_swift_ui_actor() {
break;
}
for argument in method.arguments {
if argument.is_ns_swift_ui_actor() {
break;
}
}
method.arguments.push(("mtm", Ty::MainThreadMarker));
} (Note here the difference between So e.g. |
A bit unsure where the E.g. the difference between these two: // As first
let window = NSWindow::initWithContentRect_styleMask_backing_defer(
NSWindow::alloc(),
MainThreadMarker::new(),
NSRect::new(0.0, 0.0),
NSWindowStyleMaskClosable
| NSWindowStyleMaskMiniaturizable
| NSWindowStyleMaskResizable
| NSWindowStyleMaskTitled,
NSBackingStoreBuffered,
false,
);
// As last
let window = NSWindow::initWithContentRect_styleMask_backing_defer(
NSWindow::alloc(),
NSRect::new(0.0, 0.0),
NSWindowStyleMaskClosable
| NSWindowStyleMaskMiniaturizable
| NSWindowStyleMaskResizable
| NSWindowStyleMaskTitled,
NSBackingStoreBuffered,
false,
MainThreadMarker::new(),
); (Oh, fabulous contexts and capabilities, how you could relieve me of all my troubles with but the smallest of effort)! EDIT: Parts of this is redundant since |
The resolution after #419 is that we'll end up making most classes use interior mutability, but keep mutability in certain core classes like Relating to the issues noted in the top comment, I believe most of them are addressed:
Tracked in #316, also completed by the linked PR.
Interior mutability is the default setting for
Not sure one could do that anyhow, I think Objective-C itself may assume that
Tracked in #399, Since the type ownership is no longer on the
You can probably do So the only remaining things in this is the main thread safety stuff that is not really related to this issue, I'll track that in in #359 instead. |
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 whileNSMutableString
is, naturally, mutable. Since our current implementation only allows mutation ofNSMutableString
through&mut self
, it is safe to make both of theseSend + Sync
; all is well and Rusty.Now, remember that
&NSMutableString -> &NSString
andId<NSMutableString, O> -> Id<NSString, O>
is safe - so if we were to make mutation ofNSMutableString
possible through&self
, not only wouldNSMutableString
be!Sync
, but so wouldNSString
! (They could still beSend
, that would simply allow moving them via.Id<T, Owned>
to a different thread - quite similar tostd::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 alreadyUnsafeCell
.On the other hand, if we were to remove mutability we could:
NSArray<T>
,NSDictionary<K, V>
and such collection types simplerNSString
, without them having to ensure that their object wasSync
Id::retain
could be made safe(r?)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
isSendable
butNSString
is not).The text was updated successfully, but these errors were encountered: