Commit Graph

11 Commits

Author SHA1 Message Date
Chloe Stefantsova 617d0a8e96 [model] Remove more nullability-related assignability error messages
This is a preparation for removing the subtype checking procedure that
ignores the nullability in the input types.

Change-Id: I3c1db55abde0433e9059d949f1c98aaeb61e210c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/428980
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Erik Ernst <eernst@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
2025-05-19 00:18:57 -07:00
Paul Berry a757d2af41 Enable sound-flow-analysis for Dart 3.9.
Bug: https://github.com/dart-lang/sdk/issues/60438
Change-Id: I908d4e4a9143142281d8198870f40eba6cf6f67f
Tested: trybots
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/427500
Reviewed-by: Ivan Inozemtsev <iinozemtsev@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Morgan :) <davidmorgan@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
2025-05-09 14:50:26 -07:00
Robert Nystrom 159de518e2 Reformat tests/language/m-p using the 3.8 style.
Change-Id: I28f61e1e85408acc5403bfe95f360df4c7cb5ece
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/425151
Auto-Submit: Bob Nystrom <rnystrom@google.com>
Reviewed-by: Lasse Nielsen <lrn@google.com>
Commit-Queue: Lasse Nielsen <lrn@google.com>
2025-04-29 07:30:40 -07:00
Robert Nystrom dbaf041ae4 Format tests/language/p*.
Change-Id: Ia3238c1781422ec5eb7a219a5cf8af645a4c5876
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/409000
Commit-Queue: Bob Nystrom <rnystrom@google.com>
Reviewed-by: Lasse Nielsen <lrn@google.com>
Auto-Submit: Bob Nystrom <rnystrom@google.com>
2025-02-11 15:31:25 -08:00
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
Paul Berry 7f5a698514 UNREACHABLE_SWITCH_CASE: Remove HintCode in favor of WarningCode.
Previously, `HintCode.UNREACHABLE_SWITCH_CASE` was marked as
deprecated, and `WarningCode.UNREACHABLE_SWITCH_CASE` was an alias to
it. This created a slightly confusing situation, because it meant that
all code referring to the diagnostic had to refer to it as
`WarningCode.UNREACHABLE_SWITCH_CASE` (to avoid a deprecation lint),
but the diagnostic still _behaved_ like it was a hint, and therefore
test runner expectations still had to treat it as a hint.

It turns out that it's not really necessary to go through the
deprecation dance when changing the kind of a diagnostic, since (a)
members of `HintCode` and `WarningCode` aren't exposed through the
analyzer public API, and (b) ignore comments don't have to specify
whether something is a hint or a warning.

So the easiest way to clear up the confusion is to just remove
`HintCode.UNREACHABLE_SWITCH_CASE` entirely, and move its implemention
into `WarningCode.UNREACHABLE_SWITCH_CASE` (so that the latter is no
longer an alias).

Change-Id: I9ff7901ad38a2c168c5e54cbe0c1c52bf7c50186
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/381103
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2024-08-19 16:09:14 +00:00
Paul Berry b026068313 Flow analysis: fix handling of list pattern type promotion.
When analyzing the type test implied by a pattern, flow analysis uses
three variables to control promotion behavior:

- `matchFailsIfWrongType`, which indicates whether flow analysis needs
  to account for the possible control flow path resulting from the
  type test failing. (This is `false` for cast patterns, because in
  the case where a cast pattern fails, an exception is thrown).

- `matchMayFailEvenIfCorrectType`, which indicates whether flow
  analysis needs to account for the possible control flow path
  resulting from the type test succeeding, but some other check
  causing the match to fail. (This is `true` for most list patterns,
  because the list pattern will fail to match if the list has the
  wrong length).

  (Note that `matchMayFailEvenIfCorrectType` doesn't account for the
  fact that a pattern match might fail due to failure in a subpattern
  match; this is automatically handled by the fact that flow analysis
  walks through the complete pattern in the order in which it
  executes.)

- `coversMatchedType`, which indicates whether the type test is
  guaranteed to succeed due to a subtype relationship between the
  matched value type and the type being tested (e.g. a `num x` pattern
  is guaranteed to succeed if the matched value type is `int`).

In the case where `matchFailsIfWrongType` is `true`,
`matchMayFailEvenIfCorrectType` is `true`, and `coversMatchedType` is
`false`, flow analysis must account for the fact that there are two
ways that the pattern match might fail: the type test might fail, or
the type test might succeed but then the pattern match might fail for
some other reason.

Before this change, this was done incorrectly, and flow analysis only
accounted for the possibility of the type test failing.

Fixes #55543.

Bug: https://github.com/dart-lang/sdk/issues/55543
Change-Id: I86603ec5f940402313f32177212b7960878db97f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/364942
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2024-05-01 17:12:00 +00:00
Paul Berry 907e705307 Flow analysis: use a more precise split point for refutable patterns.
Previously, the flow control logic for patterns didn't use the
`FlowModel.split` or `FlowModel.unsplit` methods at all. This meant
that if a control flow join point occurred in pattern logic, flow
analysis would consider the split point to be whatever split point was
established by the enclosing expression or statement. In the case of
an if-case statement, it would consider the split point to be at the
beginning of the scrutinee expression.

