-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#[derive] Debug, PartialEq, Hash, etc. for any function pointers, regardless of type signature #54508
Comments
what's your local rustc meta info? |
This is certainly weird - It seems to be fixed and even if I try older compiler versions, it doesn't appear. But I did get errors that I'm closing this for now, since it doesn't seem to be an issue, but I'll reopen this once I get a verifiable example of the problem working. |
Yeah, the example was picked poorly. The issue only appears when the callback carries a Not working: https://play.rust-lang.org/?gist=e805684b57c9992a9b1da66510c8c336&version=stable&mode=debug&edition=2015 All I changed was this: #[derive(Debug, Clone, PartialEq, Hash, Eq)]
pub struct Callback<T: Layout>(pub fn(WindowInfo<T>, usize, usize) -> Dom<T>); to this: #[derive(Debug, Clone, PartialEq, Hash, Eq)]
pub struct Callback<T: Layout>(pub fn(&mut WindowInfo<T>, usize, usize) -> Dom<T>); Notice the |
It seems that rust thinks that I'm still not sure where the actual bug is coming from. |
for<'r> fn(&'r mut WindowInfo<T>, usize, usize) -> Dom<T>
fn(WindowInfo<T>, usize, usize) -> Dom<T>
|
So my question then is... why isn't it implemented? Or is this the actual bug? Even after rust-lang/rfcs#387 is merged (four years ago?), this still doesn't work, so maybe it's just an issue in the standard library? But you can't impl derive for all possible function pointers: impl<Ret, A, B, C> Eq for fn(A, B, C) -> Ret
impl<Ret, A, B, C> Eq for fn<'a>(&'a A, B, C) -> Ret
impl<Ret, A, B, C> Eq for fn<'a>(&mut 'a A, B, C) -> Ret
impl<Ret, A, B, C> Eq for fn<'a, 'b>(&'a A, &'b B, C) -> Ret
impl<Ret, A, B, C> Eq for fn<'a, 'b>(&mut 'a A, &'b B, C) -> Ret
impl<Ret, A, B, C> Eq for fn<'a, 'b>(&mut 'a A, &mut 'b B, C) -> Ret
impl<Ret, A, B, C> Eq for fn<'a, 'b>(&'a A, &mut 'b B, C) -> Ret
impl<Ret, A, B, C> Eq for fn<'a, 'b>(A, &mut 'b B, C) -> Ret
impl<Ret, A, B, C> Eq for fn<'a, 'b>(A, & 'b B, C) -> Ret
impl<Ret, A, B, C> Eq for fn<'a, 'b, 'c>(&'a A, &'b B, &'c C) -> Ret
impl<Ret, A, B, C> Eq for fn<'a, 'b, 'c>(&mut 'a A, &'b B, &'c C) -> Ret
impl<Ret, A, B, C> Eq for fn<'a, 'b, 'c>(&mut 'a A, &mut 'b B, &mut 'c C) -> Ret
impl<Ret, A, B, C> Eq for fn<'a, 'b, 'c>(&mut 'a A, &'b B, &mut 'c C) -> Ret
impl<Ret, A, B, C> Eq for fn<'a, 'b, 'c>(&'a A, &'b B, &mut 'c C) -> Ret
// ... and so on. This is insane. You can't prepare for any function signature. What I don't get is that it's a function pointer - regardless of the type system, a function pointer is just a number, like a impl PartialEq for fn<*>(*) -> * {
fn eq(&self: other: &Self) -> bool { self as usize == other as usize }
} ... where the * stands for "anything", i.e. any number or arguments or lifetime of types - So maybe, I thought, this should be a compiler built-in thing, that the compiler knows about function pointers and just treats them as a // instead of:
impl<A> Eq for (A) where A: Eq + ?Sized
impl<A, B> Eq for (A, B) where A: Eq, B: Eq + ?Sized
impl<A, B, C> Eq for (A, B, C) where A: Eq, B: Eq, C: Eq + ?Sized
impl<A, B, C, D> Eq for (A, B, C, D) where A: Eq, B: Eq, C: Eq, D: Eq + ?Sized
impl<A, B, C, D, E> Eq for (A, B, C, D, E) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq + ?Sized
impl<A, B, C, D, E, F> Eq for (A, B, C, D, E, F) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq + ?Sized
impl<A, B, C, D, E, F, G> Eq for (A, B, C, D, E, F, G) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq + ?Sized
impl<A, B, C, D, E, F, G, H> Eq for (A, B, C, D, E, F, G, H) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq + ?Sized
impl<A, B, C, D, E, F, G, H, I> Eq for (A, B, C, D, E, F, G, H, I) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq + ?Sized
impl<A, B, C, D, E, F, G, H, I, J> Eq for (A, B, C, D, E, F, G, H, I, J) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq, J: Eq + ?Sized
impl<A, B, C, D, E, F, G, H, I, J, K> Eq for (A, B, C, D, E, F, G, H, I, J, K) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq, F: Eq, G: Eq, H: Eq, I: Eq, J: Eq, K: Eq + ?Sized
// just:
impl<*> Eq for (*) where *: Eq + ?Sized |
Pretty sure this is related to/the same as #46989 |
Has anything like this been merged? I'd like to put an arbitrary function pointer inside of a use std::collections::HashSet;
fn callback1(arg1: &str, arg2: &Vec<String>) {}
fn main(){
let set: HashSet<fn(&str, &Vec<String>)> = HashSet::new();
HashSet::insert(callback1);
set.remove(callback1);
} |
No, but I think this will be fixed by #108080. See #108080 (comment) |
Closing this as it is fixed now |
Suppose you have a situation like this:
https://play.rust-lang.org/?gist=d1bd43980abfb37197a8aaf84ed7b529&version=stable&mode=debug&edition=2015
You can implement this manually by writing something like this:
... 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:... because then #[derive] doesn't work on the
Something
struct! This means you have to copy-paste all over again:.. 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 theSomething
struct, don't forget to update thehash()
andfmt()
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.
The text was updated successfully, but these errors were encountered: