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 22701: Remove is(typeof()) callable check in std.typecons.apply. #8364
Fix issue 22701: Remove is(typeof()) callable check in std.typecons.apply. #8364
Conversation
Thanks for your pull request and interest in making D better, @FeepingCreature! 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 "master + phobos#8364" |
Errors seem spurious. |
@FeepingCreature please rebase. That will fix the testing pipeline. |
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.
Could you provide an example where the error message is improved with this patch? I tested this (adapted from the public unittest):
import std.typecons;
void main()
{
Nullable!int sample;
Nullable!float f;
sample = 3;
f = sample.apply!sample;
}
And I get the following results:
- Before patch:
onlineapp.d(9): Error: template `onlineapp.main.apply!(sample).apply` cannot deduce function from argument types `!()(Nullable!int)`
/dlang/dmd/linux/bin64/../../src/phobos/std/typecons.d(4038): Candidate is: `apply(T)(auto ref T t)`
with `T = Nullable!int`
must satisfy the following constraint:
` is(typeof(unaryFun!fun(T.init.get)))`
- After patch:
phobos/std/typecons.d(4047): Error: struct `Nullable` does not overload ()
phobos/std/typecons.d(4068): Error: struct `Nullable` does not overload ()
test.d(9): Error: template instance `test.main.apply!(Nullable!int)` error instantiating
Note how this patch moves the failure in the innards of the apply
function.
Sure, for example:
Without patch:
With patch:
That's where you need the magic knowledge to replace the apply with edit: Rebased. edit: Really, the template condition should just check "you are passing an in principle callable thing." It shouldn't check if it can actually be called; more urgently, if it does check that, it shouldn't then silently eat the reason why it couldn't be called. Etc |
…pply. It creates unreadable template errors for no benefit.
1e1de00
to
ac5c8d0
Compare
I understand that the current error message is not ideal, however:
This patch, however, opens the door to issuing errors from inside the implementation of auto v = someFunctionReturningNullableOfInt();
v.apply!(a => a ~ a); // error: incompatible type int for ~; ok what do I do now? This, in my opinion, is more confusing then presenting a condition which has failed. With the current status you can simply copy that condition and run it in a separate file and see why it failed, plus all the actual types are included in the error message. |
In my experience with Nullable, and Phobos' predicate functions in general, more than 90% of the time the issue is a semantic error inside the lambda. The issue is practically never an error in apply itself. And if it was, that would be the sort of issue that you can apply inside knowledge to solving. Semantic errors in the lambda are the thing that's most plausible to turn up in user code, which is exactly the target group where vague, content-free hints like tl;dr: might as well
(And yes, that's obvious, but now assume it's a much bigger range expression.) |
I am willing concede in front of real life experience with |
May be a good thing to take to the forum too? Since it's really a problem with all of std.algorithm. (Ie. if I can find the time and people agree, I'd love to remove the is(typeof())s from everything that takes a lambda. But that's the sort of problem I wouldn't want to embark on unless I had some confidence the reviewers agreed that this was worthwhile.) |
Only, that I have not used apply that much. Like once or twice. But in general I'm not a fan of template constraint in general. |
I will say: I recently made a very similar change at fork for the exact same reason: error messages were incomprehensible without, useful with. (That said I have not used apply. But seeing as feep did, ran into the same issue, this seems quite reasonable.) |
@FeepingCreature this
Would be ideal. |
Not sure how to do that? The error that I want is inside the lambda. If I static assert something in apply, wouldn't that error suppress the error in the lambda? In serialized I just used pragma(msg) to add context to an error, but since there's no way to capture error messages from __traits(compiles), the message still needs to come from a regular compile attempt at the lambda. |
I would compare type of the parameter of the passed function with the T of the Nullable. When you get a void != int you likely know where to look. |
Well, with a lambda you don't have a passed type. I guess I should add a edit: I've been playing around with this for the past half hour. I don't see any way to do it right. DMD just does not give enough control over the actual error message that will be generated. Closest I have so far is
But that prints multiple versions of the in-lambda error, and I don't see any way to avoid that without way more static if than I'm comfortable with. edit: It seems to work if I add some more nesting:
As far as I can tell this does the right thing ~ everywhere, but it's very hacky and I hate it. |
Ok, let's just merge as is and we can improve on it in the future if needed. |
To quote my bug report:
As I said in my DConf talk,
__traits(compiles)
is Satan, the Great Deceiver. The presence ofis(typeof())
(__traits(compiles
by any other name) in the definition ofapply
needlessly turns a clear, readable error in the passed lambda into an incomprehensible template error that requires advanced language knowledge or blind guessing to untangle. And there's no point, because there's only one apply function! It should just be removed.(Let's see if this passes the testsuite!)