Ensure that assert statements promote properly in unreachable code.
Fixes #40009.
Bug: https://github.com/dart-lang/sdk/issues/40009
Change-Id: I96561a72b6ba8dd8b8b95a4d9827d195941ea038
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166760
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index fad64cc..f809b87 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -2729,6 +2729,7 @@
@override
void assert_begin() {
+ _current = _current.split();
_stack.add(new _AssertContext<Variable, Type>(_current));
}
@@ -2736,7 +2737,7 @@
void assert_end() {
_AssertContext<Variable, Type> context =
_stack.removeLast() as _AssertContext<Variable, Type>;
- _current = _join(context._previous, context._conditionInfo.ifTrue);
+ _current = _merge(context._previous, context._conditionInfo.ifTrue);
}
@override
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/promotion_in_dead_code.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/promotion_in_dead_code.dart
index 354b5bf..21f9263 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/promotion_in_dead_code.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/promotion_in_dead_code.dart
@@ -40,6 +40,64 @@
}
}
+assertAlwaysThrows(Object o, Object p, bool Function(Object, Object) f) {
+ if (o is! int) return;
+ return;
+ assert(f(o = p, throw 'x'));
+ /*int*/ o;
+}
+
+class AssertAlwaysThrows_Constructor {
+ Object a;
+ Object b;
+
+ AssertAlwaysThrows_Constructor(
+ Object o, Object p, bool Function(Object, Object) f)
+ : a = o is int ? true : throw 'x',
+ b = throw 'x',
+ assert(f(o = p, throw 'x')) {
+ /*int*/ o;
+ }
+}
+
+assertFailsButMessageRepromotes(Object? o) {
+ if (o is! int) return;
+ return;
+ assert((o = null) != null, o is int ? 'ok' : throw 'x');
+ /*int*/ o;
+}
+
+class AssertFailsButMessageRepromotes_Constructor {
+ Object a;
+ Object b;
+
+ AssertFailsButMessageRepromotes_Constructor(Object? o)
+ : a = o is int ? true : throw 'x',
+ b = throw 'x',
+ assert((o = null) != null, o is int ? 'ok' : throw 'x') {
+ /*int*/ o;
+ }
+}
+
+assertMessageDepromotesButAlwaysThrows(Object o, Object p, bool b) {
+ if (o is! int) return;
+ return;
+ assert(b, throw (o = p));
+ /*int*/ o;
+}
+
+class AssertMessageDepromotesButAlwaysThrows {
+ Object a;
+ Object b;
+
+ AssertMessageDepromotesButAlwaysThrows(Object o, Object p, bool b)
+ : a = o is int ? true : throw 'x',
+ b = throw 'x',
+ assert(b, throw (o = p)) {
+ /*int*/ o;
+ }
+}
+
conditionalIs(Object o) {
return;
o is int ? null : throw 'bad';