diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ab8200986..487405ee8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -120,11 +120,11 @@ Released YYYY/MM/DD ## Added -* TODO (or remove section if none) +* Objective-c bindings generate `From for ParentClass` as well as `TryFrom for ChildClass` ([#1883][]). ## Changed -* TODO (or remove section if none) +* Objective-c bindings borrow self rather than take ownership ([#1883][]). ## Deprecated @@ -136,12 +136,15 @@ Released YYYY/MM/DD ## Fixed -* TODO (or remove section if none) +* Fixed objective-c protocol impl blocks for parent classes's protocols ([#1883][]). ## Security * TODO (or remove section if none) + +[#1883]: https://github.com/rust-lang/rust-bindgen/issues/1883 + -------------------------------------------------------------------------------- # 0.55.1 diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 1ad413ffe2..c08196090d 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -3806,7 +3806,7 @@ fn objc_method_codegen( } } else { let fn_args = fn_args.clone(); - let args = iter::once(quote! { self }).chain(fn_args.into_iter()); + let args = iter::once(quote! { &self }).chain(fn_args.into_iter()); quote! { ( #( #args ),* ) #fn_ret } @@ -3825,7 +3825,7 @@ fn objc_method_codegen( } } else { quote! { - msg_send!(self, #methods_and_args) + msg_send!(*self, #methods_and_args) } }; @@ -3901,7 +3901,7 @@ impl CodeGenerator for ObjCInterface { if !self.is_category() && !self.is_protocol() { let struct_block = quote! { #[repr(transparent)] - #[derive(Clone, Copy)] + #[derive(Clone)] pub struct #class_name(pub id); impl std::ops::Deref for #class_name { type Target = objc::runtime::Object; @@ -3921,7 +3921,9 @@ impl CodeGenerator for ObjCInterface { } }; result.push(struct_block); + let mut protocol_set: HashSet = Default::default(); for protocol_id in self.conforms_to.iter() { + protocol_set.insert(*protocol_id); let protocol_name = ctx.rust_ident( ctx.resolve_type(protocol_id.expect_type_id(ctx)) .name() @@ -3962,6 +3964,53 @@ impl CodeGenerator for ObjCInterface { } }; result.push(impl_trait); + for protocol_id in parent.conforms_to.iter() { + if protocol_set.insert(*protocol_id) { + 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 !parent.is_template() { + let parent_struct_name = parent.name(); + let child_struct_name = self.name(); + let parent_struct = ctx.rust_ident(parent_struct_name); + let from_block = quote! { + impl From<#class_name> for #parent_struct { + fn from(child: #class_name) -> #parent_struct { + #parent_struct(child.0) + } + } + }; + result.push(from_block); + + let error_msg = format!( + "This {} cannot be downcasted to {}", + parent_struct_name, child_struct_name + ); + let try_into_block = quote! { + impl std::convert::TryFrom<#parent_struct> for #class_name { + type Error = &'static str; + fn try_from(parent: #parent_struct) -> Result<#class_name, Self::Error> { + let is_kind_of : bool = unsafe { msg_send!(parent, isKindOfClass:class!(#class_name))}; + if is_kind_of { + Ok(#class_name(parent.0)) + } else { + Err(#error_msg) + } + } + } + }; + result.push(try_into_block); + } parent.parent_class } else { None diff --git a/tests/expectations/tests/libclang-3.9/objc_inheritance.rs b/tests/expectations/tests/libclang-3.9/objc_inheritance.rs index cd2b085dc3..5f07dbaab1 100644 --- a/tests/expectations/tests/libclang-3.9/objc_inheritance.rs +++ b/tests/expectations/tests/libclang-3.9/objc_inheritance.rs @@ -11,7 +11,7 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; @@ -28,7 +28,7 @@ impl Foo { impl IFoo for Foo {} pub trait IFoo: Sized + std::ops::Deref {} #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Bar(pub id); impl std::ops::Deref for Bar { type Target = objc::runtime::Object; @@ -43,10 +43,27 @@ impl Bar { } } impl IFoo for Bar {} +impl From for Foo { + fn from(child: Bar) -> Foo { + Foo(child.0) + } +} +impl std::convert::TryFrom for Bar { + type Error = &'static str; + fn try_from(parent: Foo) -> Result { + let is_kind_of: bool = + unsafe { msg_send!(parent, isKindOfClass: class!(Bar)) }; + if is_kind_of { + Ok(Bar(parent.0)) + } else { + Err("This Foo cannot be downcasted to Bar") + } + } +} impl IBar for Bar {} pub trait IBar: Sized + std::ops::Deref {} #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Baz(pub id); impl std::ops::Deref for Baz { type Target = objc::runtime::Object; @@ -61,6 +78,40 @@ impl Baz { } } impl IBar for Baz {} +impl From for Bar { + fn from(child: Baz) -> Bar { + Bar(child.0) + } +} +impl std::convert::TryFrom for Baz { + type Error = &'static str; + fn try_from(parent: Bar) -> Result { + let is_kind_of: bool = + unsafe { msg_send!(parent, isKindOfClass: class!(Baz)) }; + if is_kind_of { + Ok(Baz(parent.0)) + } else { + Err("This Bar cannot be downcasted to Baz") + } + } +} impl IFoo for Baz {} +impl From for Foo { + fn from(child: Baz) -> Foo { + Foo(child.0) + } +} +impl std::convert::TryFrom for Baz { + type Error = &'static str; + fn try_from(parent: Foo) -> Result { + let is_kind_of: bool = + unsafe { msg_send!(parent, isKindOfClass: class!(Baz)) }; + if is_kind_of { + Ok(Baz(parent.0)) + } else { + Err("This Foo cannot be downcasted to Baz") + } + } +} impl IBaz for Baz {} pub trait IBaz: Sized + std::ops::Deref {} diff --git a/tests/expectations/tests/libclang-3.9/objc_template.rs b/tests/expectations/tests/libclang-3.9/objc_template.rs index 9c5a5b75a2..4ccf72b71b 100644 --- a/tests/expectations/tests/libclang-3.9/objc_template.rs +++ b/tests/expectations/tests/libclang-3.9/objc_template.rs @@ -11,7 +11,7 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; @@ -27,15 +27,15 @@ impl Foo { } impl IFoo for Foo {} pub trait IFoo: Sized + std::ops::Deref { - unsafe fn get(self) -> id + unsafe fn get(&self) -> id where ::Target: objc::Message + Sized, { - msg_send!(self, get) + msg_send!(*self, get) } } #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct FooMultiGeneric(pub id); impl std::ops::Deref for FooMultiGeneric { type Target = objc::runtime::Object; @@ -56,10 +56,10 @@ impl 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) + msg_send!(*self, objectForKey: key) } } diff --git a/tests/expectations/tests/libclang-4/objc_inheritance.rs b/tests/expectations/tests/libclang-4/objc_inheritance.rs index cd2b085dc3..5f07dbaab1 100644 --- a/tests/expectations/tests/libclang-4/objc_inheritance.rs +++ b/tests/expectations/tests/libclang-4/objc_inheritance.rs @@ -11,7 +11,7 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; @@ -28,7 +28,7 @@ impl Foo { impl IFoo for Foo {} pub trait IFoo: Sized + std::ops::Deref {} #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Bar(pub id); impl std::ops::Deref for Bar { type Target = objc::runtime::Object; @@ -43,10 +43,27 @@ impl Bar { } } impl IFoo for Bar {} +impl From for Foo { + fn from(child: Bar) -> Foo { + Foo(child.0) + } +} +impl std::convert::TryFrom for Bar { + type Error = &'static str; + fn try_from(parent: Foo) -> Result { + let is_kind_of: bool = + unsafe { msg_send!(parent, isKindOfClass: class!(Bar)) }; + if is_kind_of { + Ok(Bar(parent.0)) + } else { + Err("This Foo cannot be downcasted to Bar") + } + } +} impl IBar for Bar {} pub trait IBar: Sized + std::ops::Deref {} #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Baz(pub id); impl std::ops::Deref for Baz { type Target = objc::runtime::Object; @@ -61,6 +78,40 @@ impl Baz { } } impl IBar for Baz {} +impl From for Bar { + fn from(child: Baz) -> Bar { + Bar(child.0) + } +} +impl std::convert::TryFrom for Baz { + type Error = &'static str; + fn try_from(parent: Bar) -> Result { + let is_kind_of: bool = + unsafe { msg_send!(parent, isKindOfClass: class!(Baz)) }; + if is_kind_of { + Ok(Baz(parent.0)) + } else { + Err("This Bar cannot be downcasted to Baz") + } + } +} impl IFoo for Baz {} +impl From for Foo { + fn from(child: Baz) -> Foo { + Foo(child.0) + } +} +impl std::convert::TryFrom for Baz { + type Error = &'static str; + fn try_from(parent: Foo) -> Result { + let is_kind_of: bool = + unsafe { msg_send!(parent, isKindOfClass: class!(Baz)) }; + if is_kind_of { + Ok(Baz(parent.0)) + } else { + Err("This Foo cannot be downcasted to Baz") + } + } +} impl IBaz for Baz {} pub trait IBaz: Sized + std::ops::Deref {} diff --git a/tests/expectations/tests/libclang-4/objc_template.rs b/tests/expectations/tests/libclang-4/objc_template.rs index eab2e36a5a..36b7d22baa 100644 --- a/tests/expectations/tests/libclang-4/objc_template.rs +++ b/tests/expectations/tests/libclang-4/objc_template.rs @@ -11,7 +11,7 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; @@ -27,15 +27,15 @@ impl Foo { } impl IFoo for Foo {} pub trait IFoo: Sized + std::ops::Deref { - unsafe fn get(self) -> *mut ObjectType + unsafe fn get(&self) -> *mut ObjectType where ::Target: objc::Message + Sized, { - msg_send!(self, get) + msg_send!(*self, get) } } #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct FooMultiGeneric(pub id); impl std::ops::Deref for FooMultiGeneric { type Target = objc::runtime::Object; @@ -56,10 +56,10 @@ impl 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) + msg_send!(*self, objectForKey: key) } } diff --git a/tests/expectations/tests/libclang-5/objc_inheritance.rs b/tests/expectations/tests/libclang-5/objc_inheritance.rs index cd2b085dc3..5f07dbaab1 100644 --- a/tests/expectations/tests/libclang-5/objc_inheritance.rs +++ b/tests/expectations/tests/libclang-5/objc_inheritance.rs @@ -11,7 +11,7 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; @@ -28,7 +28,7 @@ impl Foo { impl IFoo for Foo {} pub trait IFoo: Sized + std::ops::Deref {} #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Bar(pub id); impl std::ops::Deref for Bar { type Target = objc::runtime::Object; @@ -43,10 +43,27 @@ impl Bar { } } impl IFoo for Bar {} +impl From for Foo { + fn from(child: Bar) -> Foo { + Foo(child.0) + } +} +impl std::convert::TryFrom for Bar { + type Error = &'static str; + fn try_from(parent: Foo) -> Result { + let is_kind_of: bool = + unsafe { msg_send!(parent, isKindOfClass: class!(Bar)) }; + if is_kind_of { + Ok(Bar(parent.0)) + } else { + Err("This Foo cannot be downcasted to Bar") + } + } +} impl IBar for Bar {} pub trait IBar: Sized + std::ops::Deref {} #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Baz(pub id); impl std::ops::Deref for Baz { type Target = objc::runtime::Object; @@ -61,6 +78,40 @@ impl Baz { } } impl IBar for Baz {} +impl From for Bar { + fn from(child: Baz) -> Bar { + Bar(child.0) + } +} +impl std::convert::TryFrom for Baz { + type Error = &'static str; + fn try_from(parent: Bar) -> Result { + let is_kind_of: bool = + unsafe { msg_send!(parent, isKindOfClass: class!(Baz)) }; + if is_kind_of { + Ok(Baz(parent.0)) + } else { + Err("This Bar cannot be downcasted to Baz") + } + } +} impl IFoo for Baz {} +impl From for Foo { + fn from(child: Baz) -> Foo { + Foo(child.0) + } +} +impl std::convert::TryFrom for Baz { + type Error = &'static str; + fn try_from(parent: Foo) -> Result { + let is_kind_of: bool = + unsafe { msg_send!(parent, isKindOfClass: class!(Baz)) }; + if is_kind_of { + Ok(Baz(parent.0)) + } else { + Err("This Foo cannot be downcasted to Baz") + } + } +} impl IBaz for Baz {} pub trait IBaz: Sized + std::ops::Deref {} diff --git a/tests/expectations/tests/libclang-5/objc_template.rs b/tests/expectations/tests/libclang-5/objc_template.rs index eab2e36a5a..36b7d22baa 100644 --- a/tests/expectations/tests/libclang-5/objc_template.rs +++ b/tests/expectations/tests/libclang-5/objc_template.rs @@ -11,7 +11,7 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; @@ -27,15 +27,15 @@ impl Foo { } impl IFoo for Foo {} pub trait IFoo: Sized + std::ops::Deref { - unsafe fn get(self) -> *mut ObjectType + unsafe fn get(&self) -> *mut ObjectType where ::Target: objc::Message + Sized, { - msg_send!(self, get) + msg_send!(*self, get) } } #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct FooMultiGeneric(pub id); impl std::ops::Deref for FooMultiGeneric { type Target = objc::runtime::Object; @@ -56,10 +56,10 @@ impl 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) + msg_send!(*self, objectForKey: key) } } diff --git a/tests/expectations/tests/libclang-9/objc_inheritance.rs b/tests/expectations/tests/libclang-9/objc_inheritance.rs index cd2b085dc3..5f07dbaab1 100644 --- a/tests/expectations/tests/libclang-9/objc_inheritance.rs +++ b/tests/expectations/tests/libclang-9/objc_inheritance.rs @@ -11,7 +11,7 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; @@ -28,7 +28,7 @@ impl Foo { impl IFoo for Foo {} pub trait IFoo: Sized + std::ops::Deref {} #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Bar(pub id); impl std::ops::Deref for Bar { type Target = objc::runtime::Object; @@ -43,10 +43,27 @@ impl Bar { } } impl IFoo for Bar {} +impl From for Foo { + fn from(child: Bar) -> Foo { + Foo(child.0) + } +} +impl std::convert::TryFrom for Bar { + type Error = &'static str; + fn try_from(parent: Foo) -> Result { + let is_kind_of: bool = + unsafe { msg_send!(parent, isKindOfClass: class!(Bar)) }; + if is_kind_of { + Ok(Bar(parent.0)) + } else { + Err("This Foo cannot be downcasted to Bar") + } + } +} impl IBar for Bar {} pub trait IBar: Sized + std::ops::Deref {} #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Baz(pub id); impl std::ops::Deref for Baz { type Target = objc::runtime::Object; @@ -61,6 +78,40 @@ impl Baz { } } impl IBar for Baz {} +impl From for Bar { + fn from(child: Baz) -> Bar { + Bar(child.0) + } +} +impl std::convert::TryFrom for Baz { + type Error = &'static str; + fn try_from(parent: Bar) -> Result { + let is_kind_of: bool = + unsafe { msg_send!(parent, isKindOfClass: class!(Baz)) }; + if is_kind_of { + Ok(Baz(parent.0)) + } else { + Err("This Bar cannot be downcasted to Baz") + } + } +} impl IFoo for Baz {} +impl From for Foo { + fn from(child: Baz) -> Foo { + Foo(child.0) + } +} +impl std::convert::TryFrom for Baz { + type Error = &'static str; + fn try_from(parent: Foo) -> Result { + let is_kind_of: bool = + unsafe { msg_send!(parent, isKindOfClass: class!(Baz)) }; + if is_kind_of { + Ok(Baz(parent.0)) + } else { + Err("This Foo cannot be downcasted to Baz") + } + } +} impl IBaz for Baz {} pub trait IBaz: Sized + std::ops::Deref {} diff --git a/tests/expectations/tests/libclang-9/objc_template.rs b/tests/expectations/tests/libclang-9/objc_template.rs index 09cc739c1c..88cf209bdf 100644 --- a/tests/expectations/tests/libclang-9/objc_template.rs +++ b/tests/expectations/tests/libclang-9/objc_template.rs @@ -11,7 +11,7 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; @@ -27,15 +27,15 @@ impl Foo { } impl IFoo for Foo {} pub trait IFoo: Sized + std::ops::Deref { - unsafe fn get(self) -> u64 + unsafe fn get(&self) -> u64 where ::Target: objc::Message + Sized, { - msg_send!(self, get) + msg_send!(*self, get) } } #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct FooMultiGeneric(pub id); impl std::ops::Deref for FooMultiGeneric { type Target = objc::runtime::Object; @@ -56,10 +56,10 @@ impl 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) + msg_send!(*self, objectForKey: key) } } diff --git a/tests/expectations/tests/objc_category.rs b/tests/expectations/tests/objc_category.rs index 2c39be96be..e0328c708f 100644 --- a/tests/expectations/tests/objc_category.rs +++ b/tests/expectations/tests/objc_category.rs @@ -11,7 +11,7 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; @@ -27,19 +27,19 @@ impl Foo { } impl IFoo for Foo {} pub trait IFoo: Sized + std::ops::Deref { - unsafe fn method(self) + unsafe fn method(&self) where ::Target: objc::Message + Sized, { - msg_send!(self, method) + msg_send!(*self, method) } } impl Foo_BarCategory for Foo {} pub trait Foo_BarCategory: Sized + std::ops::Deref { - unsafe fn categoryMethod(self) + unsafe fn categoryMethod(&self) where ::Target: objc::Message + Sized, { - msg_send!(self, categoryMethod) + msg_send!(*self, categoryMethod) } } diff --git a/tests/expectations/tests/objc_class.rs b/tests/expectations/tests/objc_class.rs index a1de91fb99..5a8a71d164 100644 --- a/tests/expectations/tests/objc_class.rs +++ b/tests/expectations/tests/objc_class.rs @@ -14,7 +14,7 @@ extern "C" { pub static mut fooVar: Foo; } #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; @@ -30,10 +30,10 @@ impl Foo { } impl IFoo for Foo {} pub trait IFoo: Sized + std::ops::Deref { - unsafe fn method(self) + unsafe fn method(&self) where ::Target: objc::Message + Sized, { - msg_send!(self, method) + msg_send!(*self, method) } } diff --git a/tests/expectations/tests/objc_class_method.rs b/tests/expectations/tests/objc_class_method.rs index d28a233da2..d1f39b0c7d 100644 --- a/tests/expectations/tests/objc_class_method.rs +++ b/tests/expectations/tests/objc_class_method.rs @@ -11,7 +11,7 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; diff --git a/tests/expectations/tests/objc_interface.rs b/tests/expectations/tests/objc_interface.rs index 7cabf762af..c5ba2758b9 100644 --- a/tests/expectations/tests/objc_interface.rs +++ b/tests/expectations/tests/objc_interface.rs @@ -11,7 +11,7 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; diff --git a/tests/expectations/tests/objc_interface_type.rs b/tests/expectations/tests/objc_interface_type.rs index e8a1596378..2585df6ec1 100644 --- a/tests/expectations/tests/objc_interface_type.rs +++ b/tests/expectations/tests/objc_interface_type.rs @@ -11,7 +11,7 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; diff --git a/tests/expectations/tests/objc_method.rs b/tests/expectations/tests/objc_method.rs index e24768d28e..7c4fbd4309 100644 --- a/tests/expectations/tests/objc_method.rs +++ b/tests/expectations/tests/objc_method.rs @@ -11,7 +11,7 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; @@ -27,48 +27,48 @@ impl Foo { } impl IFoo for Foo {} pub trait IFoo: Sized + std::ops::Deref { - unsafe fn method(self) + unsafe fn method(&self) where ::Target: objc::Message + Sized, { - msg_send!(self, method) + 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) + msg_send!(*self, methodWithInt: foo) } - unsafe fn methodWithFoo_(self, foo: Foo) + unsafe fn methodWithFoo_(&self, foo: Foo) where ::Target: objc::Message + Sized, { - msg_send!(self, methodWithFoo: foo) + 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) + msg_send!(*self, methodReturningInt) } - unsafe fn methodReturningFoo(self) -> Foo + unsafe fn methodReturningFoo(&self) -> Foo where ::Target: objc::Message + Sized, { - msg_send!(self, methodReturningFoo) + msg_send!(*self, methodReturningFoo) } unsafe fn methodWithArg1_andArg2_andArg3_( - self, + &self, 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 ) + msg_send ! ( * self , methodWithArg1 : intvalue andArg2 : ptr andArg3 : floatvalue ) } unsafe fn methodWithAndWithoutKeywords_arg2Name__arg4Name_( - self, + &self, arg1: ::std::os::raw::c_int, arg2: f32, arg3: f32, @@ -77,7 +77,7 @@ pub trait IFoo: Sized + std::ops::Deref { where ::Target: objc::Message + Sized, { - msg_send ! ( self , methodWithAndWithoutKeywords : arg1 arg2Name : arg2 arg3 : arg3 arg4Name : arg4 ) + msg_send ! ( * self , methodWithAndWithoutKeywords : arg1 arg2Name : arg2 arg3 : arg3 arg4Name : arg4 ) } } pub type instancetype = id; diff --git a/tests/expectations/tests/objc_method_clash.rs b/tests/expectations/tests/objc_method_clash.rs index ba741f8d3a..8370f33fc2 100644 --- a/tests/expectations/tests/objc_method_clash.rs +++ b/tests/expectations/tests/objc_method_clash.rs @@ -11,7 +11,7 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; @@ -27,11 +27,11 @@ impl Foo { } impl IFoo for Foo {} pub trait IFoo: Sized + std::ops::Deref { - unsafe fn foo(self) + unsafe fn foo(&self) where ::Target: objc::Message + Sized, { - msg_send!(self, foo) + msg_send!(*self, foo) } unsafe fn class_foo() where diff --git a/tests/expectations/tests/objc_pointer_return_types.rs b/tests/expectations/tests/objc_pointer_return_types.rs index 0f222c8b48..c9b6b52a6b 100644 --- a/tests/expectations/tests/objc_pointer_return_types.rs +++ b/tests/expectations/tests/objc_pointer_return_types.rs @@ -11,7 +11,7 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Bar(pub id); impl std::ops::Deref for Bar { type Target = objc::runtime::Object; @@ -28,7 +28,7 @@ impl Bar { impl IBar for Bar {} pub trait IBar: Sized + std::ops::Deref {} #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; @@ -44,11 +44,11 @@ impl Foo { } impl IFoo for Foo {} pub trait IFoo: Sized + std::ops::Deref { - unsafe fn methodUsingBar_(self, my_bar: Bar) + unsafe fn methodUsingBar_(&self, my_bar: Bar) where ::Target: objc::Message + Sized, { - msg_send!(self, methodUsingBar: my_bar) + msg_send!(*self, methodUsingBar: my_bar) } unsafe fn methodReturningBar() -> Bar where diff --git a/tests/expectations/tests/objc_property_fnptr.rs b/tests/expectations/tests/objc_property_fnptr.rs index b9bcf306d8..85f18e9c18 100644 --- a/tests/expectations/tests/objc_property_fnptr.rs +++ b/tests/expectations/tests/objc_property_fnptr.rs @@ -11,7 +11,7 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; @@ -28,7 +28,7 @@ impl Foo { impl IFoo for Foo {} pub trait IFoo: Sized + std::ops::Deref { unsafe fn func( - self, + &self, ) -> ::std::option::Option< unsafe extern "C" fn( arg1: ::std::os::raw::c_char, @@ -39,10 +39,10 @@ pub trait IFoo: Sized + std::ops::Deref { where ::Target: objc::Message + Sized, { - msg_send!(self, func) + msg_send!(*self, func) } unsafe fn setFunc_( - self, + &self, func: ::std::option::Option< unsafe extern "C" fn( arg1: ::std::os::raw::c_char, @@ -53,6 +53,6 @@ pub trait IFoo: Sized + std::ops::Deref { ) where ::Target: objc::Message + Sized, { - msg_send!(self, setFunc: func) + msg_send!(*self, setFunc: func) } } diff --git a/tests/expectations/tests/objc_protocol.rs b/tests/expectations/tests/objc_protocol.rs index 5a659b2cbb..e68ddcc1d2 100644 --- a/tests/expectations/tests/objc_protocol.rs +++ b/tests/expectations/tests/objc_protocol.rs @@ -12,7 +12,7 @@ extern crate objc; pub type id = *mut objc::runtime::Object; pub trait PFoo: Sized + std::ops::Deref {} #[repr(transparent)] -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct Foo(pub id); impl std::ops::Deref for Foo { type Target = objc::runtime::Object; diff --git a/tests/expectations/tests/objc_protocol_inheritance.rs b/tests/expectations/tests/objc_protocol_inheritance.rs new file mode 100644 index 0000000000..598273ba35 --- /dev/null +++ b/tests/expectations/tests/objc_protocol_inheritance.rs @@ -0,0 +1,67 @@ +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] +#![cfg(target_os = "macos")] + +#[macro_use] +extern crate objc; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +pub trait PFoo: Sized + std::ops::Deref {} +#[repr(transparent)] +#[derive(Clone)] +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 {} +#[repr(transparent)] +#[derive(Clone)] +pub struct Bar(pub id); +impl std::ops::Deref for Bar { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Bar {} +impl Bar { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(Bar), alloc) }) + } +} +impl IFoo for Bar {} +impl PFoo for Bar {} +impl From for Foo { + fn from(child: Bar) -> Foo { + Foo(child.0) + } +} +impl std::convert::TryFrom for Bar { + type Error = &'static str; + fn try_from(parent: Foo) -> Result { + let is_kind_of: bool = + unsafe { msg_send!(parent, isKindOfClass: class!(Bar)) }; + if is_kind_of { + Ok(Bar(parent.0)) + } else { + Err("This Foo cannot be downcasted to Bar") + } + } +} +impl IBar for Bar {} +pub trait IBar: Sized + std::ops::Deref {} diff --git a/tests/headers/objc_protocol_inheritance.h b/tests/headers/objc_protocol_inheritance.h new file mode 100644 index 0000000000..d5f3a490e5 --- /dev/null +++ b/tests/headers/objc_protocol_inheritance.h @@ -0,0 +1,11 @@ +// bindgen-flags: --objc-extern-crate -- -x objective-c +// bindgen-osx-only + +@protocol Foo +@end + +@interface Foo +@end + +@interface Bar : Foo +@end