Files
sdk/pkg/_fe_analyzer_shared
Paul Berry 68c974e25e [flow analysis] Add handleReturn to model returns from anonymous methods.
Prior to the introduction of the "anonymous methods" experiment, a
`return` statement and a `throw` expression behaved identically from
the point of view of flow analysis, since both had the effect of
causing control flow to jump outside the function that flow analysis
is analyzing*. So they were both implemented using a single flow
analysis method called `handleExit`.

(*Technically a `return` from an inner function could lead to a point
in an enclosing function, and a `throw` could lead to a `catch`, but
flow analysis handles both of these possibilities using a conservative
approximation (see the `FlowModel.conservativeJoin` method), rather
than modeling them as direct jumps.

But a `return` statement inside a block-bodied anonymous method is
known to jump directly to the code that follows the anonymous method
invocation, so `handleExit` is not the correct way to model it.

Prior to this CL, this was handled in the analyzer's resolver (the
corresponding CFE logic hasn't been written yet) by treating anonymous
methods as a kind of loop construct. When visiting a return statement,
the resolver would find the innermost enclosing function expression,
local function, or block-bodied anonymous method; if it was a
block-bodied anonymous method, then it would achieve the desired
effect by calling `FlowAnalysis.handleBreak` rather than
`FlowAnalysis.handleExit`. This was an abstraction leak, because in
effect it put some of the business logic of flow analysis in its
client (namely, the knowledge that return statements in block-bodied
anonymous methods have a different flow analysis behavior than return
statements elsewhere).

This CL moves this business logic into flow analysis through the
addition of a `FlowAnalysis.handleReturn` method.

Flow analysis keeps track of whether the current point in the code
being analyzed is inside a block-bodied anonymous method using the new
field `FlowAnalysis._anonymousBlockContext`, which points to either
`null` or an instance of a new type, `_AnonymousBlockContext`. This
field is updated in proper nesting fashion by the methods:

- `anonymousBlockBody_begin`
- `anonymousBlockBody_end`
- `_functionExpression_begin`
- `_functionExpression_end`

Finally, some aspects of
https://dart-review.googlesource.com/c/sdk/+/482786 that are no longer
necessary are rolled back:

- A node no longer needs to be passed to `anonymousBlockBody_begin`.

- The mapping from nodes to branch targets is changed back to a
  mapping from statements to branch targets, since it no longer needs
  to accept an anonymous method invocation as a key.

Change-Id: I8b0f35cab016fc5bd609cfa1581ecaa36a6a6964
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/485020
Reviewed-by: Erik Ernst <eernst@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2026-03-13 10:54:31 -07:00
..
2025-02-19 09:33:31 -08:00

FE/analyzer shared code

This package contains logic that is shared between the front_end and analyzer packages. It is intended solely to facilitate development of the Dart SDK, and is not intended for use by end users. In particular, this package has no public API, so no guarantee is made of compatibility between one version of the package and the next.

End users should consider using the analyzer package to analyze Dart source code.