Skip to content

Commit 1590ea3

Browse files
committed
Make @struct constructors use 'forward' parameters
Some effects: - Upgraded pure2-last-use.cpp2 to actually use function types (which were recently added) and directly use C++23 `std::move_only_function` (which means the test case will now work only on C++23 compilers). This exposed some places where function type support hadn't been fully plumbed through the compiler, which are also added/fixed in this commit. - This means using `@struct` with GCC requires GCC 11+, because GCC 10 doesn't support `forward` parameters of a concrete type because it has a `requires` compiler bug whose fix wasn't backported to 10 (code that tries it on GCC 10 will still get the readable diagnostic we already have that says what the issue is). GCC 10 is still generally supported. Addresses #1245
1 parent 78867f8 commit 1590ea3

19 files changed

+625
-257
lines changed

regression-tests/pure2-last-use.cpp2

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -268,18 +268,11 @@ issue_857_6: @struct type = {
268268
i: std::add_lvalue_reference_t<int> = gi;
269269
}
270270

271-
// TODO Alias `std::move_only_function`.
272-
move_only_function: <T> type = {
273-
operator=: (out this) = { }
274-
operator=: (out this, move that) = { }
275-
operator(): (move this, _...) -> int = 0;
276-
}
277-
278271
issue_857_4: @struct type = {
279-
f: std::add_pointer_t<int()>;
280-
g: std::add_pointer_t<int(int)>;
281-
mf: move_only_function<int()>;
282-
mg: move_only_function<int(int)>;
272+
f: std::add_pointer_t<()->int>;
273+
g: std::add_pointer_t<(_:int)->int>;
274+
mf: std::move_only_function<()->int>;
275+
mg: std::move_only_function<(_:int)->int>;
283276
// h0: (move this) = _ = mf();
284277
// h1: (move this) = _ = this.mf();
285278
// h2: (move this, that) = _ = that.mf();
@@ -348,7 +341,7 @@ issue_857_7: @struct type = {
348341

349342
issue_857_8: @struct type = {
350343
a: std::unique_ptr<int>;
351-
b: move_only_function<int()>;
344+
b: std::move_only_function<()->int>;
352345
c: std::add_lvalue_reference_t<int>;
353346
d: (move this) = { }
354347
}
@@ -777,7 +770,7 @@ issue_884: () = {
777770
issue_888_0: (copy r: std::string, copy size: int) = {
778771
_ = r.size();
779772
}
780-
issue_888_1: (copy _: std::string, copy size: move_only_function<int(int)>) = {
773+
issue_888_1: (copy _: std::string, copy size: std::move_only_function<(_:int)->int>) = {
781774
_ = 0.size();
782775
}
783776

@@ -794,7 +787,7 @@ issue_962: (s: ::std::string) = {
794787

795788
draw: () = {
796789
pos := 0;
797-
vertex: move_only_function<int(int)> = ();
790+
vertex: std::move_only_function<(_:int)->int> = ();
798791
_ = (pos).vertex();
799792
}
800793

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,86 @@
1-
pure2-last-use.cpp2:945:44: error: a lambda expression cannot appear in this context
2-
static_cast<void>([_0 = std::array<int,[](auto const& x) -> auto { return identity(x); }(0)>()]() mutable -> auto { return _0; });// Fails on Clang 12 (lambda in unevaluated context).
3-
^
4-
1 error generated.
1+
pure2-last-use.cpp2:273:36: error: expected variable name or 'this' in lambda capture list
2+
public: std::add_pointer_t<int([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1)> g;
3+
^
4+
pure2-last-use.cpp2:329:2: error: expected '>'
5+
};
6+
^
7+
pure2-last-use.cpp2:273:30: note: to match this '<'
8+
public: std::add_pointer_t<int([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1)> g;
9+
^
10+
pure2-last-use.cpp2:344:16: error: no template named 'move_only_function' in namespace 'std'
11+
public: std::move_only_function<int()> b;
12+
~~~~~^
13+
pure2-last-use.cpp2:348:94: error: no member named 'move_only_function' in namespace 'std'
14+
CPP2_REQUIRES_ (std::is_same_v<std::unique_ptr<int>, CPP2_TYPEOF(a_)> && std::is_same_v<std::move_only_function<int()>, CPP2_TYPEOF(b_)> && std::is_same_v<std::add_lvalue_reference_t<int>, CPP2_TYPEOF(c_)>) ;
15+
~~~~~^
16+
../../../include/cpp2util.h:10008:43: note: expanded from macro 'CPP2_REQUIRES_'
17+
#define CPP2_REQUIRES_(...) requires (__VA_ARGS__)
18+
^~~~~~~~~~~
19+
pure2-last-use.cpp2:773:69: error: no template named 'move_only_function' in namespace 'std'
20+
auto issue_888_1([[maybe_unused]] std::string unnamed_param_1, std::move_only_function<int([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1)> size) -> void;
21+
~~~~~^
22+
pure2-last-use.cpp2:773:93: error: expected variable name or 'this' in lambda capture list
23+
auto issue_888_1([[maybe_unused]] std::string unnamed_param_1, std::move_only_function<int([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1)> size) -> void;
24+
^
25+
pure2-last-use.cpp2:773:156: error: expected unqualified-id
26+
auto issue_888_1([[maybe_unused]] std::string unnamed_param_1, std::move_only_function<int([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1)> size) -> void;
27+
^
28+
pure2-last-use.cpp2:773:160: error: expected '>'
29+
auto issue_888_1([[maybe_unused]] std::string unnamed_param_1, std::move_only_function<int([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1)> size) -> void;
30+
^
31+
pure2-last-use.cpp2:773:87: note: to match this '<'
32+
auto issue_888_1([[maybe_unused]] std::string unnamed_param_1, std::move_only_function<int([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1)> size) -> void;
33+
^
34+
pure2-last-use.cpp2:773:160: error: expected ')'
35+
auto issue_888_1([[maybe_unused]] std::string unnamed_param_1, std::move_only_function<int([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1)> size) -> void;
36+
^
37+
pure2-last-use.cpp2:773:17: note: to match this '('
38+
auto issue_888_1([[maybe_unused]] std::string unnamed_param_1, std::move_only_function<int([[maybe_unused]] cpp2::impl::in<int> unnamed_param_1)> size) -> void;
39+
^
40+
pure2-last-use.cpp2:271:7: error: missing '}' at end of definition of 'issue_857_4'
41+
class issue_857_4 {
42+
^
43+
pure2-last-use.cpp2:905:1: note: still within definition of 'issue_857_4' here
44+
namespace captures {
45+
^
46+
pure2-last-use.cpp2:279:178: error: no member named 'move_only_function' in namespace 'std'
47+
requires (std::is_same_v<std::add_pointer_t<int()>, CPP2_TYPEOF(f_)> && std::is_same_v<std::add_pointer_t<int(cpp2::impl::in<int> in_)>, CPP2_TYPEOF(g_)> && std::is_same_v<std::move_only_function<int()>, CPP2_TYPEOF(mf_)> && std::is_same_v<std::move_only_function<int(cpp2::impl::in<int> in_)>, CPP2_TYPEOF(mg_)>)
48+
~~~~~^
49+
pure2-last-use.cpp2:278:14: error: out-of-line definition of 'issue_857_4' does not match any declaration in 'issue_857_4'
50+
issue_857_4::issue_857_4(auto&& f_, auto&& g_, auto&& mf_, auto&& mg_)
51+
^~~~~~~~~~~
52+
pure2-last-use.cpp2:281:272: error: member initializer 'g' does not name a non-static data member or base class
53+
, g{ CPP2_FORWARD(g_) }
54+
^~~~~~~~~~~~~~~~~~~~~
55+
pure2-last-use.cpp2:282:272: error: member initializer 'mf' does not name a non-static data member or base class
56+
, mf{ CPP2_FORWARD(mf_) }
57+
^~~~~~~~~~~~~~~~~~~~~~~
58+
pure2-last-use.cpp2:283:272: error: member initializer 'mg' does not name a non-static data member or base class
59+
, mg{ CPP2_FORWARD(mg_) }{}
60+
^~~~~~~~~~~~~~~~~~~~~~~
61+
pure2-last-use.cpp2:332:8: error: incomplete type 'issue_857_5' named in nested name specifier
62+
auto issue_857_5::f() && -> void { f_copy(std::move(cpp2::move(*this).a)); }
63+
^~~~~~~~~~~~~
64+
pure2-last-use.cpp2:331:7: note: forward declaration of 'issue_857_5'
65+
class issue_857_5;
66+
^
67+
pure2-last-use.cpp2:334:3: error: incomplete type 'issue_857_5' named in nested name specifier
68+
issue_857_5::issue_857_5(auto&& a_)
69+
^~~~~~~~~~~~~
70+
pure2-last-use.cpp2:331:7: note: forward declaration of 'issue_857_5'
71+
class issue_857_5;
72+
^
73+
pure2-last-use.cpp2:334:3: error: incomplete type 'issue_857_5' named in nested name specifier
74+
issue_857_5::issue_857_5(auto&& a_)
75+
^~~~~~~~~~~~~
76+
pure2-last-use.cpp2:331:7: note: forward declaration of 'issue_857_5'
77+
class issue_857_5;
78+
^
79+
pure2-last-use.cpp2:338:6: error: incomplete type 'issue_857_5' named in nested name specifier
80+
auto issue_857_5::operator=(auto&& a_) -> issue_857_5&
81+
^~~~~~~~~~~~~
82+
pure2-last-use.cpp2:331:7: note: forward declaration of 'issue_857_5'
83+
class issue_857_5;
84+
^
85+
fatal error: too many errors emitted, stopping now [-ferror-limit=]
86+
20 errors generated.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
pure2-bugfix-for-ufcs-arguments.cpp2:71:22: error: expected ‘;’ at end of member declaration
2+
In file included from pure2-bugfix-for-ufcs-arguments.cpp:7:
3+
../../../include/cpp2util.h:10005:47: error: static assertion failed: GCC 11 or higher is required to support variables and type-scope functions that have a 'requires' clause. This includes a type-scope 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)', which relies on being able to add a 'requires' clause - in that case, use 'forward s: _' instead if you need the result to compile with GCC 10.
4+
pure2-bugfix-for-ufcs-arguments.cpp2:72:1: note: in expansion of macro ‘CPP2_REQUIRES_’
5+
pure2-bugfix-for-ufcs-arguments.cpp2:74:39: error: expected ‘;’ at end of member declaration
6+
In file included from pure2-bugfix-for-ufcs-arguments.cpp:7:
7+
../../../include/cpp2util.h:10005:47: error: static assertion failed: GCC 11 or higher is required to support variables and type-scope functions that have a 'requires' clause. This includes a type-scope 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)', which relies on being able to add a 'requires' clause - in that case, use 'forward s: _' instead if you need the result to compile with GCC 10.
8+
pure2-bugfix-for-ufcs-arguments.cpp2:75:1: note: in expansion of macro ‘CPP2_REQUIRES_’
9+
pure2-bugfix-for-ufcs-arguments.cpp2:72:3: error: no declaration matches ‘B::B(auto:116&&) requires is_same_v<A, typename std::remove_cv<typename std::remove_reference<decltype(B::__ct ::m_)>::type>::type>’
10+
pure2-bugfix-for-ufcs-arguments.cpp2:68:7: note: candidates are: ‘constexpr B::B(B&&)’
11+
pure2-bugfix-for-ufcs-arguments.cpp2:68:7: note: ‘constexpr B::B(const B&)’
12+
pure2-bugfix-for-ufcs-arguments.cpp2:71:11: note: ‘template<class auto:104> B::B(auto:104&&)’
13+
pure2-bugfix-for-ufcs-arguments.cpp2:68:7: note: ‘class B’ defined here
14+
pure2-bugfix-for-ufcs-arguments.cpp2:74:81: error: expected unqualified-id before ‘{’ token
15+
pure2-bugfix-for-ufcs-arguments.cpp2:76:6: error: no declaration matches ‘B& B::operator=(auto:117&&) requires is_same_v<A, typename std::remove_cv<typename std::remove_reference<decltype(B::operator=::m_)>::type>::type>’
16+
pure2-bugfix-for-ufcs-arguments.cpp2:68:7: note: candidates are: ‘constexpr B& B::operator=(B&&)’
17+
pure2-bugfix-for-ufcs-arguments.cpp2:68:7: note: ‘constexpr B& B::operator=(const B&)’
18+
pure2-bugfix-for-ufcs-arguments.cpp2:74:14: note: ‘template<class auto:105> B& B::operator=(auto:105&&)’
19+
pure2-bugfix-for-ufcs-arguments.cpp2:68:7: note: ‘class B’ defined here

0 commit comments

Comments
 (0)