Skip to content
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

UFCS can enable some forms of hijacking #17819

Open
dlangBugzillaToGithub opened this issue Oct 5, 2017 · 4 comments
Open

UFCS can enable some forms of hijacking #17819

dlangBugzillaToGithub opened this issue Oct 5, 2017 · 4 comments

Comments

@dlangBugzillaToGithub
Copy link

Walter Bright (@WalterBright) reported this on 2017-10-05T19:42:19Z

Transferred from https://issues.dlang.org/show_bug.cgi?id=17879

CC List

Description

From Timon Gehr:

struct S{
    // string foo(){ return "hijacked!"; } // uncomment to hijack
}

string foo(S s){ return "not hijacked!"; }

void main(){
    S s;
    import std.stdio;
    writeln(s.foo());
}
@dlangBugzillaToGithub
Copy link
Author

bugzilla (@WalterBright) commented on 2017-10-05T19:42:56Z

More discussion:

  https://github.com/tgehr/d-compiler/pull/1#discussion-diff-89697186L85

@dlangBugzillaToGithub
Copy link
Author

issues.dlang (@jmdavis) commented on 2017-10-05T21:58:15Z

How is that hijacking? When you use UFCS, you're saying that it should call the member function with that name, and if there is no member function, then it tries to call a matching free function. Anything else would make it impossible to use a member function and a free function for the same functionality, and if you reversed it so that it used UFCS instead, that would make it so that you couldn't call the member function.

It was my understanding that UFCS was purposefully designed this way, and I don't see how doing anything else makes sense. If you want to guarantee that you're calling a free function rather than a member function, then just don't use UFCS.

@dlangBugzillaToGithub
Copy link
Author

bugzilla (@WalterBright) commented on 2017-10-05T23:10:43Z

I listed it as an enhancement, not a bug, for the reasons you describe. The issue has come up before, it will again, and a bugzilla entry can serve as a focal point for it so discussions on it won't keep restarting from scratch.

@dlangBugzillaToGithub
Copy link
Author

schveiguy (@schveiguy) commented on 2017-10-06T13:13:42Z

According to the PR discussion, the issue was more like this:

mod1.d:
struct S {
    // private string foo(){ return "hijacked"; }
}

main.d:
import mod1;

string foo(S s) { return "not hijacked"; }

void main() {
   S s;
   import std.stdio;
   writeln(s.foo());
}

In other words, the *private* symbol was hijacking UFCS. S should be able to build whatever it wants privately without interfering with UFCS.

When I try to build this now, it doesn't work anyway. I get both a deprecation warning and an error. I can't figure out why the original code that the PR was fixing actually worked before the PR.

I agree with Jonathan that UFCS just doesn't take precedent over the member, and can't be considered a hijacking. If we "fixed" this, for instance, any code that used output ranges might break.

However, allowing UFCS to provide unrelated added methods that the type has the same name for, should work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant