Version 2.9.1
* Cherry-pick 27ab7a219ebe816e4c78683bbae82a8fee881531 to stable
* Cherry-pick 7b26f6e29dfea2c7d52a1fb091466d6b71c80c05 to stable
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 725055b..bbd8830 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,11 @@
-## 2.9.0
+## 2.9.1 - 2020-08-12
+
+This is a patch release that fixes unhandled exceptions in some Flutter
+applications (issue [flutter/flutter#63038][]).
+
+[flutter/flutter#63038]: https://github.com/flutter/flutter/issues/63038
+
+## 2.9.0 - 2020-08-05
### Language
diff --git a/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart b/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
index 0251f0c..b56fc6b 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
@@ -522,7 +522,8 @@
statement.expression = inferrer.ensureAssignable(
futureValueType, expressionType, statement.expression,
fileOffset: statement.expression.fileOffset,
- runtimeCheckedType: _returnContext,
+ runtimeCheckedType:
+ inferrer.computeGreatestClosure2(_returnContext),
isVoidAllowed: false)
..parent = statement;
}
@@ -559,7 +560,8 @@
statement.expression,
fileOffset: statement.fileOffset,
isVoidAllowed: true,
- runtimeCheckedType: _returnContext);
+ runtimeCheckedType:
+ inferrer.computeGreatestClosure(_returnContext));
statement.expression = expression..parent = statement;
}
diff --git a/pkg/front_end/testcases/general/issue42615.dart b/pkg/front_end/testcases/general/issue42615.dart
new file mode 100644
index 0000000..b18b51f
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue42615.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+class Class<T> {
+ Class({FutureOr<List<T>> Function() a});
+}
+
+dynamic method() => null;
+
+main() {
+ Class(a: () async => method());
+}
diff --git a/pkg/front_end/testcases/general/issue42615.dart.outline.expect b/pkg/front_end/testcases/general/issue42615.dart.outline.expect
new file mode 100644
index 0000000..77a5b08
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue42615.dart.outline.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+class Class<T extends core::Object* = dynamic> extends core::Object {
+ constructor •({() →* FutureOr<core::List<self::Class::T*>*>* a}) → self::Class<self::Class::T*>*
+ ;
+ abstract member-signature get _identityHashCode() → core::int*;
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+ abstract member-signature operator ==(dynamic other) → core::bool*;
+ abstract member-signature get hashCode() → core::int*;
+ abstract member-signature method toString() → core::String*;
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+ abstract member-signature get runtimeType() → core::Type*;
+}
+static method method() → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/issue42615.dart.strong.expect b/pkg/front_end/testcases/general/issue42615.dart.strong.expect
new file mode 100644
index 0000000..2f569f8
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue42615.dart.strong.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+class Class<T extends core::Object* = dynamic> extends core::Object {
+ constructor •({() →* FutureOr<core::List<self::Class::T*>*>* a = #C1}) → self::Class<self::Class::T*>*
+ : super core::Object::•()
+ ;
+ abstract member-signature get _identityHashCode() → core::int*;
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+ abstract member-signature operator ==(dynamic other) → core::bool*;
+ abstract member-signature get hashCode() → core::int*;
+ abstract member-signature method toString() → core::String*;
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+ abstract member-signature get runtimeType() → core::Type*;
+}
+static method method() → dynamic
+ return null;
+static method main() → dynamic {
+ new self::Class::•<dynamic>(a: () → FutureOr<core::List<dynamic>*>* async => self::method() as{TypeError} FutureOr<core::List<dynamic>*>*);
+}
+
+constants {
+ #C1 = null
+}
diff --git a/pkg/front_end/testcases/general/issue42615.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue42615.dart.strong.transformed.expect
new file mode 100644
index 0000000..6057834
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue42615.dart.strong.transformed.expect
@@ -0,0 +1,57 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+class Class<T extends core::Object* = dynamic> extends core::Object {
+ constructor •({() →* FutureOr<core::List<self::Class::T*>*>* a = #C1}) → self::Class<self::Class::T*>*
+ : super core::Object::•()
+ ;
+ abstract member-signature get _identityHashCode() → core::int*;
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+ abstract member-signature operator ==(dynamic other) → core::bool*;
+ abstract member-signature get hashCode() → core::int*;
+ abstract member-signature method toString() → core::String*;
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+ abstract member-signature get runtimeType() → core::Type*;
+}
+static method method() → dynamic
+ return null;
+static method main() → dynamic {
+ new self::Class::•<dynamic>(a: () → FutureOr<core::List<dynamic>*>* /* originally async */ {
+ final asy::_AsyncAwaitCompleter<core::List<dynamic>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::List<dynamic>*>();
+ FutureOr<core::List<dynamic>*>* :return_value;
+ dynamic :async_stack_trace;
+ (dynamic) →* dynamic :async_op_then;
+ (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L1:
+ {
+ :return_value = self::method() as{TypeError} FutureOr<core::List<dynamic>*>*;
+ break #L1;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+ :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+ return :async_completer.{asy::Completer::future};
+ });
+}
+
+constants {
+ #C1 = null
+}
diff --git a/tools/VERSION b/tools/VERSION
index 7eadffb..e82a19b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -32,7 +32,7 @@
CHANNEL stable
MAJOR 2
MINOR 9
-PATCH 0
+PATCH 1
PRERELEASE 0
PRERELEASE_PATCH 0
ABI_VERSION 38