diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 9a3b10d70b..2be9794bb7 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -3394,9 +3394,12 @@ impl TryToRustTy for Type { TypeKind::ObjCSel => Ok(quote! { objc::runtime::Sel }), - TypeKind::ObjCId | TypeKind::ObjCInterface(..) => Ok(quote! { + TypeKind::ObjCId => Ok(quote! { id }), + TypeKind::ObjCInterface(..) => Ok(quote! { + objc::runtime::Object + }), ref u @ TypeKind::UnresolvedTypeRef(..) => { unreachable!("Should have been resolved after parsing {:?}!", u) } @@ -3644,7 +3647,7 @@ fn objc_method_codegen( method: &ObjCMethod, class_name: Option<&str>, prefix: &str, -) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) { +) -> proc_macro2::TokenStream { let signature = method.signature(); let fn_args = utils::fnsig_arguments(ctx, signature); let fn_ret = utils::fnsig_return_ty(ctx, signature); @@ -3665,15 +3668,13 @@ fn objc_method_codegen( let methods_and_args = method.format_method_call(&fn_args); let body = if method.is_class_method() { - let class_name = class_name - .expect("Generating a class method without class name?") - .to_owned(); - let expect_msg = proc_macro2::Literal::string(&format!( - "Couldn't find {}", + let class_name = ctx.rust_ident( class_name - )); + .expect("Generating a class method without class name?") + .to_owned(), + ); quote! { - msg_send!(objc::runtime::Class::get(#class_name).expect(#expect_msg), #methods_and_args) + msg_send!(class!(#class_name), #methods_and_args) } } else { quote! { @@ -3684,16 +3685,11 @@ fn objc_method_codegen( let method_name = ctx.rust_ident(format!("{}{}", prefix, method.rust_name())); - ( - quote! { - unsafe fn #method_name #sig { - #body - } - }, - quote! { - unsafe fn #method_name #sig ; - }, - ) + quote! { + unsafe fn #method_name #sig where ::Target: objc::Message + Sized { + #body + } + } } impl CodeGenerator for ObjCInterface { @@ -3708,13 +3704,10 @@ impl CodeGenerator for ObjCInterface { debug_assert!(item.is_enabled_for_codegen(ctx)); let mut impl_items = vec![]; - let mut trait_items = vec![]; for method in self.methods() { - let (impl_item, trait_item) = - objc_method_codegen(ctx, method, None, ""); + let impl_item = objc_method_codegen(ctx, method, None, ""); impl_items.push(impl_item); - trait_items.push(trait_item) } let instance_method_names: Vec<_> = @@ -3724,61 +3717,97 @@ impl CodeGenerator for ObjCInterface { let ambiquity = instance_method_names.contains(&class_method.rust_name()); let prefix = if ambiquity { "class_" } else { "" }; - let (impl_item, trait_item) = objc_method_codegen( + let impl_item = objc_method_codegen( ctx, class_method, Some(self.name()), prefix, ); impl_items.push(impl_item); - trait_items.push(trait_item) } let trait_name = ctx.rust_ident(self.rust_name()); - + let trait_constraints = quote! { + Sized + std::ops::Deref + }; let trait_block = if self.is_template() { let template_names: Vec = self .template_names .iter() .map(|g| ctx.rust_ident(g)) .collect(); + quote! { - pub trait #trait_name <#(#template_names),*>{ - #( #trait_items )* + pub trait #trait_name <#(#template_names),*> : #trait_constraints { + #( #impl_items )* } } } else { quote! { - pub trait #trait_name { - #( #trait_items )* + pub trait #trait_name : #trait_constraints { + #( #impl_items )* } } }; - let ty_for_impl = quote! { - id - }; - let impl_block = if self.is_template() { - let template_names: Vec = self - .template_names - .iter() - .map(|g| ctx.rust_ident(g)) - .collect(); - quote! { - impl <#(#template_names :'static),*> #trait_name <#(#template_names),*> for #ty_for_impl { - #( #impl_items )* + let class_name = ctx.rust_ident(self.name()); + if !self.is_category() && !self.is_protocol() { + let struct_block = quote! { + #[repr(transparent)] + #[derive(Clone, Copy)] + pub struct #class_name(pub id); + impl std::ops::Deref for #class_name { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { + &*self.0 + } + } } - } - } else { - quote! { - impl #trait_name for #ty_for_impl { - #( #impl_items )* + unsafe impl objc::Message for #class_name { } + impl #class_name { + pub fn alloc() -> Self { + Self(unsafe { + msg_send!(objc::class!(#class_name), alloc) + }) + } } + }; + result.push(struct_block); + for protocol_id in self.conforms_to.iter() { + let protocol_name = ctx.rust_ident( + ctx.resolve_type(protocol_id.expect_type_id(ctx)) + .name() + .unwrap(), + ); + let impl_trait = quote! { + impl #protocol_name for #class_name { } + }; + result.push(impl_trait); } - }; + } + + if !self.is_protocol() { + let impl_block = if self.is_template() { + let template_names: Vec = self + .template_names + .iter() + .map(|g| ctx.rust_ident(g)) + .collect(); + quote! { + impl <#(#template_names :'static),*> #trait_name <#(#template_names),*> for #class_name { + } + } + } else { + quote! { + impl #trait_name for #class_name { + } + } + }; + result.push(impl_block); + } result.push(trait_block); - result.push(impl_block); result.saw_objc(); } } diff --git a/src/ir/objc.rs b/src/ir/objc.rs index cfbf3dd0ea..ba650d57eb 100644 --- a/src/ir/objc.rs +++ b/src/ir/objc.rs @@ -31,7 +31,8 @@ pub struct ObjCInterface { /// The list of template names almost always, ObjectType or KeyType pub template_names: Vec, - conforms_to: Vec, + /// The list of protocols that this interface conforms to. + pub conforms_to: Vec, /// List of the methods defined in this interfae methods: Vec, @@ -77,15 +78,15 @@ impl ObjCInterface { /// Formats the name for rust /// Can be like NSObject, but with categories might be like NSObject_NSCoderMethods - /// and protocols are like protocol_NSObject + /// and protocols are like PNSObject pub fn rust_name(&self) -> String { if let Some(ref cat) = self.category { format!("{}_{}", self.name(), cat) } else { if self.is_protocol { - format!("protocol_{}", self.name()) + format!("P{}", self.name()) } else { - self.name().to_owned() + format!("I{}", self.name().to_owned()) } } } @@ -100,6 +101,16 @@ impl ObjCInterface { &self.methods } + /// Is this a protocol? + pub fn is_protocol(&self) -> bool { + self.is_protocol + } + + /// Is this a category? + pub fn is_category(&self) -> bool { + self.category.is_some() + } + /// List of the class methods defined in this interface pub fn class_methods(&self) -> &Vec { &self.class_methods @@ -129,7 +140,7 @@ impl ObjCInterface { } CXCursor_ObjCProtocolRef => { // Gather protocols this interface conforms to - let needle = format!("protocol_{}", c.spelling()); + let needle = format!("P{}", c.spelling()); let items_map = ctx.items(); debug!("Interface {} conforms to {}, find the item", interface.name, needle); diff --git a/tests/expectations/tests/libclang-3.8/objc_template.rs b/tests/expectations/tests/libclang-3.8/objc_template.rs index 1a6f8ec325..23a6de909d 100644 --- a/tests/expectations/tests/libclang-3.8/objc_template.rs +++ b/tests/expectations/tests/libclang-3.8/objc_template.rs @@ -8,21 +8,56 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn get(self) -> id; +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(Foo), alloc) }) + } } -impl Foo for id { - unsafe fn get(self) -> id { +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn get(self) -> id + where + ::Target: objc::Message + Sized, + { msg_send!(self, get) } } -pub trait FooMultiGeneric { - unsafe fn objectForKey_(self, key: id) -> id; +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct FooMultiGeneric(pub id); +impl std::ops::Deref for FooMultiGeneric { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for FooMultiGeneric {} +impl FooMultiGeneric { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(FooMultiGeneric), alloc) }) + } +} +impl + IFooMultiGeneric for FooMultiGeneric +{ } -impl FooMultiGeneric - for id +pub trait IFooMultiGeneric: + Sized + std::ops::Deref { - unsafe fn objectForKey_(self, key: id) -> id { + unsafe fn objectForKey_(self, key: id) -> id + where + ::Target: objc::Message + Sized, + { msg_send!(self, objectForKey: key) } } diff --git a/tests/expectations/tests/libclang-3.9/objc_template.rs b/tests/expectations/tests/libclang-3.9/objc_template.rs index 1a6f8ec325..23a6de909d 100644 --- a/tests/expectations/tests/libclang-3.9/objc_template.rs +++ b/tests/expectations/tests/libclang-3.9/objc_template.rs @@ -8,21 +8,56 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn get(self) -> id; +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(Foo), alloc) }) + } } -impl Foo for id { - unsafe fn get(self) -> id { +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn get(self) -> id + where + ::Target: objc::Message + Sized, + { msg_send!(self, get) } } -pub trait FooMultiGeneric { - unsafe fn objectForKey_(self, key: id) -> id; +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct FooMultiGeneric(pub id); +impl std::ops::Deref for FooMultiGeneric { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for FooMultiGeneric {} +impl FooMultiGeneric { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(FooMultiGeneric), alloc) }) + } +} +impl + IFooMultiGeneric for FooMultiGeneric +{ } -impl FooMultiGeneric - for id +pub trait IFooMultiGeneric: + Sized + std::ops::Deref { - unsafe fn objectForKey_(self, key: id) -> id { + unsafe fn objectForKey_(self, key: id) -> id + where + ::Target: objc::Message + Sized, + { msg_send!(self, objectForKey: key) } } diff --git a/tests/expectations/tests/libclang-4/objc_template.rs b/tests/expectations/tests/libclang-4/objc_template.rs index 1aaab1776b..25276c00fc 100644 --- a/tests/expectations/tests/libclang-4/objc_template.rs +++ b/tests/expectations/tests/libclang-4/objc_template.rs @@ -9,20 +9,56 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn get(self) - -> *mut ObjectType; +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } } -impl Foo for id { - unsafe fn get(self) -> *mut ObjectType { msg_send!(self , get) } +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(Foo), alloc) }) + } } -pub trait FooMultiGeneric { - unsafe fn objectForKey_(self, key: *mut KeyType) -> *mut ObjectType; +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn get(self) -> *mut ObjectType + where + ::Target: objc::Message + Sized, + { + msg_send!(self , get) + } +} +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct FooMultiGeneric(pub id); +impl std::ops::Deref for FooMultiGeneric { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for FooMultiGeneric {} +impl FooMultiGeneric { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(FooMultiGeneric), alloc) }) + } +} +impl + IFooMultiGeneric for FooMultiGeneric +{ } -impl FooMultiGeneric - for id +pub trait IFooMultiGeneric: + Sized + std::ops::Deref { - unsafe fn objectForKey_(self, key: *mut KeyType) -> *mut ObjectType { + unsafe fn objectForKey_(self, key: *mut KeyType) -> *mut ObjectType + where + ::Target: objc::Message + Sized, + { msg_send!(self, objectForKey: key) } } diff --git a/tests/expectations/tests/libclang-5/objc_template.rs b/tests/expectations/tests/libclang-5/objc_template.rs index 23a2369519..b4c117044c 100644 --- a/tests/expectations/tests/libclang-5/objc_template.rs +++ b/tests/expectations/tests/libclang-5/objc_template.rs @@ -12,21 +12,56 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn get(self) -> *mut ObjectType; +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(Foo), alloc) }) + } } -impl Foo for id { - unsafe fn get(self) -> *mut ObjectType { +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn get(self) -> *mut ObjectType + where + ::Target: objc::Message + Sized, + { msg_send!(self, get) } } -pub trait FooMultiGeneric { - unsafe fn objectForKey_(self, key: *mut KeyType) -> *mut ObjectType; +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct FooMultiGeneric(pub id); +impl std::ops::Deref for FooMultiGeneric { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for FooMultiGeneric {} +impl FooMultiGeneric { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(FooMultiGeneric), alloc) }) + } +} +impl + IFooMultiGeneric for FooMultiGeneric +{ } -impl FooMultiGeneric - for id +pub trait IFooMultiGeneric: + Sized + std::ops::Deref { - unsafe fn objectForKey_(self, key: *mut KeyType) -> *mut ObjectType { + unsafe fn objectForKey_(self, key: *mut KeyType) -> *mut ObjectType + where + ::Target: objc::Message + Sized, + { msg_send!(self, objectForKey: key) } } diff --git a/tests/expectations/tests/libclang-9/objc_template.rs b/tests/expectations/tests/libclang-9/objc_template.rs index 089f0398a7..4bf234d74a 100644 --- a/tests/expectations/tests/libclang-9/objc_template.rs +++ b/tests/expectations/tests/libclang-9/objc_template.rs @@ -12,21 +12,56 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn get(self) -> u64; +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(Foo), alloc) }) + } } -impl Foo for id { - unsafe fn get(self) -> u64 { +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn get(self) -> u64 + where + ::Target: objc::Message + Sized, + { msg_send!(self, get) } } -pub trait FooMultiGeneric { - unsafe fn objectForKey_(self, key: u64) -> u64; +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct FooMultiGeneric(pub id); +impl std::ops::Deref for FooMultiGeneric { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for FooMultiGeneric {} +impl FooMultiGeneric { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(FooMultiGeneric), alloc) }) + } +} +impl + IFooMultiGeneric for FooMultiGeneric +{ } -impl FooMultiGeneric - for id +pub trait IFooMultiGeneric: + Sized + std::ops::Deref { - unsafe fn objectForKey_(self, key: u64) -> u64 { + unsafe fn objectForKey_(self, key: u64) -> u64 + where + ::Target: objc::Message + Sized, + { msg_send!(self, objectForKey: key) } } diff --git a/tests/expectations/tests/objc_category.rs b/tests/expectations/tests/objc_category.rs index 48970fdee5..544903f588 100644 --- a/tests/expectations/tests/objc_category.rs +++ b/tests/expectations/tests/objc_category.rs @@ -12,19 +12,36 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn method(self); +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } } -impl Foo for id { - unsafe fn method(self) { - msg_send!(self, method) +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(Foo), alloc) }) } } -pub trait Foo_BarCategory { - unsafe fn categoryMethod(self); +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn method(self) + where + ::Target: objc::Message + Sized, + { + msg_send!(self, method) + } } -impl Foo_BarCategory for id { - unsafe fn categoryMethod(self) { +impl Foo_BarCategory for Foo {} +pub trait Foo_BarCategory: Sized + std::ops::Deref { + unsafe fn categoryMethod(self) + where + ::Target: objc::Message + Sized, + { msg_send!(self, categoryMethod) } } diff --git a/tests/expectations/tests/objc_class.rs b/tests/expectations/tests/objc_class.rs index e312f7a5ac..515d1c1601 100644 --- a/tests/expectations/tests/objc_class.rs +++ b/tests/expectations/tests/objc_class.rs @@ -13,13 +13,29 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; extern "C" { - pub static mut fooVar: *mut id; + pub static mut fooVar: *mut objc::runtime::Object; } -pub trait Foo { - unsafe fn method(self); +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(Foo), alloc) }) + } } -impl Foo for id { - unsafe fn method(self) { +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn method(self) + where + ::Target: objc::Message + Sized, + { msg_send!(self, method) } } diff --git a/tests/expectations/tests/objc_class_method.rs b/tests/expectations/tests/objc_class_method.rs index 42245b9984..d6a3343c52 100644 --- a/tests/expectations/tests/objc_class_method.rs +++ b/tests/expectations/tests/objc_class_method.rs @@ -12,54 +12,60 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn method(); - unsafe fn methodWithInt_(foo: ::std::os::raw::c_int); - unsafe fn methodWithFoo_(foo: id); - unsafe fn methodReturningInt() -> ::std::os::raw::c_int; - unsafe fn methodReturningFoo() -> *mut id; - unsafe fn methodWithArg1_andArg2_andArg3_( - intvalue: ::std::os::raw::c_int, - ptr: *mut ::std::os::raw::c_char, - floatvalue: f32, - ); +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(Foo), alloc) }) + } } -impl Foo for id { - unsafe fn method() { - msg_send!( - objc::runtime::Class::get("Foo").expect("Couldn't find Foo"), - method - ) +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn method() + where + ::Target: objc::Message + Sized, + { + msg_send!(class!(Foo), method) } - unsafe fn methodWithInt_(foo: ::std::os::raw::c_int) { - msg_send!( - objc::runtime::Class::get("Foo").expect("Couldn't find Foo"), - methodWithInt: foo - ) + unsafe fn methodWithInt_(foo: ::std::os::raw::c_int) + where + ::Target: objc::Message + Sized, + { + msg_send!(class!(Foo), methodWithInt: foo) } - unsafe fn methodWithFoo_(foo: id) { - msg_send!( - objc::runtime::Class::get("Foo").expect("Couldn't find Foo"), - methodWithFoo: foo - ) + unsafe fn methodWithFoo_(foo: id) + where + ::Target: objc::Message + Sized, + { + msg_send!(class!(Foo), methodWithFoo: foo) } - unsafe fn methodReturningInt() -> ::std::os::raw::c_int { - msg_send!( - objc::runtime::Class::get("Foo").expect("Couldn't find Foo"), - methodReturningInt - ) + unsafe fn methodReturningInt() -> ::std::os::raw::c_int + where + ::Target: objc::Message + Sized, + { + msg_send!(class!(Foo), methodReturningInt) } - unsafe fn methodReturningFoo() -> *mut id { - msg_send!( - objc::runtime::Class::get("Foo").expect("Couldn't find Foo"), - methodReturningFoo - ) + unsafe fn methodReturningFoo() -> *mut objc::runtime::Object + where + ::Target: objc::Message + Sized, + { + msg_send!(class!(Foo), methodReturningFoo) } unsafe fn methodWithArg1_andArg2_andArg3_( intvalue: ::std::os::raw::c_int, ptr: *mut ::std::os::raw::c_char, floatvalue: f32, - ) { - msg_send ! ( objc :: runtime :: Class :: get ( "Foo" ) . expect ( "Couldn't find Foo" ) , methodWithArg1 : intvalue andArg2 : ptr andArg3 : floatvalue ) + ) where + ::Target: objc::Message + Sized, + { + msg_send ! ( class ! ( Foo ) , methodWithArg1 : intvalue andArg2 : ptr andArg3 : floatvalue ) } } diff --git a/tests/expectations/tests/objc_interface.rs b/tests/expectations/tests/objc_interface.rs index b49f21f7d7..c2671317b4 100644 --- a/tests/expectations/tests/objc_interface.rs +++ b/tests/expectations/tests/objc_interface.rs @@ -12,7 +12,21 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; -pub trait Foo {} -impl Foo for id {} -pub trait protocol_bar {} -impl protocol_bar for id {} +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(Foo), alloc) }) + } +} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref {} +pub trait Pbar: Sized + std::ops::Deref {} diff --git a/tests/expectations/tests/objc_interface_type.rs b/tests/expectations/tests/objc_interface_type.rs index 5868aa7fb3..b6d166daeb 100644 --- a/tests/expectations/tests/objc_interface_type.rs +++ b/tests/expectations/tests/objc_interface_type.rs @@ -12,12 +12,27 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; -pub trait Foo {} -impl Foo for id {} +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(Foo), alloc) }) + } +} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref {} #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct FooStruct { - pub foo: *mut id, + pub foo: *mut objc::runtime::Object, } #[test] fn bindgen_test_layout_FooStruct() { @@ -53,5 +68,5 @@ extern "C" { pub fn fooFunc(foo: id); } extern "C" { - pub static mut kFoo: *const id; + pub static mut kFoo: *const objc::runtime::Object; } diff --git a/tests/expectations/tests/objc_method.rs b/tests/expectations/tests/objc_method.rs index 255d85108f..381646c4b7 100644 --- a/tests/expectations/tests/objc_method.rs +++ b/tests/expectations/tests/objc_method.rs @@ -12,40 +12,51 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn method(self); - unsafe fn methodWithInt_(self, foo: ::std::os::raw::c_int); - unsafe fn methodWithFoo_(self, foo: id); - unsafe fn methodReturningInt(self) -> ::std::os::raw::c_int; - unsafe fn methodReturningFoo(self) -> *mut id; - unsafe fn methodWithArg1_andArg2_andArg3_( - self, - intvalue: ::std::os::raw::c_int, - ptr: *mut ::std::os::raw::c_char, - floatvalue: f32, - ); - unsafe fn methodWithAndWithoutKeywords_arg2Name__arg4Name_( - self, - arg1: ::std::os::raw::c_int, - arg2: f32, - arg3: f32, - arg4: ::std::os::raw::c_int, - ) -> instancetype; +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(Foo), alloc) }) + } } -impl Foo for id { - unsafe fn method(self) { +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn method(self) + where + ::Target: objc::Message + Sized, + { msg_send!(self, method) } - unsafe fn methodWithInt_(self, foo: ::std::os::raw::c_int) { + unsafe fn methodWithInt_(self, foo: ::std::os::raw::c_int) + where + ::Target: objc::Message + Sized, + { msg_send!(self, methodWithInt: foo) } - unsafe fn methodWithFoo_(self, foo: id) { + unsafe fn methodWithFoo_(self, foo: id) + where + ::Target: objc::Message + Sized, + { msg_send!(self, methodWithFoo: foo) } - unsafe fn methodReturningInt(self) -> ::std::os::raw::c_int { + unsafe fn methodReturningInt(self) -> ::std::os::raw::c_int + where + ::Target: objc::Message + Sized, + { msg_send!(self, methodReturningInt) } - unsafe fn methodReturningFoo(self) -> *mut id { + unsafe fn methodReturningFoo(self) -> *mut objc::runtime::Object + where + ::Target: objc::Message + Sized, + { msg_send!(self, methodReturningFoo) } unsafe fn methodWithArg1_andArg2_andArg3_( @@ -53,7 +64,9 @@ impl Foo for id { intvalue: ::std::os::raw::c_int, ptr: *mut ::std::os::raw::c_char, floatvalue: f32, - ) { + ) where + ::Target: objc::Message + Sized, + { msg_send ! ( self , methodWithArg1 : intvalue andArg2 : ptr andArg3 : floatvalue ) } unsafe fn methodWithAndWithoutKeywords_arg2Name__arg4Name_( @@ -62,7 +75,10 @@ impl Foo for id { arg2: f32, arg3: f32, arg4: ::std::os::raw::c_int, - ) -> instancetype { + ) -> instancetype + where + ::Target: objc::Message + Sized, + { msg_send ! ( self , methodWithAndWithoutKeywords : arg1 arg2Name : arg2 arg3 : arg3 arg4Name : arg4 ) } } diff --git a/tests/expectations/tests/objc_method_clash.rs b/tests/expectations/tests/objc_method_clash.rs index 739d2aa96f..92b7930b4b 100644 --- a/tests/expectations/tests/objc_method_clash.rs +++ b/tests/expectations/tests/objc_method_clash.rs @@ -12,18 +12,33 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn foo(self); - unsafe fn class_foo(); +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(Foo), alloc) }) + } } -impl Foo for id { - unsafe fn foo(self) { +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { + unsafe fn foo(self) + where + ::Target: objc::Message + Sized, + { msg_send!(self, foo) } - unsafe fn class_foo() { - msg_send!( - objc::runtime::Class::get("Foo").expect("Couldn't find Foo"), - foo - ) + unsafe fn class_foo() + where + ::Target: objc::Message + Sized, + { + msg_send!(class!(Foo), foo) } } diff --git a/tests/expectations/tests/objc_property_fnptr.rs b/tests/expectations/tests/objc_property_fnptr.rs index a1c4b3d2c3..8b5ab0ac19 100644 --- a/tests/expectations/tests/objc_property_fnptr.rs +++ b/tests/expectations/tests/objc_property_fnptr.rs @@ -12,24 +12,23 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; -pub trait Foo { - unsafe fn func( - self, - ) -> ::std::option::Option< - unsafe extern "C" fn( - arg1: ::std::os::raw::c_char, - arg2: ::std::os::raw::c_short, - arg3: f32, - ) -> ::std::os::raw::c_int, - >; - unsafe fn setFunc_( - self, - func: ::std::option::Option< - unsafe extern "C" fn() -> ::std::os::raw::c_int, - >, - ); +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(Foo), alloc) }) + } } -impl Foo for id { +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref { unsafe fn func( self, ) -> ::std::option::Option< @@ -38,7 +37,10 @@ impl Foo for id { arg2: ::std::os::raw::c_short, arg3: f32, ) -> ::std::os::raw::c_int, - > { + > + where + ::Target: objc::Message + Sized, + { msg_send!(self, func) } unsafe fn setFunc_( @@ -46,7 +48,9 @@ impl Foo for id { func: ::std::option::Option< unsafe extern "C" fn() -> ::std::os::raw::c_int, >, - ) { + ) where + ::Target: objc::Message + Sized, + { msg_send!(self, setFunc: func) } } diff --git a/tests/expectations/tests/objc_protocol.rs b/tests/expectations/tests/objc_protocol.rs index aeb6de026b..25870f2aca 100644 --- a/tests/expectations/tests/objc_protocol.rs +++ b/tests/expectations/tests/objc_protocol.rs @@ -12,7 +12,22 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; -pub trait protocol_Foo {} -impl protocol_Foo for id {} -pub trait Foo {} -impl Foo for id {} +pub trait PFoo: Sized + std::ops::Deref {} +#[repr(transparent)] +#[derive(Clone, Copy)] +pub struct Foo(pub id); +impl std::ops::Deref for Foo { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Foo {} +impl Foo { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(Foo), alloc) }) + } +} +impl PFoo for Foo {} +impl IFoo for Foo {} +pub trait IFoo: Sized + std::ops::Deref {} diff --git a/tests/expectations/tests/objc_whitelist.rs b/tests/expectations/tests/objc_whitelist.rs index 3089fb7f69..f4c0e231e7 100644 --- a/tests/expectations/tests/objc_whitelist.rs +++ b/tests/expectations/tests/objc_whitelist.rs @@ -12,37 +12,5 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; -pub trait protocol_SomeProtocol { - unsafe fn protocolMethod(self); - unsafe fn protocolClassMethod(); -} -impl protocol_SomeProtocol for id { - unsafe fn protocolMethod(self) { - msg_send!(self, protocolMethod) - } - unsafe fn protocolClassMethod() { - msg_send!( - objc::runtime::Class::get("SomeProtocol") - .expect("Couldn't find SomeProtocol"), - protocolClassMethod - ) - } -} -pub trait WhitelistMe { - unsafe fn method(self); - unsafe fn classMethod(); -} -impl WhitelistMe for id { - unsafe fn method(self) { - msg_send!(self, method) - } - unsafe fn classMethod() { - msg_send!( - objc::runtime::Class::get("WhitelistMe") - .expect("Couldn't find WhitelistMe"), - classMethod - ) - } -} -pub trait WhitelistMe_InterestingCategory {} -impl WhitelistMe_InterestingCategory for id {} +impl WhitelistMe_InterestingCategory for WhitelistMe {} +pub trait WhitelistMe_InterestingCategory: Sized + std::ops::Deref {}