cppfront
cppfront copied to clipboard
[BUG] Disable UFCS if the function needs to be captured
See thread starting at https://github.com/hsutter/cppfront/issues/550#issuecomment-1834594548:
There is another case that #506 doesn't yet cover (https://cpp2.godbolt.org/z/hzYxv5rn6):
type_declaration: @struct type = { require: (this) = { } } require_fn: type == std::function<void(bool, std::string_view)>; array2: (inout t: type_declaration) = { require: require_fn = :(args...) t&$*.require(args...); _ = require; } main: () = { }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...); }}; | ^
requirehas typerequire_fn, so it isn't that its type is deduced. But it still tries to userequirewithout 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.
require: require_fn = :(args...) t&$*.require(args...);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.