Files
sdk/tests/language/inference_update_2/try_finally_test.dart
Lasse R.H. Nielsen f8086c81ae Collect all test-related files in package:expect.
Collects files from `package:async_helper` and `tests/language`
that are generally useful, so that all test-related helpers are
in `package:expect`.

Moves the two libraries from `package:async_helper` into `package:expect`,
and the `tests/language/static_type_helper.dart` file too.

Deprecates `async_minitest.dart`, to follow `minitest.dart`,
expecting the Flutter use of it to have been fixed to not break
on deprecation (I believe Flutter no longer breaks builds on deprecations at all).

Patch 1 is the actual change.
Patch 2+4+8 is changing all existing references to the files.
Patch 6 ignores deprecation in files still using `async_minitest.dart`.

3+5+7+9 are updating this text to make the numbers match.
Then it's just test-expectations and small tweaks from there.

Change-Id: I1b665135b5fef9b9a0c3b340ffe9daf874d0174c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/373120
Reviewed-by: Nate Bosch <nbosch@google.com>
Reviewed-by: Devon Carew <devoncarew@google.com>
Commit-Queue: Lasse Nielsen <lrn@google.com>
2024-10-11 16:53:52 +00:00

343 lines
11 KiB
Dart

// Copyright (c) 2023, 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.
// Tests interactions between field promotion and try/finally statements.
// In a try/finally statement, the `finally` clause is analyzed as though the
// `try` block hasn't executed yet (and any variables written inside the `try`
// block have been de-promoted), to account for the fact that an exception might
// occur at any time during the `try` block. However, after the `finally` block
// is finished, any flow model changes that occurred during the `finally` block
// are rewound and re-applied to the flow model state after the `try` block, to
// account for the fact that if the try/finally statement completes normally, it
// is known that the `try` block executed fully.
//
// We need to verify that this rebasing logic handles all the possible ways that
// field promotion can occur relative to a try/finally statement.
import 'package:expect/static_type_helper.dart';
class C {
final Object? _o1;
C(this._o1);
}
class D {
final C _c;
final Object? _o2;
D(this._c, this._o2);
}
abstract class E {
C get _c;
Object? get _o3;
}
class F extends E {
final C _c;
final Object? _o3;
F(this._c, this._o3);
}
void promotedInTry(D d) {
try {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d._c._o1!;
d._o2!;
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
} finally {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
}
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
}
void promotedBeforeTryFinally(D d) {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d._c._o1!;
d._o2!;
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
try {
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
} finally {
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
}
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
}
void promotedBeforeTryFinallyAndInTry(D d) {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d._c._o1!;
d._o2!;
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
try {
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
d._c._o1 as int;
d._o2 as int;
d._c._o1.expectStaticType<Exactly<int>>();
d._o2.expectStaticType<Exactly<int>>();
} finally {
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
}
d._c._o1.expectStaticType<Exactly<int>>();
d._o2.expectStaticType<Exactly<int>>();
}
void promotedInBothTryAndFinally_sameType(D d) {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
try {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d._c._o1!;
d._o2!;
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
} finally {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d._c._o1!;
d._o2!;
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
}
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
}
void promotedInBothTryAndFinally_finallyTypeIsSubtype(D d) {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
try {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d._c._o1!;
d._o2!;
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
} finally {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d._c._o1 as int;
d._o2 as int;
d._c._o1.expectStaticType<Exactly<int>>();
d._o2.expectStaticType<Exactly<int>>();
}
d._c._o1.expectStaticType<Exactly<int>>();
d._o2.expectStaticType<Exactly<int>>();
}
void promotedInBothTryAndFinally_finallyTypeIsSupertype(D d) {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
try {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d._c._o1 as int;
d._o2 as int;
d._c._o1.expectStaticType<Exactly<int>>();
d._o2.expectStaticType<Exactly<int>>();
} finally {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d._c._o1!;
d._o2!;
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
}
d._c._o1.expectStaticType<Exactly<int>>();
d._o2.expectStaticType<Exactly<int>>();
}
void promotedInFinally(D d) {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
try {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
} finally {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d._c._o1!;
d._o2!;
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
}
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
}
void promotedBeforeTryFinally_assignedInTry(D d, D d2) {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d._c._o1!;
d._o2!;
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
try {
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
d = d2;
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
} finally {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
}
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
}
void promotedBeforeTryFinally_assignedAndRepromotedInTry(D d, D d2) {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d._c._o1!;
d._o2!;
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
try {
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
d = d2;
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d._c._o1!;
d._o2!;
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
} finally {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
}
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
}
void assignedInTry_promotedInFinally(D d, D d2) {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
try {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d = d2;
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
} finally {
d._c._o1!;
d._o2!;
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
}
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
}
void assignedInTry_promotedInFinally_propertyUnknownInTry(D d, D d2) {
try {
// Note: no calls to `expectStaticType` here, because we want to trigger the
// code path where flow analysis doesn't even know about the property until
// the finally block
d = d2;
} finally {
d._c._o1!;
d._o2!;
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
}
d._c._o1.expectStaticType<Exactly<Object>>();
d._o2.expectStaticType<Exactly<Object>>();
}
void notPromotableInTry_promotedInFinally(E e) {
try {
e._c._o1!;
e._o3!;
e._c._o1.expectStaticType<Exactly<Object>>();
e._o3.expectStaticType<Exactly<Object>>();
} finally {
e as F;
e._c._o1!;
e._o3!;
e._c._o1.expectStaticType<Exactly<Object>>();
e._o3.expectStaticType<Exactly<Object>>();
}
e._c._o1.expectStaticType<Exactly<Object>>();
e._o3.expectStaticType<Exactly<Object>>();
}
void assignedButNotPromotableInTry_promotedInFinally(E e, E e2) {
try {
e = e2;
e._c._o1!;
e._o3!;
e._c._o1.expectStaticType<Exactly<Object>>();
e._o3.expectStaticType<Exactly<Object>>();
} finally {
e as F;
e._c._o1!;
e._o3!;
e._c._o1.expectStaticType<Exactly<Object>>();
e._o3.expectStaticType<Exactly<Object>>();
}
e._c._o1.expectStaticType<Exactly<Object>>();
e._o3.expectStaticType<Exactly<Object>>();
}
void assignedAndPromotedInTry_promotedToSubtypeInFinally(D d, D d2) {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
try {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d = d2;
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d._c._o1 as num;
d._o2 as num;
d._c._o1.expectStaticType<Exactly<num>>();
d._o2.expectStaticType<Exactly<num>>();
} finally {
d._c._o1.expectStaticType<Exactly<Object?>>();
d._o2.expectStaticType<Exactly<Object?>>();
d._c._o1 as int;
d._o2 as int;
d._c._o1.expectStaticType<Exactly<int>>();
d._o2.expectStaticType<Exactly<int>>();
}
d._c._o1.expectStaticType<Exactly<int>>();
d._o2.expectStaticType<Exactly<int>>();
}
main() {
C c = C(1);
D d = D(c, 2);
F f = F(c, 3);
promotedInTry(d);
promotedBeforeTryFinally(d);
promotedBeforeTryFinallyAndInTry(d);
promotedInBothTryAndFinally_sameType(d);
promotedInBothTryAndFinally_finallyTypeIsSubtype(d);
promotedInBothTryAndFinally_finallyTypeIsSupertype(d);
promotedInFinally(d);
promotedBeforeTryFinally_assignedInTry(d, d);
promotedBeforeTryFinally_assignedAndRepromotedInTry(d, d);
assignedInTry_promotedInFinally(d, d);
assignedInTry_promotedInFinally_propertyUnknownInTry(d, d);
notPromotableInTry_promotedInFinally(f);
assignedButNotPromotableInTry_promotedInFinally(f, f);
assignedAndPromotedInTry_promotedToSubtypeInFinally(d, d);
}