Function comparing 2 variables of any type

my computer is not at hand,but I think assert_eq! may fit.

1 Like

Hi! Thank, you. It's good as starting point for me. But solution should not only compare types, but values of variables in the case type is the same.

Obviously that does not work:

fn eq<A: PartialEq + 'static, B: PartialEq + 'static>(a: A, b: B) -> bool {
    if std::any::TypeId::of::<A>() != std::any::TypeId::of::<B>() {
        return false;
    } else {
        return a == b;
    }
}

Is it possible to solve the problem without a macros?

^-- That is the original problem statement, which @2e71828 's solution solves.

3 Likes

Not sure I understand how transmute can help. Probably I phrased the problem poorly.

Why not just returning false in the case of different types? Or your idea that the transmute will do nothing for the same class, but will calm down the compiler? Is such solution okay?

Did you mean that?

fn eq<A: PartialEq + 'static, B: PartialEq + 'static>(a: A, b: B) -> bool {
    if std::any::TypeId::of::<A>() != std::any::TypeId::of::<B>() {
        return false;
    } else {
        unsafe {
            return std::mem::transmute::<A, B>(a) == b;
        }
    }
}

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
   --> src/main.rs:163:14
    |
163 |       return std::mem::transmute::< A, B >( a ) == b;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: source type: `A` (this type does not have a fixed size)
    = note: target type: `B` (this type does not have a fixed size)

You don't need any unsafe here.

use std::any::Any;
use std::cmp::PartialEq;

fn cmp(a: impl PartialEq + 'static, b: impl PartialEq + 'static) -> bool {
    if let Some(b_cast) = (&b as &dyn Any).downcast_ref() {
        &a == b_cast
    } else {
        false
    }
}
13 Likes

Ignore my attempted solution. I have no idea how to force a size_of(A) == size_of(B) requirement that std::mem::transmute requires.

Go with @Hyeonu 's solution.

1 Like

That's what I have been looking for. Thank you Hyeonu :slight_smile:

Hyeonu what do you recommend to read? Is it possible to implement it without dynamic typing, so that implementation was at compile-time?

Thank you for hints.

There's no dynamic dispatch in example above, as you can check on playground. If you select "Show Assembly", you'll see that cmp is compiled to the following:

playground::cmp:
	cmpl	%edi, %esi
	sete	%al
	retq

playground::cmp:
	xorl	%eax, %eax
	retq

(not sure how they are really selected, however - looks like the ASM output is missing something).
You can see that there are two versions: one checks the equality of arguments, another immediately returns false (xor X, X is a simple way to set X to 0); everything using dyn Any is entirely optimized out.

5 Likes

Amazing! Thank you!

It seems such implementation has very limited application because of static restriction. Is it possible to remove static restriction?

I am getting:

error[E0759]: `other` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> src/main.rs:128:29
    |
117 |   fn eq( &self, other : &Logic< RightRef, RighCopy > ) -> bool
    |                         ---------------------------- this data with an anonymous lifetime `'_`...
...
128 |             Logic::ValNode( e2 ) => return identical_tolerant( &e1, &e2 ),
    |                             ^^             ------------------ ...and is required to live as long as `'static` here
    |                             |
    |                             ...is captured here...

Without further context, no you can't.

Ah.. Does not it make using Any impractical? Must be another solution exist.

If someone has in mind less restricted solution, please share. I opened a new question.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.