@@ -5,93 +5,91 @@ using namespace Windows::Foundation;
55
66namespace
77{
8- struct free_awaitable
9- {
10- };
11- bool await_ready (free_awaitable)
12- {
13- return true ;
14- }
15- void await_suspend (free_awaitable, std::experimental::coroutine_handle<>)
16- {
17- }
18- void await_resume (free_awaitable)
19- {
8+ using std::experimental::suspend_never;
209
21- }
22-
23- struct member_awaitable
10+ // Never suspends.
11+ // Allows copying, but asserts if you try.
12+ struct suspend_never_but_assert_if_copied : suspend_never
2413 {
25- bool await_ready ()
14+ suspend_never_but_assert_if_copied () = default ;
15+ suspend_never_but_assert_if_copied (suspend_never_but_assert_if_copied const &)
2616 {
27- return true ;
17+ REQUIRE ( false ) ;
2818 }
29- void await_suspend (std::experimental::coroutine_handle<>)
19+ };
20+
21+ // The bad_awaiter asserts if it ever gets used.
22+ // Use it for ambiguous alternatives we don't want to pick.
23+ struct bad_awaiter : suspend_never
24+ {
25+ void await_resume () const noexcept
3026 {
27+ REQUIRE (false );
3128 }
32- void await_resume ()
33- {
29+ };
3430
35- }
31+ // If the only awaitable is the member awaitable, then use it.
32+ struct member_awaitable : suspend_never_but_assert_if_copied
33+ {
3634 };
3735
38- struct free_operator_awaitable
36+ // Should pick the free operator co_await over the member awaitable.
37+ struct free_operator_awaitable : bad_awaiter
3938 {
4039 };
4140 auto operator co_await (free_operator_awaitable)
4241 {
43- struct awaitable
44- {
45- bool await_ready ()
46- {
47- return true ;
48- }
49- void await_suspend (std::experimental::coroutine_handle<>)
50- {
51- }
52- void await_resume ()
53- {
54- }
55- };
56- return awaitable{};
42+ return suspend_never_but_assert_if_copied{};
5743 }
5844
59- struct member_operator_awaitable
45+ // Should pick the member operator co_await over the member awaitable.
46+ struct member_operator_awaitable : bad_awaiter
6047 {
6148 auto operator co_await ()
6249 {
63- struct awaitable
64- {
65- bool await_ready ()
66- {
67- return true ;
68- }
69- void await_suspend (std::experimental::coroutine_handle<>)
70- {
71- }
72- void await_resume ()
73- {
74- }
75- };
76- return awaitable{};
50+ return suspend_never_but_assert_if_copied{};
7751 }
7852 };
7953
80- struct no_copy_awaitable
54+ // Verify that we can await non-copyable objects.
55+ struct no_copy_awaitable : suspend_never
8156 {
8257 no_copy_awaitable () = default ;
8358 no_copy_awaitable (no_copy_awaitable const &) = delete ;
59+ };
8460
85- bool await_ready ()
61+ // operator co_await takes precedence over member awaitable.
62+ struct ambiguous_awaitable1 : bad_awaiter
63+ {
64+ auto operator co_await ()
8665 {
87- return true ;
66+ return suspend_never_but_assert_if_copied{} ;
8867 }
89- void await_suspend (std::experimental::coroutine_handle<>)
68+ };
69+
70+ // This awaitable supports both member co_await
71+ // and free co_await, and the free co_await is a
72+ // better match if invoked on an lvalue. We don't try
73+ // to support this case. We just declare it as ambiguous.
74+ struct ambiguous_awaitable2 : bad_awaiter
75+ {
76+ auto operator co_await () const
9077 {
78+ return bad_awaiter{};
9179 }
92- void await_resume ()
93- {
80+ };
81+ suspend_never_but_assert_if_copied operator co_await (ambiguous_awaitable2&)
82+ {
83+ return {};
84+ }
9485
86+ // We invoke this on an lvalue, so the member co_await is unavailable.
87+ // Verify that the unavailable co_await is ignored.
88+ struct ambiguous_awaitable3 : suspend_never_but_assert_if_copied
89+ {
90+ auto operator co_await ()&&
91+ {
92+ return bad_awaiter{};
9593 }
9694 };
9795
@@ -120,18 +118,21 @@ namespace
120118
121119 static std::vector<std::pair<void const *, notification>> watcher;
122120 static handle start_racing{ CreateEventW (nullptr , true , false , nullptr ) };
123- constexpr size_t test_suspension_points = 12 ;
121+ constexpr size_t test_suspension_points = 13 ;
124122
125123 IAsyncAction Async ()
126124 {
127125 co_await resume_on_signal (start_racing.get ());
128126 co_await resume_background ();
129127 co_await resume_background ();
130- co_await free_awaitable{};
131128 co_await member_awaitable{};
132129 co_await free_operator_awaitable{};
133130 co_await member_operator_awaitable{};
134131 co_await no_copy_awaitable{};
132+ co_await ambiguous_awaitable1{};
133+ // co_await ambiguous_awaitable2{}; // does not compile
134+ ambiguous_awaitable3 awaitable3;
135+ co_await awaitable3;
135136 co_await AsyncAction ();
136137 co_await AsyncActionWithProgress ();
137138 co_await AsyncOperation ();
0 commit comments