4 ms·
This post reminds me of a problem I've hit with my Objective-Rust project[1] (Rust code that's interoperable with Objective-C), to which I haven't found a good
by cornstalks 8y ago
This post reminds me of a problem I've hit with my Objective-Rust project[1] (Rust code that's interoperable with Objective-C), to which I haven't found a good solution.
The closest analog to Objective-C's @protocols in Rust are traits. I would love to be able to transliterate the following Objective-C:
@protocol SomeProtocol
// methods
@end
void demo() {
// Just a demo of how to use SomeProtocol with a var:
id<SomeProtocol> variable = nil;
}
To the following Rust:
#[objrs(protocol)]
trait SomeProtocol {
// methods
}
fn demo() {
// Just a demo of how to use SomeProtocol with a var:
let variable: *mut Id<SomeProtocol> = 0 as *mut _;
}
// The following is provided by objrs:
struct Id<T: ?Sized>(core::marker::PhantomData<T>, Opaque);
extern "C" {
type Opaque;
}
Unfortunately, RFC 255[2] breaks this. This fails because SomeProtocol is not object safe. Trait objects in Rust can be pretty frustrating in Rust, as this post illustrates.
I've had to workaround this in objrs by doing something like the following:
#[objrs(protocol)]
trait SomeProtocol {
// methods
}
// The macro above generates stuff kinda like this:
struct SomeProtocolId;
impl SomeProtocol for SomeProtocolId {}
impl<T: ?Sized + SomeProtocol> SomeProtocol for Id<T> {}
fn demo() {
// Now you have to know when to use SomeProtocol vs SomeProtocolId:
let variable: *mut Id<SomeProtocolId> = 0 as *mut _;
}
I'm going to see if there are some places where this blog post might simplify some things in my code... it's got some interesting ideas.
[1]: https://gitlab.com/objrs/objrs https://gitlab.com/objrs/objrs
[2]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md https://github.com/rust-lang/rfcs/blob/master/text/0255-obje...
- saagarjha 8y agoI don't know enough Rust to completely understand what you are talking about with object safety, but this is a very interesting project. How do you plan to handle Objective-C's runtime features? Even if you don't plan to implement advanced features like objc_allocateClassPair, one thing you will have to deal with rather quickly is informal protocols and optional methods, which are resolved at runtime.
- cornstalks 8y agoRuntime modifications to the Objective-C runtime (e.g., objc_allocateClassPair) will have to go through libobjc, just like they do in Objective-C. I could provide friendlier interfaces to libobjc, but I don't plan to. objrs already supports optional methods (for externally-defined protocols), though using them is the same as in Objective-C (you still have to call respondsToSelector: first). I've thought about adding an additional API that simplifies this a bit (i.e., a method that returns an Option, where it's None if the class doesn't respond to the method, or Some(fn) if it does (where fn is a closure you can use to invoke the function)).
- comex 8y agoIdeally you want `Id` to actually be parameterized on traits, not trait object types that happen to have the same syntax (now deprecated) as their corresponding traits. Of course, that's not currently possible. But you may be interested in this repo for planning an RFC to eventually add such functionality: https://github.com/Centril/rfc-trait-parametric-polymorphism/ https://github.com/Centril/rfc-trait-parametric-polymorphism... After being created 8 months ago, it's sort of inactive, but hopefully that'll change once the compiler's feature-implementation backlog starts catching up – in particular, once "chalk in rustc" becomes a reality.
- cornstalks 8y agoOh neat! I hadn't seen that one, but it's literally item #20 on my Rust wishlist. I'll have to file an issue to give some motivating examples. Thank you for pointing it out to me!