Permit overloaded methods for user-defined value types

I started dabbling with user-defined value types, and there’s one issue that I keep bumping into.

I want to implement an eq method in my UD60x18 type. I started doing it like this:

pragma solidity >=0.8.9;

type UD60x18 is uint256;
using { eq } for UD60x18 global;

function eq(UD60x18 x, UD60x18 y) pure returns (bool) {
    return UD60x18.unwrap(x) == UD60x18.unwrap(y);
}

So far so good. But I also want to overload the eq method like this:

function eq(UD60x18 x, uint256 y) pure returns (bool) {
    return UD60x18.unwrap(x) == y;
}

Adding the code above results into a compiler error:

Identifier not found or not unique.

I want to overload the eq method like this because in my implementation contracts there are some scenarios where I need to compare two UD60x18s and other scenarios where I need to compare a UD60x18 and uint256. Being able to overload this would allow me to lower the churn by calling UD60x18.wrap and UD60x18.unwrap fewer times.

A similar rationale applies to most other methods I want to implement, like and, leftShift, rightShift etc.

What do you think? Here’s a GitHub Gist with the work I’ve done so far.

1 Like

The current plan was to not allow overloads here on purpose. Would you like to hop on our design call tomorrow to discuss this?
This is maybe not too related to overloading, but especially the comparison with uint256 could be confusing as it is implemented above. Requiring an explicit conversion to UD60x18 (that then either applies the shift or not, depending on the name of the conversion function) could resolve the confusion.

Sorry, I’ve just seen this, and today I’m fully booked out.

Oh, I see what you mean. Indeed the same variable y is used as a UD60x18 in the one case and as a uint256 in the other.

Fair enough. I’ll stick with one of the overloads above and just use wrap or unwrap before calling it.