Implementing ClassType in declare_class! is unsafe because we need the user to uphold a few safety guarantees, and that was just the most convenient place to put the unsafe keyword.
After #521 though, the only safety guarantees that the user needs to uphold are:
- Any invariants that the superclass
ClassType::Super may have must be upheld.
ClassType::Mutability must be correct.
Drop must be implemented correctly.
We should work on ways to make fulfilling these unsafe requirements more granular.
One possibility for requirement 2 would be to migrate from an associated type Mutability to a constant, that you must initialize with unsafe if you need certain features:
pub struct Mutability {}
impl Mutability {
pub const fn interior_mutable() -> Self {
todo!()
}
/// # Safety
/// ... clearly detailed docs for when this is safe ...
pub const unsafe fn main_thread_only() -> Self {
todo!()
}
// ...
}
// Usage
declare_class!(
struct MyClass;
unsafe impl ClassType for MyClass {
type Super = NSObject;
const MUTABILITY: Mutability = Mutability::interior_mutable();
// Or
// SAFETY: ...
// const MUTABILITY: Mutability = unsafe { Mutability::main_thread_only() };
const NAME: &'static str = "MyClass";
}
// ...
);
Implementing
ClassTypeindeclare_class!isunsafebecause we need the user to uphold a few safety guarantees, and that was just the most convenient place to put theunsafekeyword.After #521 though, the only safety guarantees that the user needs to uphold are:
ClassType::Supermay have must be upheld.ClassType::Mutabilitymust be correct.Dropmust be implemented correctly.We should work on ways to make fulfilling these
unsaferequirements more granular.One possibility for requirement 2 would be to migrate from an associated type
Mutabilityto a constant, that you must initialize withunsafeif you need certain features: