@@ -6060,11 +6060,64 @@ class KernelSsaGraphBuilder extends ir.Visitor<void> with ir.VisitorVoidMixin {
6060
6060
6061
6061
@override
6062
6062
void visitAwaitExpression (ir.AwaitExpression node) {
6063
- node.operand.accept (this );
6063
+ // `await e` first checks if the runtime type of `e` is a subtype of
6064
+ // `Future<T>` where `T = flatten(S)` and `S` is the static type of `e`.
6065
+ // (The type `Future<T>` is helpfully precomputed by the CFE and stored in
6066
+ // [AwaitExpression.runtimeCheckType].)
6067
+ //
6068
+ // If the check succeeds (or if no `runtimeCheckType` is provided), we await
6069
+ // `e` directly.
6070
+ //
6071
+ // If the check fails, we must await `Future.value(e)` instead.
6072
+ //
6073
+ // See https://github.com/dart-lang/sdk/issues/49396 for details.
6074
+
6075
+ final operand = node.operand;
6076
+ operand.accept (this );
6064
6077
HInstruction awaited = pop ();
6065
- // TODO(herhut): Improve this type.
6066
- push (HAwait (awaited, _abstractValueDomain.dynamicType)
6067
- ..sourceInformation = _sourceInformationBuilder.buildAwait (node));
6078
+ final runtimeCheckType = node.runtimeCheckType;
6079
+ final sourceInformation = _sourceInformationBuilder.buildAwait (node);
6080
+
6081
+ void checkType () {
6082
+ // TODO(fishythefish): Can we get rid of the redundancy with the type
6083
+ // checks in async_patch?
6084
+ _pushIsTest (runtimeCheckType! , awaited, sourceInformation);
6085
+ }
6086
+
6087
+ void pushAwait (HInstruction expression) {
6088
+ // TODO(herhut): Improve this type.
6089
+ push (HAwait (expression, _abstractValueDomain.dynamicType)
6090
+ ..sourceInformation = sourceInformation);
6091
+ }
6092
+
6093
+ void awaitUnwrapped () {
6094
+ pushAwait (awaited);
6095
+ }
6096
+
6097
+ void awaitWrapped () {
6098
+ final constructor = _commonElements.futureValueConstructor! ;
6099
+ final arguments = [awaited];
6100
+ // If [runtimeCheckType] exists, it is guaranteed to be `Future<T>`, and
6101
+ // we want to call `Future<T>.value`.
6102
+ final typeArgument = _elementMap.getDartType (
6103
+ (runtimeCheckType as ir.InterfaceType ).typeArguments.single);
6104
+ final typeArguments = [typeArgument];
6105
+ _addTypeArguments (arguments, typeArguments, sourceInformation);
6106
+ final instanceType = _commonElements.futureType (typeArgument);
6107
+ _addImplicitInstantiation (instanceType);
6108
+ _pushStaticInvocation (constructor, arguments,
6109
+ _typeInferenceMap.getReturnTypeOf (constructor), typeArguments,
6110
+ sourceInformation: sourceInformation, instanceType: instanceType);
6111
+ _removeImplicitInstantiation (instanceType);
6112
+ pushAwait (pop ());
6113
+ }
6114
+
6115
+ if (runtimeCheckType == null ) {
6116
+ awaitUnwrapped ();
6117
+ } else {
6118
+ SsaBranchBuilder (this )
6119
+ .handleConditional (checkType, awaitUnwrapped, awaitWrapped);
6120
+ }
6068
6121
}
6069
6122
6070
6123
@override
0 commit comments