Okay, so I came from C and this part really put me off. Why? Because I like saying what I mean, and meaning what I say. Nothing hidden, nothing implicit. And C, as opposed to C++, does not allow you to say something you don't mean.
Here is one C++ example, without looking for the signature of f(), there's no way to tell the answer. So essentially two pieces of identical code with identical input values and no external side effects can still give you different output. Ah C++, the garbage that you are.
int x = 5;
f(x);
// WHAT IS THE VALUE OF X HERE?
int x = 5;
f(x);
// WHAT IS THE VALUE OF X HERE?
So why is Rust any better in this regard? Because at the end of the day, Rust deals with actual concrete types and values, the only thing references are good for is being references: they sometimes save you some copying and let you refer to stuff and that's pretty much it. So the "ref1 == ref2" operation is a deep equality check and not a "does ref1 point to the same object as ref2" check. Because sometimes objects in different places in memory can be semantically equal. So it's okay for obj1 to mean obj1, &obj1 to mean obj1, &&obj1 to mean obj1, etc...
If you need raw pointers like you need in C, because you know the objects you want to compare are singletons, then you can always cast using
&obj as *const Obj
or
&mut obj as *mut Obj
But that's an escape hatch.
BTW, this auto-dereferencing you're experiencing is part of the Deref trait if you ever want to overload it. But that's, in my own opinion, an escape hatch as well.
All in all, unless you're doing very specific things, try to write your code in high-level semantics (meaning using these deep-equality rather than pointer-equality semantics), and then benchmark and find out which parts are hurting your performance. Rust allows you to do that and still get between very-reasonable-and-very-good speed.