-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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
Ranked overload resolution #1256
Comments
This is needed so much! The case when there's an exact match with other convertible types should be fixed very soon. I've this problem
|
Hi, I just encountered this issue and was wondering what the plan is for incorporating a fix? |
We have to define the order of resolution for every possible conversion. |
Just bumped into this issue, with Is this issue still unresolved? |
I'll add it to 0.6.0. |
What is the current thinking around this issue ? |
I think this could be done in a non-breaking way (because after this change, I think more code compiles than before) - can someone please check? |
My proposal for a simple implementation is: If there is a unique function where the argument types are equal (including storage location), use this one. Otherwise do overload resolution as we currently do it. |
I have an idea. What if, instead of adding implicit rules on overload resolution we added a way to clarify the type of an argument? My proposal would be to introduce a special conversion operator, let's call it function foo(uint256 x) {}
function foo(uint32 x) {}
function foo(address x) {}
function foo(string memory x) {}
function foo(string storage x) {}
function test() {
uint32 x;
foo(exact(x)); // calls foo(uint32)
foo(exact(uint(x))); // calls foo(uint256)
foo(x); // ERROR: ambiguous
address a;
foo(a); // calls foo(address) directly
foo(payable(a)); // calls foo(address) through implicit conversion
foo(exact(payable(a))); // ERROR: foo(payable) does not exist; implicit conversion to address not allowed
string storage s;
foo(s); // ERROR: ambiguous
foo(exact(s)); // calls foo(string storage)
// If we introduce the copyof operator:
foo(copyof s); // ERROR: ambiguous
foo(exact(copyof s)); // calls foo(string memory)
foo(exact(memory(s)); // calls foo(string memory) - possible alternative if we don't
} The operator would affect the expression rather than "stick" to the value. When you copy/assign a value, it does not preserve the "exactness". I.e. after Some alternative syntax ideas: foo(x, exact payable(a), y);
foo(x, exact<payable>(a), y);
foo(x, exact|payable(a)|, y);
foo(x, |payable(a)|, y);
foo(x, only(payable(a)), y);
foo(x, explicit(payable(a)), y);
foo(x, noconv(payable(a)), y);
foo(x, asIs(payable(a)), y);
// We could also allow making variables permanently exact:
address payable exact constant b;
foo(x, b, y); |
I would actually say we can relax this even more radically.
we can just disregard |
So in general, if I have two overload choices |
Chiming in to cast my support for this. As I explained here, I find it a bit confusing that the compiler cannot disambiguate between two functions Overloading functions with different integer width is super common when writing tests with Foundry. |
Just wanted to note that when solving this we should remember that integers are not the only case here. For example #13879 brought up a related case with function pointers. |
Currently, functions are selected as overload candidates if all arguments can be implicitly converted to the expected types. If there is not exactly one candidate, resolution fails.
This makes it impossible to call different functions depending on whether one argument is a storage or a memory array, because storage arrays can be implicitly converted to both storage and memory arrays.
We should add a ranking of candidates depending on which conversions have to take place.
For this, a conversion from e.g. storage to memory should be "worse" than a widening of an integer type which in turn is worse than no conversion at all.
The text was updated successfully, but these errors were encountered: