Skip to content

Commit efdffab

Browse files
mkustermannCommit Bot
authored and
Commit Bot
committed
Reland "[vm] Fix some async* semantics issues: Only run generator if there's active subscription (not paused/cancelled)"
This fixes an issue where VM would run the async* generator after a `yield` / `yield*` even though the subscription may be paused or cancelled. Furthermore this fixes an issue where `StackTrace.current` used in async* generator crashes VM and/or produces truncated stack trace. This fixes the following existing tests that were failing before: * co19/Language/Statements/Yield_and_Yield_Each/Yield_Each/execution_async_t08 * co19/Language/Statements/Yield_and_Yield_Each/Yield_Each/execution_async_t09 * co19/Language/Statements/Yield_and_Yield_Each/Yield_Each/execution_async_t10 * language/async_star/async_star_cancel_test * language/async_star/pause_test New in reland: Allow the generator to to cause cancelling it's own consumer. This addresses the issue of original revert -> see flutter/flutter#101514 Issue flutter/flutter#100441 Issue #48695 Issue #34775 TEST=vm/dart{,_2}/causal_stacks/flutter_regress_100441_test Change-Id: I091b7159d59ea15fc31162b4b6b17260d523d7cb Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/242400 Reviewed-by: Lasse Nielsen <[email protected]> Commit-Queue: Martin Kustermann <[email protected]>
1 parent 0b5a8fa commit efdffab

22 files changed

+337
-93
lines changed

pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,10 @@ static method asyncStarString() → asy::Stream<core::String> /* originally asyn
121121
return null;
122122
else
123123
[yield] null;
124-
if(:controller.{asy::_AsyncStarStreamController::addStream}(self::asyncStarString2()){(asy::Stream<core::String>) → core::bool})
124+
:controller.{asy::_AsyncStarStreamController::addStream}(self::asyncStarString2()){(asy::Stream<core::String>) → void};
125+
[yield] null;
126+
if(_in::unsafeCast<core::bool>(:result_or_exception))
125127
return null;
126-
else
127-
[yield] null;
128128
[yield] let dynamic #t1 = asy::_awaitHelper(self::asyncString(), :async_op_then, :async_op_error) in null;
129129
if(:controller.{asy::_AsyncStarStreamController::add}(_in::unsafeCast<core::String>(:result_or_exception)){(core::String) → core::bool})
130130
return null;

pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -652,10 +652,10 @@ static method controlFlow() → dynamic /* futureValueType= dynamic */ /* origin
652652
#L16:
653653
{
654654
[yield] let dynamic #t55 = asy::_awaitHelper(func<asy::Stream<core::int>>(self::intStream()){(asy::Stream<core::int>) → FutureOr<asy::Stream<core::int>>}, :async_op_then, :async_op_error) in null;
655-
if(:controller.{asy::_AsyncStarStreamController::addStream}(_in::unsafeCast<asy::Stream<core::int>>(:result_or_exception)){(asy::Stream<core::int>) → core::bool})
655+
:controller.{asy::_AsyncStarStreamController::addStream}(_in::unsafeCast<asy::Stream<core::int>>(:result_or_exception)){(asy::Stream<core::int>) → void};
656+
[yield] null;
657+
if(_in::unsafeCast<core::bool>(:result_or_exception))
656658
return null;
657-
else
658-
[yield] null;
659659
}
660660
return;
661661
}

pkg/front_end/testcases/general/statements.dart.weak.transformed.expect

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ static method bar(dynamic d) → dynamic /* originally async* */ {
4444
return null;
4545
else
4646
[yield] null;
47-
if(:controller.{asy::_AsyncStarStreamController::addStream}(x as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Stream<dynamic>){(asy::Stream<dynamic>) → core::bool})
47+
:controller.{asy::_AsyncStarStreamController::addStream}(x as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Stream<dynamic>){(asy::Stream<dynamic>) → void};
48+
[yield] null;
49+
if(_in::unsafeCast<core::bool>(:result_or_exception))
4850
return null;
49-
else
50-
[yield] null;
5151
}
5252
}
5353
else

pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.weak.transformed.expect

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ library test;
22
import self as self;
33
import "dart:async" as asy;
44
import "dart:core" as core;
5+
import "dart:_internal" as _in;
56

