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

Fix issue 19829 - __traits(isSame) returns true for some non-local de… #9710

Merged
merged 1 commit into from
May 30, 2019

Conversation

Biotronic
Copy link
Contributor

…legate lambdas even when they are different

As shown in the issue,

pragma(msg, __traits(isSame, i => x[i], a => a));

prints true. This is because the presence of x is not indicated in any way in the lambda serialization. This PR fixes that by making lambdas incomparable when they use identifiers that are not in the parameter list.

@dlang-bot
Copy link
Contributor

dlang-bot commented Apr 26, 2019

Thanks for your pull request and interest in making D better, @Biotronic! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the annotated coverage diff directly on GitHub with CodeCov's browser extension
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

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

Auto-close Bugzilla Severity Description
19829 major __traits(isSame) returns true for some non-local delegate lambdas even when they are different

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub fetch digger
dub run digger -- build "master + dmd#9710"

@aG0aep6G
Copy link
Contributor

This is because the presence of x is not indicated in any way in the lambda serialization.

So i => x[i] was being treated like i => [i], right? But that means i => [i] is considered the "same" as a => a. Indeed:

pragma(msg, __traits(isSame, i => [i], a => a)); // Prints "true".

That's another bug, isn't it?

@Biotronic
Copy link
Contributor Author

You're right. In fact, there's a whole bunch of different things that could happen inside the lambda that should mark it as incomparable. Working on that now.

@RazvanN7
Copy link
Contributor

Maybe a better fix would be to use the mangled name of the variable so that the comparison is rightly done.

@Biotronic
Copy link
Contributor Author

That would mean i => i wouldn't compare equal to a => a, if I'm understanding you correctly.

@RazvanN7
Copy link
Contributor

RazvanN7 commented Apr 27, 2019

That would mean i => i wouldn't compare equal to a => a, if I'm understanding you correctly.

No. I forgot that lambda comparison cannot be done for lambdas that contain non-parameter variables and I was suggesting that the functionality is extended so that lambda comparison works properly with local/global variables by using in the serialization the mangled name of the variable. I just figured that that would need a bit more work because it would require additional semantic passes to be performed.

For now, the fix should be to add a serialization mechanism for arrays.

@thewilsonator
Copy link
Contributor

Please retarget this to stable. Should this be merged soon and then the other issues fixed in another PR?

@RazvanN7
Copy link
Contributor

Yes.

@thewilsonator
Copy link
Contributor

Alright this is good to go as soon as it targets stable.

@Biotronic
Copy link
Contributor Author

Why stable? If I'm reading CONTRIBUTING.md correctly, that's for regressions only.

Also, the version you approved does not, as aG0aep6G pointed out, correctly handle __traits(isSame, i => [i], a => a) and various other possibilities.

Supporting global variables and the like would be an enhancement, and so should be handled elsewhere.

@Biotronic
Copy link
Contributor Author

Bah. Or maybe not, since the tests in testlambdacomp assume that many things work that aren't implemented.

@thewilsonator
Copy link
Contributor

Why stable? If I'm reading CONTRIBUTING.md correctly, that's for regressions only.

Its also for serious bug fixes and for bug fixes that will trivially result in no regressions.

@thewilsonator
Copy link
Contributor

compilable/testlambdacomp.d(108): Error: static assert:  `__traits(isSame, (a) => a + r1.a, (b) => b + r2.a)` is false

override void visit(TypeExp) { buf.reset(); }
override void visit(TypeidExp) { buf.reset(); }
override void visit(VoidInitExp) { buf.reset(); }
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't simply overwriting the Expression node account for all those cases?

override void visit(Expression) { buf.reset(); }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems reasonable, and was the first thing I tried, but I can't seem to get it to work.

@Biotronic
Copy link
Contributor Author

It's actually worse than I thought. Try this:

enum i = 2;
static assert(!__traits(isSame, a => i, get!())); // Fails.

template get() {
    enum i = "foo";
    alias get = b => i;
}

The identifier lookup in lambdacomp is very simplistic, and will match identifiers in the local scope when it shouldn't.

@Biotronic Biotronic force-pushed the Issue-19829 branch 2 times, most recently from 3554fc9 to a0ecc6b Compare May 1, 2019 04:59
@Biotronic Biotronic changed the base branch from master to stable May 1, 2019 14:48
@Biotronic Biotronic changed the base branch from stable to master May 1, 2019 14:48
@Biotronic Biotronic changed the base branch from master to stable May 1, 2019 14:55
@Biotronic Biotronic changed the base branch from stable to master May 1, 2019 15:35
@RazvanN7
Copy link
Contributor

RazvanN7 commented May 2, 2019

The lambda comparison works only for things that can be known right after parsing and with minimal semantic information. The examples that you have shown all require that semantic3 is ran before fetching that kind of information.

@thewilsonator
Copy link
Contributor

No point waiting any longer for this.

@dlang-bot dlang-bot merged commit 3a388fb into dlang:master May 30, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants