-
Notifications
You must be signed in to change notification settings - Fork 258
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
Add UFCS failure case error diagnostics #1023
Conversation
This might be easily achievable. Maybe these changes can achieve that:
+#define CPP2_UFCS_EMPTY(...)
#define CPP2_UFCS_IDENTITY(...) __VA_ARGS__
-#define CPP2_UFCS_(LAMBDADEFCAPT,MVFWD,QUALID,TEMPKW,...) \
+#define CPP2_UFCS_(LAMBDADEFCAPT,SFINAE,MVFWD,QUALID,TEMPKW,...) \
[LAMBDADEFCAPT]< \
typename Obj, typename... Params \
CPP2_UFCS_IS_NOTHROW_PARAM(MVFWD,QUALID,TEMPKW,__VA_ARGS__) \
CPP2_UFCS_CONSTRAINT_PARAM(MVFWD,QUALID,TEMPKW,__VA_ARGS__) \
> \
CPP2_LAMBDA_NO_DISCARD (Obj&& obj, Params&& ...params) CPP2_FORCE_INLINE_LAMBDA_CLANG \
noexcept(CPP2_UFCS_IS_NOTHROW_ARG(MVFWD,QUALID,TEMPKW,__VA_ARGS__)) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) \
- requires CPP2_UFCS_CONSTRAINT_ARG(MVFWD,QUALID,TEMPKW,__VA_ARGS__) { \
+ SFINAE(requires CPP2_UFCS_CONSTRAINT_ARG(MVFWD,QUALID,TEMPKW,__VA_ARGS__)) { \
+#define CPP2_UFCS(...) CPP2_UFCS_(&,CPP2_UFCS_EMPTY,CPP2_UFCS_IDENTITY,(),,__VA_ARGS__)
+#define CPP2_UFCS_MOVE(...) CPP2_UFCS_(&,CPP2_UFCS_EMPTY,std::move,(),,__VA_ARGS__)
+#define CPP2_UFCS_FORWARD(...) CPP2_UFCS_(&,CPP2_UFCS_EMPTY,CPP2_FORWARD,(),,__VA_ARGS__)
+#define CPP2_UFCS_TEMPLATE(...) CPP2_UFCS_(&,CPP2_UFCS_EMPTY,CPP2_UFCS_IDENTITY,(),template,__VA_ARGS__)
+#define CPP2_UFCS_QUALIFIED_TEMPLATE(QUALID,...) CPP2_UFCS_(&,CPP2_UFCS_EMPTY,CPP2_UFCS_IDENTITY,QUALID,template,__VA_ARGS__)
+#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,CPP2_UFCS_IDENTITY,CPP2_UFCS_IDENTITY,(),,__VA_ARGS__)
+#define CPP2_UFCS_TEMPLATE_NONLOCAL(...) CPP2_UFCS_(,CPP2_UFCS_IDENTITY,CPP2_UFCS_IDENTITY,(),template,__VA_ARGS__)
+#define CPP2_UFCS_QUALIFIED_TEMPLATE_NONLOCAL(QUALID,...) CPP2_UFCS_(,CPP2_UFCS_IDENTITY,CPP2_UFCS_IDENTITY,QUALID,template,__VA_ARGS__) |
I actually did this in #490, before realizing the need for SFINAE. An important piece of information not visible at the call site are the overload sets. #include <vector>
int main() {
std::vector<int> x;
std::vector<long> y;
x.swap(y);
} Just having the |
Per #1023 (comment) and followups
🎉 Indeed, that was exactly what was needed -- thanks!
Wonderful, yes it does make the errors better... using the example above, now I get a message that includes:
Very nice. Thanks again. |
@@ -887,6 +887,7 @@ class out { | |||
#endif | |||
#endif | |||
|
|||
#define CPP2_UFCS_EMPTY(...) |
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.
Maybe CPP2_UFCS_EMPTY
wasn't necessary, and passing CPP2_UFCS_IDENTITY
instead would have done the job.
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.
But then all the cases would be the same again, and we'd have the original problem in non-SFINAE cases?
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.
Ah, you're right.
Partly addresses #1004
Context: this comment
The purpose of this PR is to improve the diagnostic when UFCS calls don't resolve. The main problem case I've encountered is when the UFCS is a definite last use and the function that would be called does not accept rvalues. So I've added diagnostics for those cases. For example, this code
currently gets an error like this:
and with this PR gets this nicer error:
But to make that work I also had to comment out the
requires
clause that constrains the argument, so that we can enter the lambda and reach the new diagnostics, and it's thoserequires
failures that are the hard-to-read diagnostics. However, therequires
clause seems to be there to make UFCS calls possible in SFINAE contexts.And all regressions pass... except the SFINAE cases (see the 3 changed
.output
files). Because those cases want thatrequires
to fail, right?Summarizing the problem
If I'm understanding this right, it seems there's an inherent tension here for UFCS calls that won't succeed...
requires
so as not to enter the body, and be SFINAE-ABLE but also get the current hard-to-understand diagnostics in move-from-last-use-and-pass-to-something-that-can't-take-an-rvalue casesrequires
and enter the body, and get the new nicer diagnostic for those cases... and I don't yet see how to achieve both at the same time.
@JohelEGP since you crafted the current UFCS version, what do you think?