Skip to content

Fix for issue 11947 - typecons.Proxy incorrectly handles variadic member templates #1914

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

Closed
wants to merge 2 commits into from

Conversation

radcapricorn
Copy link
Contributor

@yebblies
Copy link
Member

yebblies commented Feb 9, 2014

In the future, please copy-paste the title of the bug you're fixing into the commit/pull request description. This way nobody has to look up/memorize the bug numbers. It's also helpful to put a link to the bug report in the pull request description. I've added it to this one.

@radcapricorn
Copy link
Contributor Author

Thanks for the heads up, I'll be more thorough from now on.

auto ref opDispatch(this X, Args...)(auto ref Args args)
{
static if (Args.length)
// T is empty, deduction is in effect
Copy link
Member

Choose a reason for hiding this comment

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

Why this assumption? IFTI doesn't have to be used for all template parameters.

@radcapricorn
Copy link
Contributor Author

I am still acclimatizing to github. Shall I close this request and make a new one, or can I just commit new changes to further the review?

@JakobOvrum
Copy link
Member

I am still acclimatizing to github. Shall I close this request and make a new one, or can I just commit new changes to further the review?

Either amend the existing commit with new changes (then force push), or add new commits that should be squashed before pulling, once review is done. Alternatives to amending include pushing a remade branch entirely with the same name, and using interactive rebase with the edit command.

@radcapricorn
Copy link
Contributor Author

Got it, thanks. I'm discovering even more quirks with this issue, i.e. forwarding when both template and non-template functions/opCall are present, or when making a proxy for a function.

auto ref opCall(this X, Args...)(auto ref Args args) { return a(args); }
auto ref opCall(this X, Args...)(auto ref Args args)
{
static if(is(typeof(a.opCall(args))))
Copy link
Member

Choose a reason for hiding this comment

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

Forgot to mention: why this change? It seems like a no-op. If it's due to a bug, there should be a comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've commented on the opCall in the same report in bugzilla. Or you mean why the static if? Then a comment is due indeed. It's to allow proxying e.g. a function. The opCall will become even more elaborate to accomodate for all possibilities.

Do you recommend splitting this into separate issues? I.e. one for opDisptatch, one for opCall?

Copy link
Member

Choose a reason for hiding this comment

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

I mean the existing code, i.e. a(args) should be correct. I notice that it doesn't work for pointers to structs with opCall, which seems to be the underlying problem as presented in the bug report. Automatic dereferencing of pointers is only a thing for the dot/member-access operator, which precludes opCall and all other operator overloads (which makes sense - stuff like unary *, indexing and binary + etc. would conflict with those of the pointer type).

If you want to proxy a struct by reference, make get return by ref.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, so you mean that attempting to opCall() a pointer is an entirely separate problem (bug?). Ok, makes sense.

But that still won't cancel out the need for various static ifs in the upcoming fix, to accomodate for: templated opCall() (exactly the same problem as with opDispatch, manifests when partially specifying template arguments; the "easily broken" problem you mentioned), proxying a function, mixed templated/non-templated opCall declarations. What a mess :)

@radcapricorn
Copy link
Contributor Author

Okay, another round :)

@radcapricorn
Copy link
Contributor Author

Umm... You're commenting on an outdated commit. Is this intentional? Although the comment about mismatch in template/real argument numbers does seem interesting. I haven't accounted for that case. Oh well, more work, I guess.

@monarchdodra
Copy link
Collaborator

Umm... You're commenting on an outdated commit. Is this intentional?

Seems that way... It wasn't intentional. Don't know how I managed that.

Although the comment about mismatch in template/real argument numbers does seem interesting. I haven't accounted for that case. Oh well, more work, I guess.

Yeah, I was looking at your commit "as a whole", and I think your MergeArgs thing is still subject to the issue.

@radcapricorn
Copy link
Contributor Author

Not MegreArgs per se. An additional check is needed to see if a.name!T(args) compiles: this way it will also respect functions that expect explicit template args, i.e. func(T)(int a). Oh, this issue is just frustrating :)

// variadic template method
static assert(is(typeof(impostor.variadic())));
static assert(is(typeof(impostor.variadic("hello"))));
static assert(is(typeof(impostor.variadic!int(42, "hello"))));
Copy link
Member

Choose a reason for hiding this comment

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

This test is wrong! Replacing variadic with p.variadic causes it to fail.

I suggest that you prefix each test with a variant which bypasses Proxy and addresses RealThing directly, to avoid false positives.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure I understand what you mean.

Copy link
Member

Choose a reason for hiding this comment

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

This line will not work:

impostor.p.variadic!int(42, "hello");

Note that by using .p, we address RealThing directly, bypassing Proxy.
But your test asserts that this line will work:

impostor.variadic!int(42, "hello");

Proxy's goal is to forward valid uses of an object to the alias it is proxying. However, the line doesn't work if you remove the Proxy and address the RealThing directly, so it is not a valid way to use RealThing.

Thus, there is no obligation for Proxy to work in this case. Adding the line to the test implies that you assert that any future implementation of Proxy needs to satisfy this false requirement. I also suspect that this false requirement is partially responsible for the size and complexity of your patch.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, I see now. Yes, that is indeed a false assumption.
However, the size and complexity of the patch stems from the fact that it tries to deal with several possible scenarios at once:

  • template members
  • variadic template members
  • templates overloading non-template members

Perhaps it's indeed feasible to break this up in a series of patches which would help to reason about each one, as you've suggested in your pull request. I don't mind closing this one in favour of yours and later submitting incremental fixes. What do you think?

Copy link
Member

Choose a reason for hiding this comment

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

However, the size and complexity of the patch stems from the fact that it tries to deal with several possible scenarios at once:

All right. MergeArgs was what got me suspicious. But I haven't looked closely yet.

I don't mind closing this one in favour of yours and later submitting incremental fixes. What do you think?

You could do it here, just rebase the pull and split the changes into separate commits.

@quickfur
Copy link
Member

ping
Any updates since last comments?

@radcapricorn
Copy link
Contributor Author

No updates as of yet. I was away from D for a while, only now resuming the work on these changes.

@CyberShadow
Copy link
Member

Note that I have a second pull request which attempts to solve the same problem: #1980

@quickfur
Copy link
Member

quickfur commented Sep 4, 2014

ping
Any progress so far, or should we close this for now and reopen it later when you're ready?

@quickfur
Copy link
Member

Since the other PR #1980 has merged, and this one hasn't been updated for a while, I'm closing this for now. Please reopen this once you have time to work on an improvement to the fix already checked in.

@quickfur quickfur closed this Sep 15, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants