Description
Suppose you have a situation like this:
trait MyTrait { }
// This works:
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
struct WorkingFunctionPointer<T: MyTrait>(fn(T));
// This doesn't work:
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
struct NotWorkingFunctionPointer<T: MyTrait>(fn(&T));
You can implement this manually by writing something like this:
// #[derive(Debug, Clone, PartialEq, Hash, Eq)] for NotWorkingFunctionPointer<T>
impl<T: Layout> fmt::Debug for NotWorkingFunctionPointer<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "NotWorkingFunctionPointer(0x{:x})", self.0 as usize)
}
}
impl<T: Layout> Clone for NotWorkingFunctionPointer<T> {
fn clone(&self) -> Self {
NotWorkingFunctionPointer(self.0.clone())
}
}
impl<T: Layout> Hash for NotWorkingFunctionPointer<T> {
fn hash<H>(&self, state: &mut H) where H: Hasher {
state.write_usize(self.0 as usize);
}
}
impl<T: Layout> PartialEq for NotWorkingFunctionPointer<T> {
fn eq(&self, rhs: &Self) -> bool {
self.0 as usize == rhs.0 as usize
}
}
impl<T: Layout> Eq for NotWorkingFunctionPointer<T> { }
impl<T: Layout> Copy for NotWorkingFunctionPointer<T> { }
... but this is tedious to do and leads to a lot of boilerplaite code. Even worse, this is especially bad if you have a FunctionPointer<T>
used in a struct like this:
// #[derive] won't work here, same error!
struct Something<T: MyTrait> {
ptr: NotWorkingFunctionPointer<T>,
// other fields for demonstration
blah: Blah,
foo: Foo,
baz: Baz,
}
... because then #[derive] doesn't work on the Something
struct! This means you have to copy-paste all over again:
// A manual #[derive(Debug, Clone, PartialEq, Hash, Eq)] for Something<T>
impl<T: Layout> fmt::Debug for Something<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Something { ptr: {:?}, blah: {:?}, foo: {:?}, baz: {:?} }", self.ptr, self.blah, self.foo, self.baz)
}
}
impl<T: MyTrait> Clone for Something<T> {
fn clone(&self) -> Self {
Something {
ptr: self.ptr.clone(),
blah: self.blah.clone(),
foo: self.foo.clone(),
baz: self.baz.clone(),
}
}
}
impl<T: MyTrait> Clone for Something<T> {
fn clone(&self) -> Self {
Something {
ptr: self.ptr.clone(),
blah: self.blah.clone(),
foo: self.foo.clone(),
baz: self.baz.clone(),
}
}
}
impl<T: Layout> Hash for Something<T> {
fn hash<H>(&self, state: &mut H) where H: Hasher {
state.hash(self.ptr);
state.hash(self.foo);
state.hash(self.bar);
state.hash(self.baz);
}
}
impl<T: Layout> PartialEq for Something<T> {
fn eq(&self, rhs: &Self) -> bool {
self.ptr == rhs.ptr &&
self.foo == rhs.foo &&
self.bar == rhs.bar &&
self.baz == rhs.baz &&
}
}
impl<T: Layout> Eq for Something<T> { }
impl<T: Layout> Copy for Something<T> { }
.. and over and over and over again, for each struct that you wrap / use Something
in. Nevermind that this is error-prone if you add a field to the Something
struct, don't forget to update the hash()
and fmt()
functions! This leads to a whole bunch of code that I need to copy-paste because derive doesn't work.
The real-world code where I encountered this problem is:
https://github.com/maps4print/azul/blob/4f2ba2e6eebdd0718d1adb15aac34c643f0f94ca/src/dom.rs#L159-L228
https://github.com/maps4print/azul/blob/4f2ba2e6eebdd0718d1adb15aac34c643f0f94ca/src/dom.rs#L358-L394
https://github.com/maps4print/azul/blob/4f2ba2e6eebdd0718d1adb15aac34c643f0f94ca/src/dom.rs#L413-L452
It's just stupid, copy-pasted code and if possible, I'd like to get rid of it with derive, but right now I sadly can't. My manual code is just a workaround for now, and I'd like this to be properly fixed somehow. Thanks in advance for any help.