67
import "dart:async";
78

@@ -25,10 +26,10 @@ static method test() → dynamic {
2526
else
2627
[yield] null;
2728
asy::Stream<core::double*>* s;
28-
if(:controller.{asy::_AsyncStarStreamController::addStream}(s){(asy::Stream<core::num*>) → core::bool})
29+
:controller.{asy::_AsyncStarStreamController::addStream}(s){(asy::Stream<core::num*>) → void};
30+
[yield] null;
31+
if(_in::unsafeCast<core::bool>(:result_or_exception))
2932
return null;
30-
else
31-
[yield] null;
3233
}
3334
return;
3435
}

pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.weak.transformed.expect

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ library test;
2929
import self as self;
3030
import "dart:core" as core;
3131
import "dart:async" as asy;
32+
import "dart:_internal" as _in;
3233

3334
import "dart:async";
3435

@@ -109,18 +110,18 @@ static method foo() → asy::Stream<core::List<core::int*>*>* /* originally asyn
109110
return null;
110111
else
111112
[yield] null;
112-
if(:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:17:64: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'Stream<List<int>>'.
113+
:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:17:64: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'Stream<List<int>>'.
113114
- 'List' is from 'dart:core'.
114115
- 'Stream' is from 'dart:async'.
115116
yield* /*error:YIELD_OF_INVALID_TYPE*/ /*@typeArgs=dynamic*/ [];
116-
^" in core::_GrowableList::•<dynamic>(0) as{TypeError} asy::Stream<core::List<core::int*>*>*){(asy::Stream<core::List<core::int*>*>) → core::bool})
117+
^" in core::_GrowableList::•<dynamic>(0) as{TypeError} asy::Stream<core::List<core::int*>*>*){(asy::Stream<core::List<core::int*>*>) → void};
118+
[yield] null;
119+
if(_in::unsafeCast<core::bool>(:result_or_exception))
117120
return null;
118-
else
119-
[yield] null;
120-
if(:controller.{asy::_AsyncStarStreamController::addStream}(self::MyStream::•<core::List<core::int*>*>()){(asy::Stream<core::List<core::int*>*>) → core::bool})
121+
:controller.{asy::_AsyncStarStreamController::addStream}(self::MyStream::•<core::List<core::int*>*>()){(asy::Stream<core::List<core::int*>*>) → void};
122+
[yield] null;
123+
if(_in::unsafeCast<core::bool>(:result_or_exception))
121124
return null;
122-
else
123-
[yield] null;
124125
}
125126
return;
126127
}

pkg/front_end/testcases/inference/local_return_and_yield.dart.weak.transformed.expect

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ library test;
1010
import self as self;
1111
import "dart:core" as core;
1212
import "dart:async" as asy;
13+
import "dart:_internal" as _in;
1314

1415
import "dart:async";
1516

