| // 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. | |
| // Verifies that when there is a control flow join implied by a pattern, the | |
| // split point is the beginning of the top level pattern. | |
| import 'package:expect/static_type_helper.dart'; | |
| void guarded(int Function(Object) f, int? i) { | |
| if (f(throw '') case int() when i == null) { | |
| } else { | |
| // There is a join point here, joining the flow control paths where (a) the | |
| // pattern `int()` failed to match and (b) the guard `i == null` was not | |
| // satisfied. Since the scrutinee has type `int`, and the pattern is | |
| // `int()`, the pattern is guaranteed to match, so path (a) is | |
| // unreachable. Path (b) is also unreachable due to the fact that the | |
| // scrutinee throws, but since the split point is the beginning of the | |
| // pattern, path (b) is reachable from the split point. So the promotion | |
| // implied by (b) is preserved after the join. | |
| i.expectStaticType<Exactly<int>>(); | |
| } | |
| } | |
| void logicalOr((Null, Null, int?) x) { | |
| if (x | |
| case ((!= null, _, _) | |
| // At this point, control flow is unreachable due to the fact that | |
| // the `!= null` pattern in the first field of the record pattern | |
| // above can never match the type `Null`. | |
| && | |
| ((_, != null, _) | |
| // At this point, control flow is unreachable for a second | |
| // reason: because the `!= null` pattern in the second field | |
| // of the record pattern above can never match the type | |
| // `Null`. | |
| || | |
| (_, _, _?) | |
| // At this point, the third field of the scrutinee is promoted | |
| // from `int?` to `int`, due to the null check pattern. | |
| ) | |
| // At this point, there is a control flow join between the two | |
| // branches of the logical-or pattern. Since the split point | |
| // corresponding to the control flow join is at the beginning of the | |
| // top level pattern, both branches are considered unreachable, so | |
| // neither is favored in the join, and therefore, the promotion from | |
| // the second branch is lost. | |
| ) && | |
| // The record pattern below matches `x` to the unpromoted type of the | |
| // third field of the scrutinee, so we just have to verify that it has | |
| // the expected type of `int?`. | |
| (_, _, var y)) { | |
| y.expectStaticType<Exactly<int?>>(); | |
| } | |
| } | |
| main() {} |