-
-
Notifications
You must be signed in to change notification settings - Fork 610
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
Fix duplicate function detection for overloads introduced by aliases #12053
Conversation
c537f23 to
34d99fb
Compare
34d99fb to
b9e834e
Compare
|
Thanks for your pull request and interest in making D better, @MoonlightSentinel! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. Bugzilla references
Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub run digger -- build "stable + dmd#12053" |
| @@ -53,7 +47,7 @@ void f4() {} | |||
| void f4() {} // conflict | |||
|
|
|||
| void f5() @safe {} | |||
| void f5() @system {} // conflict | |||
| void f5() @system {} // no conflict because of attribute based overloading in in extern(D) | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, extern(D) preserves the mangling, but does overload resolution work well, or the user has to resort to hackery (e.g. externDFunc to traits)? If the answer is no, I think it's not a bad idea to deprecate such form of likely accidental overloading.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using __traits(getOverloads, ...) should also work IIRC.
But thats out of scope for this PR.
EDIT: It does work e.g. for opApply IIRC
|
An alternative fix would be to disallow inserting an overload in an overload list via alias this if the inserted function might conflict with any of the other overloads. Inserting a conflicting overload can never be useful. |
da8b9ae to
15fe4b7
Compare
|
Switchted to comparing the Some examples:
EDIT: Will squash & adapt the commit message once it is ready. |
|
@RazvanN7 You can still call the function using extern (C) int puts(scope const char*) @trusted @nogc;
void func() @safe { puts("@safe"); }
void func() @nogc { puts("@nogc"); }
void main() @nogc
{
__traits(getOverloads, M, "func")[1](); // Writes "@nogc"
}But I can also defer those changes into a latter PR and retain the current behaviour for now. |
|
With this behavior change, how does it affect the Spec? |
|
The spec doesn't mention conflicting functions IIRC. That's why the proposed implementation checks only for functions that cause issues in the backend (function merging for dmd/errors for ldc/gdc). |
The previous implementation compared small parts of the function mangling to detect duplicate functions. This approach had several flaws manifesting in the referenced issue as well as other false positives for (static) members, `alias`ing into different scopes, ... . Issue 21505 was caused by the assumption that all functions visited by `overloadApply` have the same name. This doesn't hold for overloads introduced by an `alias`. A reliable mangling-based implementation would need to compare most of the mangled name while also omitting severel aspects e.g. the return type to detect `int foo()` and `void foo()`. Hence the current implementation was replaced by actually comparing the `FuncDeclaration`s because it allows for more fine grained checks (and also should save some memory allocations).
15fe4b7 to
487e320
Compare
|
Rebased & squashed the commits |
|
I don't know why, but this change introduced a lot of errors in the form of |
@safe:
struct I {int* x;}
pure I gcd(I, I) {return I();}
auto foo(I func) {
if (R n = func)
R r = n.foo!()(n); // Error: address of variable n assigned to r with longer lifetime`
}
struct R {
@safe:
I d;
this(I) {}
bool opCast() {return true;}
R foo()(R) out {check();} do {
gcd(d, d);
return this;
}
bool check() {return true;}
}When compiled with |
|
The DIP1000 implementation is very brittle, so I guess this error is probably depending on the order of semantic analysis. |
Added the intial report as a bugzilla reference