You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[BUG] Variable with placeholder type can't share name with member call in initializer #550
main.cpp2:5:23: error: variable 'f' declared with deduced type 'auto' cannot appear in its own initializer
5 | auto f {CPP2_UFCS_0(f, t())};
| ^
1 error generated.
Rewriting Cpp1 auto f {t().f()};
to Cpp2 f := t().f();
can result in ill-formed code.
You'd either need to change the member's name,
or come up with a new name for the local variable.
Maybe there's something from the exploration of #307 I can salvage to solve this issue.
Nope (#307 (comment)):
Even then, with the new branch in the macro, a variable named after a member function breaks UFCS
#506's resolution for #550 adds quite some complexity to Cppfront.
The same can be done here to resolve this #788.
The alternative is to just embrace #550 and #788 as limitations of Cppfront,
and require users to not name such variables like the function in a UFCS call.
main.cpp2:6:91: error: variable 'require' cannot be implicitly captured in a lambda with no capture-default specified
6 | require_fn require {[_0 = (&t)](auto const& ...args) mutable -> auto { return CPP2_UFCS(require, (*cpp2::assert_not_null(_0)), args...); }};
| ^
main.cpp2:6:14: note: 'require' declared here
6 | require_fn require {[_0 = (&t)](auto const& ...args) mutable -> auto { return CPP2_UFCS(require, (*cpp2::assert_not_null(_0)), args...); }};
| ^
require has type require_fn, so it isn't that its type is deduced.
But it still tries to use require without capturing it.
Name lookup finds an object, so it doesn't try a free function, and the object must be captured.
If we're in a context that would need to capture the name, we should not use the UFCS macro.
In the context of a member function, this would happen to work due to #281.
main.cpp2:6:38: error: variable 'require' declared with deduced type 'std::optional' cannot appear in its own initializer
6 | std::optional require {CPP2_UFCS_0(require, t)};
| ^
main.cpp2:6:17: error: no viable constructor or deduction guide for deduction of template arguments of 'optional'
6 | std::optional require {CPP2_UFCS_0(require, t)};
| ^
This is the same as #550 (comment).
Except that we can't easily identify that CTAD is required.
Maybe a nested requirement such as requires { typename std::optional; } might work to detect it.
Activity
JohelEGP commentedon Aug 10, 2023
All compilers reject https://compiler-explorer.com/z/4f3d818hs:
(Opened https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110978 for GCC's ICE.)
Maybe
overload_linearlywould work.No, it doesn't: https://compiler-explorer.com/z/9vnKvveK5.
JohelEGP commentedon Aug 29, 2023
Rewriting Cpp1
auto f {t().f()};to Cpp2
f := t().f();can result in ill-formed code.
You'd either need to change the member's name,
or come up with a new name for the local variable.
Maybe there's something from the exploration of #307 I can salvage to solve this issue.
Nope (#307 (comment)):
JohelEGP commentedon Aug 30, 2023
I think the solution is to disable UFCS
if name lookup finds that the function identifier being called
is a variable and we are in its initializer.
JohelEGP commentedon Oct 29, 2023
From #788 (comment):
JohelEGP commentedon Nov 22, 2023
Here is a data point that suggests Cpp1 code equivalent to Cpp2
𝘮𝘦𝘮 := 𝘷𝘢𝘳.𝘮𝘦𝘮();is prolific.There are 12.1 K results precisely for
auto size = 𝘷𝘢𝘳.size();(https://github.com/search?q=lang%3AC%2B%2B+content%3A%2Fauto+size+%3D+%28%3F%3A%5Ba-zA-Z_%5D%2B%29%5C.size%5C%28%5C%29%3B%2F+NOT+is%3Afork&type=code).JohelEGP commentedon Nov 30, 2023
There is another case that #506 doesn't yet cover (https://cpp2.godbolt.org/z/hzYxv5rn6):
requirehas typerequire_fn, so it isn't that its type is deduced.But it still tries to use
requirewithout capturing it.Name lookup finds an object, so it doesn't try a free function, and the object must be captured.
If we're in a context that would need to capture the name, we should not use the UFCS macro.
In the context of a member function, this would happen to work due to #281.
There is another case that #506 doesn't yet cover (https://cpp2.godbolt.org/z/xj1P9cd66):
This is the same as #550 (comment).
Except that we can't easily identify that CTAD is required.
Maybe a nested requirement such as
requires { typename std::optional; }might work to detect it.JohelEGP commentedon Nov 30, 2023
For this kind of code, in GitHub,
there are precisely 7 uses with the identifier
sizethat would break if they were rewritten to Cpp2 and compiled with cppfront:
https://github.com/search?q=lang%3AC%2B%2B+content%3A%2F+size+%3D+%5C%5B.*%5C.size%5C%28%5C%29%3B%2F+NOT+is%3Afork&type=code.