@@ -129,10 +130,10 @@ static method main() → dynamic {
129130
try {
130131
#L3:
131132
{
132-
if(:controller.{asy::_AsyncStarStreamController::addStream}(asy::Stream::fromIterable<(core::int*) →* core::int*>(core::_GrowableList::_literal1<(core::int*) →* core::int*>((core::int* x) → core::int* => x))){(asy::Stream<(core::int*) →* core::int*>) → core::bool})
133+
:controller.{asy::_AsyncStarStreamController::addStream}(asy::Stream::fromIterable<(core::int*) →* core::int*>(core::_GrowableList::_literal1<(core::int*) →* core::int*>((core::int* x) → core::int* => x))){(asy::Stream<(core::int*) →* core::int*>) → void};
134+
[yield] null;
135+
if(_in::unsafeCast<core::bool>(:result_or_exception))
133136
return null;
134-
else
135-
[yield] null;
136137
}
137138
return;
138139
}

pkg/front_end/testcases/inference/top_level_return_and_yield.dart.weak.transformed.expect

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ library test;
1010
import self as self;
1111
import "dart:core" as core;
1212
import "dart:async" as asy;
13+
import "dart:_internal" as _in;
1314

1415
import "dart:async";
1516

@@ -128,10 +129,10 @@ static method f() → asy::Stream<(core::int*) →* core::int*>* /* originally a
128129
try {
129130
#L3:
130131
{
131-
if(:controller.{asy::_AsyncStarStreamController::addStream}(asy::Stream::fromIterable<(core::int*) →* core::int*>(core::_GrowableList::_literal1<(core::int*) →* core::int*>((core::int* x) → core::int* => x))){(asy::Stream<(core::int*) →* core::int*>) → core::bool})
132+
:controller.{asy::_AsyncStarStreamController::addStream}(asy::Stream::fromIterable<(core::int*) →* core::int*>(core::_GrowableList::_literal1<(core::int*) →* core::int*>((core::int* x) → core::int* => x))){(asy::Stream<(core::int*) →* core::int*>) → void};
133+
[yield] null;
134+
if(_in::unsafeCast<core::bool>(:result_or_exception))
132135
return null;
133-
else
134-
[yield] null;
135136
}
136137
return;
137138
}

pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ library /*isNonNullableByDefault*/;
4040
import self as self;
4141
import "dart:async" as asy;
4242
import "dart:core" as core;
43+
import "dart:_internal" as _in;
4344

4445
static method getNull() → dynamic
4546
return null;
@@ -160,13 +161,13 @@ static method test4() → asy::Stream<core::bool> /* originally async* */ {
160161
try {
161162
#L4:
162163
{
163-
if(:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:21:10: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
164+
:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:21:10: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
164165
- 'Stream' is from 'dart:async'.
165166
yield* getStreamNull(); // error
166-
^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → core::bool})
167+
^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → void};
168+
[yield] null;
169+
if(_in::unsafeCast<core::bool>(:result_or_exception))
167170
return null;
168-
else
169-
[yield] null;
170171
}
171172
return;
172173
}
@@ -203,10 +204,10 @@ static method test7() → asy::Stream<core::bool> /* originally async* */ {
203204
try {
204205
#L5:
205206
{
206-
if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
207+
:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
208+
[yield] null;
209+
if(_in::unsafeCast<core::bool>(:result_or_exception))
207210
return null;
208-
else
209-
[yield] null;
210211
}
211212
return;
212213
}
@@ -285,13 +286,13 @@ static method test() → dynamic /* futureValueType= dynamic */ /* originally as
285286
try {
286287
#L8:
287288
{
288-
if(:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:38:12: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
289+
:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:38:12: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
289290
- 'Stream' is from 'dart:async'.
290291
yield* getStreamNull(); // error
291-
^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → core::bool})
292+
^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → void};
293+
[yield] null;
294+
if(_in::unsafeCast<core::bool>(:result_or_exception))
292295
return null;
293-
else
294-
[yield] null;
295296
}
296297
return;
297298
}
@@ -328,10 +329,10 @@ static method test() → dynamic /* futureValueType= dynamic */ /* originally as
328329
try {
329330
#L9:
330331
{
331-
if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
332+
:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
333+
[yield] null;
334+
if(_in::unsafeCast<core::bool>(:result_or_exception))
332335
return null;
333-
else
334-
[yield] null;
335336
}
336337
return;
337338
}
@@ -402,10 +403,10 @@ static method test() → dynamic /* futureValueType= dynamic */ /* originally as
402403
try {
403404
#L11:
404405
{
405-
if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamNull()){(asy::Stream<dynamic>) → core::bool})
406+
:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamNull()){(asy::Stream<dynamic>) → void};
407+
[yield] null;
408+
if(_in::unsafeCast<core::bool>(:result_or_exception))
406409
return null;
407-
else
408-
[yield] null;
409410
}
410411
return;
411412
}
@@ -440,10 +441,10 @@ static method test() → dynamic /* futureValueType= dynamic */ /* originally as
440441
try {
441442
#L12:
442443
{
443-
if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
444+
:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
445+
[yield] null;
446+
if(_in::unsafeCast<core::bool>(:result_or_exception))
444447
return null;
445-
else
446-
[yield] null;
447448
}
448449
return;
449450
}

pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ library /*isNonNullableByDefault*/;
4040
import self as self;
4141
import "dart:async" as asy;
4242
import "dart:core" as core;
43+
import "dart:_internal" as _in;
4344

4445
static method getNull() → dynamic
4546
return null;
@@ -160,13 +161,13 @@ static method test4() → asy::Stream<core::bool> /* originally async* */ {
160161
try {
161162
#L4:
162163
{
163-
if(:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:21:10: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
164+
:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:21:10: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
164165
- 'Stream' is from 'dart:async'.
165166
yield* getStreamNull(); // error
166-
^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → core::bool})
167+
^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → void};
168+
[yield] null;
169+
if(_in::unsafeCast<core::bool>(:result_or_exception))
167170
return null;
168-
else
169-
[yield] null;
170171
}
171172
return;
172173
}
@@ -203,10 +204,10 @@ static method test7() → asy::Stream<core::bool> /* originally async* */ {
203204
try {
204205
#L5:
205206
{
206-
if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
207+
:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
208+
[yield] null;
209+
if(_in::unsafeCast<core::bool>(:result_or_exception))
207210
return null;
208-
else
209-
[yield] null;
210211
}
211212
return;
212213
}
@@ -285,13 +286,13 @@ static method test() → dynamic /* futureValueType= dynamic */ /* originally as
285286
try {
286287
#L8:
287288
{
288-
if(:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:38:12: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
289+
:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:38:12: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
289290
- 'Stream' is from 'dart:async'.
290291
yield* getStreamNull(); // error
291-
^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → core::bool})
292+
^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → void};
293+
[yield] null;
294+
if(_in::unsafeCast<core::bool>(:result_or_exception))
292295
return null;
293-
else
294-
[yield] null;
295296
}
296297
return;
297298
}
@@ -328,10 +329,10 @@ static method test() → dynamic /* futureValueType= dynamic */ /* originally as
328329
try {
329330
#L9:
330331
{
331-
if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
332+
:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
333+
[yield] null;
334+
if(_in::unsafeCast<core::bool>(:result_or_exception))
332335
return null;
333-
else
334-
[yield] null;
335336
}
336337
return;
337338
}
@@ -402,10 +403,10 @@ static method test() → dynamic /* futureValueType= dynamic */ /* originally as
402403
try {
403404
#L11:
404405
{
405-
if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamNull()){(asy::Stream<dynamic>) → core::bool})
406+
:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamNull()){(asy::Stream<dynamic>) → void};
407+
[yield] null;
408+
if(_in::unsafeCast<core::bool>(:result_or_exception))
406409
return null;
407-
else
408-
[yield] null;
409410
}
410411
return;
411412
}
@@ -440,10 +441,10 @@ static method test() → dynamic /* futureValueType= dynamic */ /* originally as
440441
try {
441442
#L12:
442443
{
443-
if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
444+
:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
445+
[yield] null;
446+
if(_in::unsafeCast<core::bool>(:result_or_exception))
444447
return null;
445-
else
446-
[yield] null;
447448
}
448449
return;
449450
}

pkg/vm/lib/transformations/continuation.dart

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,10 +1329,21 @@ class AsyncStarFunctionRewriter extends AsyncRewriterBase {
13291329
functionType: addMethodFunctionType)
13301330
..fileOffset = stmt.fileOffset;
13311331

1332-
statements.add(new IfStatement(
1333-
addExpression,
1334-
new ReturnStatement(new NullLiteral()),
1335-
createContinuationPoint()..fileOffset = stmt.fileOffset));
1332+
if (stmt.isYieldStar) {
1333+
statements.add(ExpressionStatement(addExpression));
1334+
statements.add(createContinuationPoint()..fileOffset = stmt.fileOffset);
1335+
final wasCancelled = StaticInvocation(
1336+
helper.unsafeCast,
1337+
Arguments(<Expression>[VariableGet(expressionRewriter!.asyncResult)],
1338+
types: <DartType>[helper.coreTypes.boolNonNullableRawType]));
1339+
statements
1340+
.add(IfStatement(wasCancelled, ReturnStatement(NullLiteral()), null));
1341+
} else {
1342+
statements.add(new IfStatement(
1343+
addExpression,
1344+
new ReturnStatement(new NullLiteral()),
1345+
createContinuationPoint()..fileOffset = stmt.fileOffset));
1346+
}
13361347
return removalSentinel ?? EmptyStatement();
13371348
}
13381349

0 commit comments

Comments
 (0)