objc2 icon indicating copy to clipboard operation
objc2 copied to clipboard

Fails compiling in `rust-analyzer`

Open nooly1998 opened this issue 5 months ago • 3 comments

Compile Error in aarch64-apple-darwin target.

proj config:

[package]
name = "untitled"
version = "0.0.0"
edition = "2021"

[dependencies]
objc2 = "0.6.1"
objc2-foundation = "0.3.1"
objc2-app-kit = "0.3.1"

objc2-0.6.1 example code:

#![deny(unsafe_op_in_unsafe_fn)]
use std::cell::OnceCell;

use objc2::rc::Retained;
use objc2::runtime::ProtocolObject;
use objc2::{define_class, msg_send, DefinedClass, MainThreadOnly};
use objc2_app_kit::{
    NSApplication, NSApplicationActivationPolicy, NSApplicationDelegate, NSAutoresizingMaskOptions,
    NSBackingStoreType, NSColor, NSFont, NSTextAlignment, NSTextField, NSWindow, NSWindowDelegate,
    NSWindowStyleMask,
};
use objc2_foundation::{
    ns_string, MainThreadMarker, NSNotification, NSObject, NSObjectProtocol, NSPoint, NSRect,
    NSSize,
};

#[derive(Debug, Default)]
struct AppDelegateIvars {
    window: OnceCell<Retained<NSWindow>>,
}

define_class!(
    // SAFETY:
    // - The superclass NSObject does not have any subclassing requirements.
    // - `Delegate` does not implement `Drop`.
    #[unsafe(super = NSObject)]
    #[thread_kind = MainThreadOnly]
    #[ivars = AppDelegateIvars]
    struct Delegate;

    // SAFETY: `NSObjectProtocol` has no safety requirements.
    unsafe impl NSObjectProtocol for Delegate {}

    // SAFETY: `NSApplicationDelegate` has no safety requirements.
    unsafe impl NSApplicationDelegate for Delegate {
        // SAFETY: The signature is correct.
        #[unsafe(method(applicationDidFinishLaunching:))]
        fn did_finish_launching(&self, notification: &NSNotification) {
            let mtm = self.mtm();

            let app = unsafe { notification.object() }
                .unwrap()
                .downcast::<NSApplication>()
                .unwrap();

            let text_field = unsafe {
                let text_field = NSTextField::labelWithString(ns_string!("Hello, World!"), mtm);
                text_field.setFrame(NSRect::new(
                    NSPoint::new(5.0, 100.0),
                    NSSize::new(290.0, 100.0),
                ));
                text_field.setTextColor(Some(&NSColor::colorWithSRGBRed_green_blue_alpha(
                    0.0, 0.5, 0.0, 1.0,
                )));
                text_field.setAlignment(NSTextAlignment::Center);
                text_field.setFont(Some(&NSFont::systemFontOfSize(45.0)));
                text_field.setAutoresizingMask(
                    NSAutoresizingMaskOptions::ViewWidthSizable
                        | NSAutoresizingMaskOptions::ViewHeightSizable,
                );
                text_field
            };

            // SAFETY: We disable releasing when closed below.
            let window = unsafe {
                NSWindow::initWithContentRect_styleMask_backing_defer(
                    NSWindow::alloc(mtm),
                    NSRect::new(NSPoint::new(0.0, 0.0), NSSize::new(300.0, 300.0)),
                    NSWindowStyleMask::Titled
                        | NSWindowStyleMask::Closable
                        | NSWindowStyleMask::Miniaturizable
                        | NSWindowStyleMask::Resizable,
                    NSBackingStoreType::Buffered,
                    false,
                )
            };
            // SAFETY: Disable auto-release when closing windows.
            // This is required when creating `NSWindow` outside a window
            // controller.
            unsafe { window.setReleasedWhenClosed(false) };

            // Set various window properties.
            window.setTitle(ns_string!("A window"));
            let view = window.contentView().expect("window must have content view");
            unsafe { view.addSubview(&text_field) };
            window.center();
            unsafe { window.setContentMinSize(NSSize::new(300.0, 300.0)) };
            window.setDelegate(Some(ProtocolObject::from_ref(self)));

            // Show the window.
            window.makeKeyAndOrderFront(None);

            // Store the window in the delegate.
            self.ivars().window.set(window).unwrap();

            app.setActivationPolicy(NSApplicationActivationPolicy::Regular);

            // Activate the application.
            // Required when launching unbundled (as is done with Cargo).
            #[allow(deprecated)]
            app.activateIgnoringOtherApps(true);
        }
    }

    // SAFETY: `NSWindowDelegate` has no safety requirements.
    unsafe impl NSWindowDelegate for Delegate {
        #[unsafe(method(windowWillClose:))]
        fn window_will_close(&self, _notification: &NSNotification) {
            // Quit the application when the window is closed.
            unsafe { NSApplication::sharedApplication(self.mtm()).terminate(None) };
        }
    }
);

impl Delegate {
    fn new(mtm: MainThreadMarker) -> Retained<Self> {
        let this = Self::alloc(mtm).set_ivars(AppDelegateIvars::default());
        // SAFETY: The signature of `NSObject`'s `init` method is correct.
        unsafe { msg_send![super(this), init] }
    }
}

fn main() {
    let mtm = MainThreadMarker::new().unwrap();

    let app = NSApplication::sharedApplication(mtm);
    let delegate = Delegate::new(mtm);
    app.setDelegate(Some(ProtocolObject::from_ref(&*delegate)));

    app.run();
}
compile error:
error[E0200]: the trait `NSObjectProtocol` requires an `unsafe impl` declaration
   --> src/main.rs:22:1
    |
22  | / define_class!(
...   |
113 | | );
    | |_^
    |
    = note: the trait `NSObjectProtocol` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
    = note: this error originates in the macro `$crate::__define_class_output_impls` which comes from the expansion of the macro `define_class` (in Nightly builds, run with -Z macro-backtrace for more info)
help: add `unsafe` to this trait implementation
   --> /Users/username/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/objc2-0.6.1/src/macros/define_class.rs:862:9
    |
862 |         unsafe impl $protocol for $for {}
    |         ++++++

The same problem occurs in all unsafe implementations of the define_class! macro.

Thanks.

nooly1998 avatar Jul 19 '25 11:07 nooly1998

Hmm. I copied your exact example and I could not reproduce your error. I'm on an m1 mac, macOS 15.5, xcode 26 beta (but the non-beta should also work fine).

simlay avatar Jul 19 '25 17:07 simlay

Ok, Reinstalling Rust solved the problem for me, probably a cache issue.

2025年7月20日 01:24,simlay @.***> 写道:

simlay left a comment (madsmtm/objc2#771) https://github.com/madsmtm/objc2/issues/771#issuecomment-3092467246 Hmm. I copied your exact example and I could not reproduce your error. I'm on an m1 mac, macOS 15.5, xcode 26 beta (but the non-beta should also work fine).

— Reply to this email directly, view it on GitHub https://github.com/madsmtm/objc2/issues/771#issuecomment-3092467246, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANUJDBANBA23DHCYKRQDSGL3JJ5MLAVCNFSM6AAAAACB4QXRYKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTAOJSGQ3DOMRUGY. You are receiving this because you authored the thread.

nooly1998 avatar Jul 21 '25 01:07 nooly1998

Yeah, I've seen this kind of issue when using rust-analyzer before. Probably due to our (very) weird macros. I'll keep it open in case I get around to investigating it further at some point.

madsmtm avatar Aug 06 '25 17:08 madsmtm