From b1b1d038bb7cfabed6eaef7a4a2b295a5db5fbb1 Mon Sep 17 00:00:00 2001 From: Sebastian Imlay Date: Mon, 24 Aug 2020 14:21:03 -0700 Subject: [PATCH 01/10] Initial stuff for changing ownership and adding inheritance --- src/codegen/mod.rs | 17 +++++++++-- .../tests/libclang-9/objc_inheritance.rs | 21 +++++++++++-- .../tests/libclang-9/objc_template.rs | 12 ++++---- tests/expectations/tests/objc_category.rs | 10 +++---- tests/expectations/tests/objc_class.rs | 6 ++-- tests/expectations/tests/objc_class_method.rs | 2 +- tests/expectations/tests/objc_interface.rs | 2 +- .../expectations/tests/objc_interface_type.rs | 2 +- tests/expectations/tests/objc_method.rs | 30 +++++++++---------- tests/expectations/tests/objc_method_clash.rs | 6 ++-- .../tests/objc_pointer_return_types.rs | 8 ++--- .../expectations/tests/objc_property_fnptr.rs | 10 +++---- tests/expectations/tests/objc_protocol.rs | 2 +- 13 files changed, 77 insertions(+), 51 deletions(-) diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 60e0e5929f..cba826d8e8 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -3810,7 +3810,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 } @@ -3829,7 +3829,7 @@ fn objc_method_codegen( } } else { quote! { - msg_send!(self, #methods_and_args) + msg_send!(*self, #methods_and_args) } }; @@ -3905,7 +3905,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; @@ -3966,6 +3966,17 @@ impl CodeGenerator for ObjCInterface { } }; result.push(impl_trait); + if !parent.is_template() { + let parent_struct_name = ctx.rust_ident(parent.name()); + let from_block = quote! { + impl From<#class_name> for #parent_struct_name { + fn from(child: #class_name) -> #parent_struct_name { + #parent_struct_name(child.0) + } + } + }; + result.push(from_block); + } parent.parent_class } else { None diff --git a/tests/expectations/tests/libclang-9/objc_inheritance.rs b/tests/expectations/tests/libclang-9/objc_inheritance.rs index cd2b085dc3..ef16325e15 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,15 @@ impl Bar { } } impl IFoo for Bar {} +impl From for Foo { + fn from(child: Bar) -> Foo { + Foo(child.0) + } +} 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 +66,16 @@ impl Baz { } } impl IBar for Baz {} +impl From for Bar { + fn from(child: Baz) -> Bar { + Bar(child.0) + } +} impl IFoo for Baz {} +impl From for Foo { + fn from(child: Baz) -> Foo { + Foo(child.0) + } +} 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; From 64a16c9247c5468fa3a71b5d5840e0a0c24e2bfe Mon Sep 17 00:00:00 2001 From: Sebastian Imlay Date: Fri, 28 Aug 2020 16:30:47 -0700 Subject: [PATCH 02/10] Updates base on comments * Added TryInto trait implementation from parent to child interfaces. * Added HashSet for protocols so that the protocol inheritance works as well. --- src/codegen/mod.rs | 47 +++++++++++-- .../tests/libclang-9/objc_inheritance.rs | 45 ++++++++++++ .../tests/objc_protocol_inheritance.rs | 70 +++++++++++++++++++ tests/headers/objc_protocol_inheritance.h | 11 +++ 4 files changed, 167 insertions(+), 6 deletions(-) create mode 100644 tests/expectations/tests/objc_protocol_inheritance.rs create mode 100644 tests/headers/objc_protocol_inheritance.h diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index cba826d8e8..7837091a6e 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -49,6 +49,7 @@ use crate::{Entry, HashMap, HashSet}; use std; use std::borrow::Cow; use std::cell::Cell; +use std::collections::HashSet as CollectionHashSet; use std::collections::VecDeque; use std::fmt::Write; use std::iter; @@ -3925,11 +3926,13 @@ impl CodeGenerator for ObjCInterface { } }; result.push(struct_block); + let mut protocol_set : CollectionHashSet = CollectionHashSet::new(); 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() - .unwrap(), + .name() + .unwrap(), ); let impl_trait = quote! { impl #protocol_name for #class_name { } @@ -3966,16 +3969,48 @@ impl CodeGenerator for ObjCInterface { } }; result.push(impl_trait); + for protocol_id in parent.conforms_to.iter() { + if !protocol_set.contains(protocol_id) { + + 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 = ctx.rust_ident(parent.name()); + 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_name { - fn from(child: #class_name) -> #parent_struct_name { - #parent_struct_name(child.0) + impl From<#class_name> for #parent_struct { + fn from(child: #class_name) -> #parent_struct { + #parent_struct(child.0) } } }; result.push(from_block); + + let try_into_block = quote! { + impl std::convert::TryFrom<#parent_struct> for #class_name { + type Error = String; + 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(format!("This {} is not an cannot be downcasted to {}", #parent_struct_name, #child_struct_name)) + } + } + } + }; + result.push(try_into_block); } parent.parent_class } else { diff --git a/tests/expectations/tests/libclang-9/objc_inheritance.rs b/tests/expectations/tests/libclang-9/objc_inheritance.rs index ef16325e15..a84f6f371b 100644 --- a/tests/expectations/tests/libclang-9/objc_inheritance.rs +++ b/tests/expectations/tests/libclang-9/objc_inheritance.rs @@ -48,6 +48,21 @@ impl From for Foo { Foo(child.0) } } +impl std::convert::TryFrom for Bar { + type Error = String; + 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(format!( + "This {} is not an cannot be downcasted to {}", + "Foo", "Bar" + )) + } + } +} impl IBar for Bar {} pub trait IBar: Sized + std::ops::Deref {} #[repr(transparent)] @@ -71,11 +86,41 @@ impl From for Bar { Bar(child.0) } } +impl std::convert::TryFrom for Baz { + type Error = String; + 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(format!( + "This {} is not an cannot be downcasted to {}", + "Bar", "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 = String; + 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(format!( + "This {} is not an cannot be downcasted to {}", + "Foo", "Baz" + )) + } + } +} impl IBaz for Baz {} pub trait IBaz: Sized + std::ops::Deref {} diff --git a/tests/expectations/tests/objc_protocol_inheritance.rs b/tests/expectations/tests/objc_protocol_inheritance.rs new file mode 100644 index 0000000000..14570e1ee3 --- /dev/null +++ b/tests/expectations/tests/objc_protocol_inheritance.rs @@ -0,0 +1,70 @@ +#![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 = String; + 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(format!( + "This {} is not an cannot be downcasted to {}", + "Foo", "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 From 600cbddf03da975cb091af70c19f28bebe951e45 Mon Sep 17 00:00:00 2001 From: Sebastian Imlay Date: Fri, 28 Aug 2020 16:34:05 -0700 Subject: [PATCH 03/10] ran cargo fmt --- src/codegen/mod.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 7837091a6e..39803a1e55 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -3926,13 +3926,14 @@ impl CodeGenerator for ObjCInterface { } }; result.push(struct_block); - let mut protocol_set : CollectionHashSet = CollectionHashSet::new(); + let mut protocol_set: CollectionHashSet = + CollectionHashSet::new(); 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() - .unwrap(), + .name() + .unwrap(), ); let impl_trait = quote! { impl #protocol_name for #class_name { } @@ -3971,10 +3972,11 @@ impl CodeGenerator for ObjCInterface { result.push(impl_trait); for protocol_id in parent.conforms_to.iter() { if !protocol_set.contains(protocol_id) { - protocol_set.insert(*protocol_id); let protocol_name = ctx.rust_ident( - ctx.resolve_type(protocol_id.expect_type_id(ctx)) + ctx.resolve_type( + protocol_id.expect_type_id(ctx), + ) .name() .unwrap(), ); From d9d030d1e7d1d90bf02b1776f926dc0d9a0a20d3 Mon Sep 17 00:00:00 2001 From: Sebastian Imlay Date: Sat, 29 Aug 2020 16:57:13 -0700 Subject: [PATCH 04/10] First attempt to fix CI --- .../tests/libclang-3.9/objc_inheritance.rs | 76 +++++++++++++++++-- .../tests/libclang-4/objc_inheritance.rs | 66 +++++++++++++++- .../tests/libclang-5/objc_inheritance.rs | 66 +++++++++++++++- 3 files changed, 197 insertions(+), 11 deletions(-) diff --git a/tests/expectations/tests/libclang-3.9/objc_inheritance.rs b/tests/expectations/tests/libclang-3.9/objc_inheritance.rs index cd2b085dc3..982fc14cb4 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,78 @@ impl Bar { } } impl IFoo for Bar {} + +mpl From for Foo { + ++ fn from(child: Bar) -> Foo { + ++ Foo(child.0) + ++ } + ++} + +impl std::convert::TryFrom for Bar { + type Error = String; + 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(format!( + "This {} is not an cannot be downcasted to {}", + "Foo", "Bar" + )) + } + } +} impl IBar for Bar {} +impl From for Bar { + fn from(child: Baz) -> Bar { + Bar(child.0) + } +} + +impl std::convert::TryFrom for Baz { + type Error = String; + 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(format!( + "This {} is not an cannot be downcasted to {}", + "Bar", "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 = String; + 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(format!( + "This {} is not an cannot be downcasted to {}", + "Foo", "Baz" + )) + } + } +} 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; @@ -60,7 +128,5 @@ impl Baz { Self(unsafe { msg_send!(objc::class!(Baz), alloc) }) } } -impl IBar for Baz {} -impl IFoo for Baz {} impl IBaz for Baz {} pub trait IBaz: Sized + std::ops::Deref {} diff --git a/tests/expectations/tests/libclang-4/objc_inheritance.rs b/tests/expectations/tests/libclang-4/objc_inheritance.rs index cd2b085dc3..a84f6f371b 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,30 @@ 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 = String; + 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(format!( + "This {} is not an cannot be downcasted to {}", + "Foo", "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 +81,46 @@ 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 = String; + 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(format!( + "This {} is not an cannot be downcasted to {}", + "Bar", "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 = String; + 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(format!( + "This {} is not an cannot be downcasted to {}", + "Foo", "Baz" + )) + } + } +} impl IBaz for Baz {} pub trait IBaz: Sized + std::ops::Deref {} diff --git a/tests/expectations/tests/libclang-5/objc_inheritance.rs b/tests/expectations/tests/libclang-5/objc_inheritance.rs index cd2b085dc3..a84f6f371b 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,30 @@ 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 = String; + 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(format!( + "This {} is not an cannot be downcasted to {}", + "Foo", "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 +81,46 @@ 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 = String; + 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(format!( + "This {} is not an cannot be downcasted to {}", + "Bar", "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 = String; + 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(format!( + "This {} is not an cannot be downcasted to {}", + "Foo", "Baz" + )) + } + } +} impl IBaz for Baz {} pub trait IBaz: Sized + std::ops::Deref {} From 314cca5635cb751eb7ee2c6d590a8c3559dde6e9 Mon Sep 17 00:00:00 2001 From: Sebastian Imlay Date: Mon, 31 Aug 2020 02:13:39 -0700 Subject: [PATCH 05/10] Fix spacing issue --- .../tests/libclang-3.9/objc_inheritance.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/tests/expectations/tests/libclang-3.9/objc_inheritance.rs b/tests/expectations/tests/libclang-3.9/objc_inheritance.rs index 982fc14cb4..76b758ec50 100644 --- a/tests/expectations/tests/libclang-3.9/objc_inheritance.rs +++ b/tests/expectations/tests/libclang-3.9/objc_inheritance.rs @@ -44,16 +44,11 @@ impl Bar { } impl IFoo for Bar {} -mpl From for Foo { - -+ fn from(child: Bar) -> Foo { - -+ Foo(child.0) - -+ } - -+} - +impl From for Foo { + fn from(child: Bar) -> Foo { + Foo(child.0) + } +} impl std::convert::TryFrom for Bar { type Error = String; fn try_from(parent: Foo) -> Result { From 0054fab15f8ef64cbab7a86769c9e632322f24b3 Mon Sep 17 00:00:00 2001 From: Sebastian Imlay Date: Mon, 31 Aug 2020 13:51:42 -0700 Subject: [PATCH 06/10] Updates from PR comments --- src/codegen/mod.rs | 12 +++++----- .../tests/libclang-3.9/objc_inheritance.rs | 22 +++++-------------- .../tests/libclang-4/objc_inheritance.rs | 21 +++++------------- .../tests/libclang-5/objc_inheritance.rs | 19 +++++----------- .../tests/libclang-9/objc_inheritance.rs | 21 +++++------------- .../tests/objc_protocol_inheritance.rs | 7 ++---- 6 files changed, 30 insertions(+), 72 deletions(-) diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index dc0a44e354..5f2d37b0c8 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -49,7 +49,6 @@ use crate::{Entry, HashMap, HashSet}; use std; use std::borrow::Cow; use std::cell::Cell; -use std::collections::HashSet as CollectionHashSet; use std::collections::VecDeque; use std::fmt::Write; use std::iter; @@ -3922,8 +3921,7 @@ impl CodeGenerator for ObjCInterface { } }; result.push(struct_block); - let mut protocol_set: CollectionHashSet = - CollectionHashSet::new(); + 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( @@ -3967,8 +3965,7 @@ impl CodeGenerator for ObjCInterface { }; result.push(impl_trait); for protocol_id in parent.conforms_to.iter() { - if !protocol_set.contains(protocol_id) { - protocol_set.insert(*protocol_id); + if protocol_set.insert(*protocol_id) { let protocol_name = ctx.rust_ident( ctx.resolve_type( protocol_id.expect_type_id(ctx), @@ -3995,15 +3992,16 @@ impl CodeGenerator for ObjCInterface { }; 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 = String; + 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(format!("This {} is not an cannot be downcasted to {}", #parent_struct_name, #child_struct_name)) + Err(#error_msg) } } } diff --git a/tests/expectations/tests/libclang-3.9/objc_inheritance.rs b/tests/expectations/tests/libclang-3.9/objc_inheritance.rs index 76b758ec50..f2049a88b9 100644 --- a/tests/expectations/tests/libclang-3.9/objc_inheritance.rs +++ b/tests/expectations/tests/libclang-3.9/objc_inheritance.rs @@ -50,17 +50,14 @@ impl From for Foo { } } impl std::convert::TryFrom for Bar { - type Error = String; + 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(format!( - "This {} is not an cannot be downcasted to {}", - "Foo", "Bar" - )) + Err("This Foo cannot be downcasted to Bar") } } } @@ -70,19 +67,15 @@ impl From for Bar { Bar(child.0) } } - impl std::convert::TryFrom for Baz { - type Error = String; + 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(format!( - "This {} is not an cannot be downcasted to {}", - "Bar", "Baz" - )) + Err("This Bar cannot be downcasted to Baz") } } } @@ -93,17 +86,14 @@ impl From for Foo { } } impl std::convert::TryFrom for Baz { - type Error = String; + 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(format!( - "This {} is not an cannot be downcasted to {}", - "Foo", "Baz" - )) + Err("This Foo cannot be downcasted to Baz") } } } diff --git a/tests/expectations/tests/libclang-4/objc_inheritance.rs b/tests/expectations/tests/libclang-4/objc_inheritance.rs index a84f6f371b..5f07dbaab1 100644 --- a/tests/expectations/tests/libclang-4/objc_inheritance.rs +++ b/tests/expectations/tests/libclang-4/objc_inheritance.rs @@ -49,17 +49,14 @@ impl From for Foo { } } impl std::convert::TryFrom for Bar { - type Error = String; + 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(format!( - "This {} is not an cannot be downcasted to {}", - "Foo", "Bar" - )) + Err("This Foo cannot be downcasted to Bar") } } } @@ -87,17 +84,14 @@ impl From for Bar { } } impl std::convert::TryFrom for Baz { - type Error = String; + 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(format!( - "This {} is not an cannot be downcasted to {}", - "Bar", "Baz" - )) + Err("This Bar cannot be downcasted to Baz") } } } @@ -108,17 +102,14 @@ impl From for Foo { } } impl std::convert::TryFrom for Baz { - type Error = String; + 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(format!( - "This {} is not an cannot be downcasted to {}", - "Foo", "Baz" - )) + Err("This Foo cannot be downcasted to Baz") } } } diff --git a/tests/expectations/tests/libclang-5/objc_inheritance.rs b/tests/expectations/tests/libclang-5/objc_inheritance.rs index a84f6f371b..42c961e7cd 100644 --- a/tests/expectations/tests/libclang-5/objc_inheritance.rs +++ b/tests/expectations/tests/libclang-5/objc_inheritance.rs @@ -56,10 +56,7 @@ impl std::convert::TryFrom for Bar { if is_kind_of { Ok(Bar(parent.0)) } else { - Err(format!( - "This {} is not an cannot be downcasted to {}", - "Foo", "Bar" - )) + Err("This Foo cannot be downcasted to Bar") } } } @@ -87,17 +84,14 @@ impl From for Bar { } } impl std::convert::TryFrom for Baz { - type Error = String; + 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(format!( - "This {} is not an cannot be downcasted to {}", - "Bar", "Baz" - )) + Err("This Bar cannot be downcasted to Baz") } } } @@ -108,17 +102,14 @@ impl From for Foo { } } impl std::convert::TryFrom for Baz { - type Error = String; + 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(format!( - "This {} is not an cannot be downcasted to {}", - "Foo", "Baz" - )) + Err("This Foo cannot be downcasted to Baz") } } } diff --git a/tests/expectations/tests/libclang-9/objc_inheritance.rs b/tests/expectations/tests/libclang-9/objc_inheritance.rs index a84f6f371b..5f07dbaab1 100644 --- a/tests/expectations/tests/libclang-9/objc_inheritance.rs +++ b/tests/expectations/tests/libclang-9/objc_inheritance.rs @@ -49,17 +49,14 @@ impl From for Foo { } } impl std::convert::TryFrom for Bar { - type Error = String; + 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(format!( - "This {} is not an cannot be downcasted to {}", - "Foo", "Bar" - )) + Err("This Foo cannot be downcasted to Bar") } } } @@ -87,17 +84,14 @@ impl From for Bar { } } impl std::convert::TryFrom for Baz { - type Error = String; + 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(format!( - "This {} is not an cannot be downcasted to {}", - "Bar", "Baz" - )) + Err("This Bar cannot be downcasted to Baz") } } } @@ -108,17 +102,14 @@ impl From for Foo { } } impl std::convert::TryFrom for Baz { - type Error = String; + 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(format!( - "This {} is not an cannot be downcasted to {}", - "Foo", "Baz" - )) + Err("This Foo cannot be downcasted to Baz") } } } diff --git a/tests/expectations/tests/objc_protocol_inheritance.rs b/tests/expectations/tests/objc_protocol_inheritance.rs index 14570e1ee3..598273ba35 100644 --- a/tests/expectations/tests/objc_protocol_inheritance.rs +++ b/tests/expectations/tests/objc_protocol_inheritance.rs @@ -52,17 +52,14 @@ impl From for Foo { } } impl std::convert::TryFrom for Bar { - type Error = String; + 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(format!( - "This {} is not an cannot be downcasted to {}", - "Foo", "Bar" - )) + Err("This Foo cannot be downcasted to Bar") } } } From e4fb4a7d7cd2912bdbf2fcc0a9e210eceb226d9d Mon Sep 17 00:00:00 2001 From: Sebastian Imlay Date: Mon, 31 Aug 2020 14:04:26 -0700 Subject: [PATCH 07/10] Updated CHANGELOG.md --- CHANGELOG.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 From 6c5f592b3baed7d3033ddc6664ef55f3722832c6 Mon Sep 17 00:00:00 2001 From: Sebastian Imlay Date: Mon, 31 Aug 2020 15:31:54 -0700 Subject: [PATCH 08/10] Updates for CI --- src/codegen/mod.rs | 5 ++++- .../expectations/tests/libclang-3.9/objc_template.rs | 12 ++++++------ tests/expectations/tests/libclang-4/objc_template.rs | 12 ++++++------ .../tests/libclang-5/objc_inheritance.rs | 2 +- tests/expectations/tests/libclang-5/objc_template.rs | 12 ++++++------ 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 5f2d37b0c8..c08196090d 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -3992,7 +3992,10 @@ impl CodeGenerator for ObjCInterface { }; result.push(from_block); - let error_msg = format!("This {} cannot be downcasted to {}", parent_struct_name, child_struct_name); + 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; 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_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 42c961e7cd..5f07dbaab1 100644 --- a/tests/expectations/tests/libclang-5/objc_inheritance.rs +++ b/tests/expectations/tests/libclang-5/objc_inheritance.rs @@ -49,7 +49,7 @@ impl From for Foo { } } impl std::convert::TryFrom for Bar { - type Error = String; + type Error = &'static str; fn try_from(parent: Foo) -> Result { let is_kind_of: bool = unsafe { msg_send!(parent, isKindOfClass: class!(Bar)) }; 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) } } From 5d5c5a59d3bda5f06fbaeff96e4b4ed18f561090 Mon Sep 17 00:00:00 2001 From: Sebastian Imlay Date: Mon, 31 Aug 2020 18:23:24 -0700 Subject: [PATCH 09/10] Update to fix CI --- .../tests/libclang-3.9/objc_inheritance.rs | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/tests/expectations/tests/libclang-3.9/objc_inheritance.rs b/tests/expectations/tests/libclang-3.9/objc_inheritance.rs index f2049a88b9..59cfacc34c 100644 --- a/tests/expectations/tests/libclang-3.9/objc_inheritance.rs +++ b/tests/expectations/tests/libclang-3.9/objc_inheritance.rs @@ -43,7 +43,6 @@ impl Bar { } } impl IFoo for Bar {} - impl From for Foo { fn from(child: Bar) -> Foo { Foo(child.0) @@ -62,6 +61,22 @@ impl std::convert::TryFrom for Bar { } } impl IBar for Bar {} +pub trait IBar: Sized + std::ops::Deref {} +#[repr(transparent)] +#[derive(Clone)] +pub struct Baz(pub id); +impl std::ops::Deref for Baz { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for Baz {} +impl Baz { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(objc::class!(Baz), alloc) }) + } +} impl From for Bar { fn from(child: Baz) -> Bar { Bar(child.0) @@ -97,21 +112,5 @@ impl std::convert::TryFrom for Baz { } } } -pub trait IBar: Sized + std::ops::Deref {} -#[repr(transparent)] -#[derive(Clone)] -pub struct Baz(pub id); -impl std::ops::Deref for Baz { - type Target = objc::runtime::Object; - fn deref(&self) -> &Self::Target { - unsafe { &*self.0 } - } -} -unsafe impl objc::Message for Baz {} -impl Baz { - pub fn alloc() -> Self { - Self(unsafe { msg_send!(objc::class!(Baz), alloc) }) - } -} impl IBaz for Baz {} pub trait IBaz: Sized + std::ops::Deref {} From b88fc1ec11bbe07415d8229f0ab68e500bfb4267 Mon Sep 17 00:00:00 2001 From: Sebastian Imlay Date: Mon, 31 Aug 2020 20:20:53 -0700 Subject: [PATCH 10/10] Fix test for CI --- tests/expectations/tests/libclang-3.9/objc_inheritance.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/expectations/tests/libclang-3.9/objc_inheritance.rs b/tests/expectations/tests/libclang-3.9/objc_inheritance.rs index 59cfacc34c..5f07dbaab1 100644 --- a/tests/expectations/tests/libclang-3.9/objc_inheritance.rs +++ b/tests/expectations/tests/libclang-3.9/objc_inheritance.rs @@ -77,6 +77,7 @@ impl Baz { Self(unsafe { msg_send!(objc::class!(Baz), alloc) }) } } +impl IBar for Baz {} impl From for Bar { fn from(child: Baz) -> Bar { Bar(child.0)