Skip to content

Commit b64550e

Browse files
lrhncommit-bot@chromium.org
authored andcommitted
Add a nullFuture in dart:internal.
This is the future returned by `dart:async` in some cases which used to return `null` pre null-safety. Code inside the SDK which *needs* to not change its timing of events can recognize the future and skip waiting for it, giving the same "synchronous" behavior as before the null safety change. Longer term, we need to wean people off depending on the specific interleaving of events. Maybe we should randomly shuffle our microtask queue. Change-Id: I8d52e74f0549a3068f5dfaffb28c7894b324c49d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/172641 Commit-Queue: Lasse R.H. Nielsen <[email protected]> Reviewed-by: Nate Bosch <[email protected]>
1 parent 90ec6f2 commit b64550e

File tree

4 files changed

+43
-17
lines changed

4 files changed

+43
-17
lines changed

pkg/front_end/testcases/nnbd/issue42546.dart.outline.expect

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,19 @@ static method main() → dynamic
2828

2929

3030
Extra constant evaluation status:
31-
Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:661:13 -> SymbolConstant(#catchError)
32-
Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:661:13 -> ListConstant(const <Type*>[])
33-
Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:661:13 -> SymbolConstant(#test)
34-
Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:698:13 -> SymbolConstant(#whenComplete)
35-
Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:698:13 -> ListConstant(const <Type*>[])
36-
Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:698:13 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
37-
Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:725:13 -> SymbolConstant(#timeout)
38-
Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:725:13 -> ListConstant(const <Type*>[])
39-
Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:725:13 -> SymbolConstant(#onTimeout)
40-
Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:622:13 -> SymbolConstant(#then)
41-
Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:622:13 -> SymbolConstant(#onError)
42-
Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:709:13 -> SymbolConstant(#asStream)
43-
Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:709:13 -> ListConstant(const <Type*>[])
44-
Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:709:13 -> ListConstant(const <dynamic>[])
45-
Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:709:13 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
31+
Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:664:13 -> SymbolConstant(#catchError)
32+
Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:664:13 -> ListConstant(const <Type*>[])
33+
Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:664:13 -> SymbolConstant(#test)
34+
Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:701:13 -> SymbolConstant(#whenComplete)
35+
Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:701:13 -> ListConstant(const <Type*>[])
36+
Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:701:13 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
37+
Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:728:13 -> SymbolConstant(#timeout)
38+
Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:728:13 -> ListConstant(const <Type*>[])
39+
Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:728:13 -> SymbolConstant(#onTimeout)
40+
Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:625:13 -> SymbolConstant(#then)
41+
Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:625:13 -> SymbolConstant(#onError)
42+
Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:712:13 -> SymbolConstant(#asStream)
43+
Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:712:13 -> ListConstant(const <Type*>[])
44+
Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:712:13 -> ListConstant(const <dynamic>[])
45+
Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:712:13 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
4646
Extra constant evaluation: evaluated: 61, effectively constant: 15

sdk/lib/async/async.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ import "dart:_internal"
101101
checkNotNullable,
102102
EmptyIterator,
103103
IterableElementError,
104+
nullFuture,
104105
printToZone,
105106
printToConsole,
106107
Since,

sdk/lib/async/future.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,11 @@ abstract class FutureOr<T> {
147147
*/
148148
abstract class Future<T> {
149149
/// A `Future<Null>` completed with `null`.
150-
static final _Future<Null> _nullFuture =
151-
new _Future<Null>.zoneValue(null, _rootZone);
150+
///
151+
/// Currently shared with `dart:internal`.
152+
/// If that future can be removed, then change this back to
153+
/// `_Future<Null>.zoneValue(null, _rootZone);`
154+
static final _Future<Null> _nullFuture = nullFuture as _Future<Null>;
152155

153156
/// A `Future<bool>` completed with `false`.
154157
static final _Future<bool> _falseFuture =

sdk/lib/internal/internal.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,28 @@ int parseHexByte(String source, int index) {
119119
return digit1 * 16 + digit2 - (digit2 & 256);
120120
}
121121

122+
/// A resusable `null`-valued future used by `dart:async`.
123+
///
124+
/// **DO NOT USE.**
125+
///
126+
/// This future is used in situations where a future is expected,
127+
/// but no asynchronous computation actually happens,
128+
/// like cancelling a stream from a controller with no `onCancel` callback.
129+
/// *Some code depends on recognizing this future in order to react
130+
/// synchronously.*
131+
/// It does so to avoid changing event interleaving during the null safety
132+
/// migration where, for example, the [StreamSubscription.cancel] method
133+
/// stopped being able to return `null`.
134+
/// The code that would be broken by such a timing change is fragile,
135+
/// but we are not able to simply change it.
136+
/// For better or worse, code depends on the precise timing that our libraries
137+
/// have so far exhibited.
138+
///
139+
/// This future will be removed again if we can ever do so.
140+
/// Do not use it for anything other than preserving timing
141+
/// during the null safety migration.
142+
final Future<Null> nullFuture = Zone.root.run(() => Future<Null>.value(null));
143+
122144
/// A default hash function used by the platform in various places.
123145
///
124146
/// This is currently the [Jenkins hash function][1] but using masking to keep

0 commit comments

Comments
 (0)