Split points are used by flow analysis for the sole purpose of
ensuring that joins propagate type promotions the same way in dead
code as they do in live code (so that users introducing temporary
`throw` expressions or `return` statements into their code do not have
to deal with nuisance compile errors in the (now dead) code that
follows. The consequence of flow analysis considering the split point
to be at the beginning of the scrutinee expression is that if the
scrutinee expression is proven to always throw, then joins that arise
from the pattern or guard may not behave consistently with how they
would have behaved otherwise. For example:

    int getInt(Object o) => ...;
    void consumeInt(int i) { ... }
    test(int? i) {
      if (
          // (1)
          getInt('foo')
          case
              // (2)
              int()
          // (3)
          when i == null) {
      } else {
        // (4)
        consumeInt(i);
      }
    }

In the above code, there is a join point at (4), joining control flows
from (a) the situation where the pattern `int()` failed to match, and
(b) the situation where `i == null` evaluated to `false` (and hence
`i` is promoted to non-nullable `int`). Since the return type of
`getInt` is `int`, it's impossible for the pattern `int()` to fail, so
at the join point, control flow path (a) is considered
unreacable. Therefore the promotion from control flow path (b) is
kept, and so the call to `consumeInt` is valid.

In order to decide whether to preserve promotions from one of the
control flow paths leading up to a join, flow analysis only considers
reachability relative to the corresponding split point. Prior to this
change, the split point in question occurred at (1), so if the
expression `getInt('foo')` had been replaced with `getInt(throw
UnimplementedError())`, flow analysis would have considered both
control flow paths (a) and (b) to be unreachable relative to the split
point, so it would not have preserved the promotion from (b), and
there would have been a compile time error in the (now dead) call to
`consumeInt`.

This change moves the split point from (1) to (2), so that changing
`getInt('foo')` to `getInt(throw UnimplementedError())` no longer
causes any change in type promotion behavior.

The implementation of this change is to add calls to `FlowModel.split`
and `FlowModel.unsplit` around all top-level patterns. At first glance
this might appear to affect the behavior of all patterns, but actually
the only user-visible effect is on patterns in if-case statements,
because:

- In switch statements and switch expressions, there is already a
  split point before each case.

- In irrefutable patterns, there is no user-visible effect, because
  irrefutable patterns cannot fail to match, and therefore don't do
  any control flow joins.

This change allows the split points for patterns to be determined by a
simple syntactic rule, which will facilitate some refactoring of split
points that I am currently working on.

Change-Id: I55573ba5c28b2f2e6bba8731f9e3b02613b6beb2
Bug: https://github.com/dart-lang/sdk/issues/53167
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/319381
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2023-08-11 17:09:49 +00:00
Paul Berry 2ca7380ab0 Flow analysis: fix first phase handling of pattern assignments.
Prior to this change, the first phase of flow analysis, in which flow
analysis "looks ahead" to see which variables are potentially assigned
in each code block, was failing to properly account for variables that
are assigned by pattern assignment expressions. This "look ahead"
information is used by flow analysis to determine the effects of
nonlinear control flow (e.g. to figure out which variables to demote
at the top of a loop, or to figure out which variables are potentially
assigned inside a closure). As a result, it was possible to construct
correct code that would be rejected by the analyzer and compiler, as
well as incorrect code that would (unsoundly) be accepted.

The fix is to call `AssignedVariables.write` from the analyzer's
`FlowAnalysisVisitor`, and from the CFE's `BodyBuilder`, to let flow
analysis know about variable assignments that occur inside pattern
assignment expressions.

Fixes #52745.

Change-Id: I0e6f426a5c5c36f214d5a206aaf5a2de0bfdaac1
Bug: https://github.com/dart-lang/sdk/issues/52745
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/310502
Auto-Submit: Paul Berry <paulberry@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
2023-06-21 14:33:42 +00:00
Paul Berry 9bfae1a720 Initial language tests for patterns flow analysis.
These tests are based on the unit tests I wrote during development of
the flow analysis support for patterns; as such, they are not
especially uniform in their coverage, but they should be a good
start. I intend to expand coverage in future CLs.

Bug: https://github.com/dart-lang/sdk/issues/50419
Change-Id: I23bd96621a0269c1e642a7fa3b65c851357505c3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/304320
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Bob Nystrom <rnystrom@google.com>
2023-05-19 18:20:28 +00:00
Paul Berry cb0eb28cba Account for differing flow analysis conventions between CFE and shared code.
With one exception (noted below), the shared analysis logic uses the
convention that the expressions passed to flow analysis are the
original (pre-lowered) expressions, whereas the expressions passed to
flow analysis by the CFE are the lowered expressions. This difference
caused two problems:

- If a boolean expression appeared on the right hand side of a pattern
  assignment or pattern variable declaration, and it was lowered, the
  flow analysis implications of that boolean expression would be lost.

- If a boolean expression appeared in a `when` clause, and it was
  lowered, the flow analysis implications of that boolean expression
  would be lost. Exception: for switch statements, the shared analysis
  logic has been passing lowered expressions to flow analysis, so this
  problem didn't occur for `when` clauses in switch statements.

Notably, when compiling for the VM, the CFE lowers expressions like
`x != null` to something more like `!(x == null)`.

Fortunately, the first of these two situations shouldn't cause
problems very often, since typically if the right hand side of an
assignment or variable declaration is a boolean expression, there is
no need for the left hand side to involve patterns.

As for the second of these two situations, it's also not too likely to
cause problems, since typically null checks occur inside patterns
rather than in `when` clauses.

As a short term fix, we remove the exception noted above, and we
account for the difference in conventions by adding a call to
`FlowAnalysis.forwardExpression` to the CFE's implementation of
`dispatchExpression`, so that when transitioning between CFE logic and
shared logic, flow analysis will be informed how to match up the
lowered expressions to their pre-lowered counterparts.

Longer term, I would like to switch everything to the convention of
using the original (pre-lowered) expressions; this will bring the
analyzer and CFE into better alignment with each other and should
eliminate a class of subtle bugs. This long term goal is tracked in
https://github.com/dart-lang/sdk/issues/52189.

Fixes #52183.
Fixes #52241.

Bug: https://github.com/dart-lang/sdk/issues/52183, https://github.com/dart-lang/sdk/issues/52241.
Change-Id: I2449ce34c54325603bc2730d1660a7cfc7d79aec
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/298840
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2023-05-10 19:31:19 +00:00