[XL] Change in dart/sdk[main]: Take steps to support anonymous block bodies

0 views
Skip to first unread message

Erik Ernst (Gerrit)

unread,
Mar 2, 2026, 10:52:27 AMMar 2
to Paul Berry, Commit Queue, dart-analys...@google.com, rev...@dartlang.org
Attention needed from Paul Berry

Erik Ernst added 1 comment

Patchset-level comments
File-level comment, Patchset 9 (Latest):
Erik Ernst . resolved

The tests `$SDK/tests/language/anonymous_methods/block/*_test.dart` are now accepted by the analyzer.

Open in Gerrit

Related details

Attention is currently required from:
  • Paul Berry
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: I04bc3c852611dbefb885afce655dc00054709fb7
Gerrit-Change-Number: 482786
Gerrit-PatchSet: 9
Gerrit-Owner: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Paul Berry <paul...@google.com>
Gerrit-Attention: Paul Berry <paul...@google.com>
Gerrit-Comment-Date: Mon, 02 Mar 2026 15:52:23 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
unsatisfied_requirement
open
diffy

Paul Berry (Gerrit)

unread,
Mar 2, 2026, 5:04:38 PMMar 2
to Erik Ernst, Commit Queue, dart-analys...@google.com, rev...@dartlang.org
Attention needed from Erik Ernst

Paul Berry added 3 comments

File pkg/analyzer/lib/src/generated/error_verifier.dart
Line 125, Patchset 9 (Latest): final TypeImpl? _returnType;
Paul Berry . unresolved

It took me a while to figure out what this is for.

I *think* what it's for is to allow `ErrorVerifier.visitAnonymousMethodInvocation` to override the standard behavior of the `returnType` getter (which is to look up the return type in the element), because I guess anonymous method invocations don't have an associated element?

But if they don't have elements, why not? Our usual rule is that something needs to be an element if you can refer to it by name, OR if it's needed as the parent element to something you *can* refer to by name. If an anonymous method has a parameter, then that parameter must have a parameter element, and that parameter element should have a parent which is the anonymous method element, right?

Assuming that's true (that anonymous methods *do* have elements), then you shouldn't have to modify `EnclosingExecutableContext` at all; you should just be able to pass in the correct element when you call the constructor.

Line 401, Patchset 9 (Latest): var returnType =
Paul Berry . unresolved

This seems wrong to me for a couple of reasons:

1. Converting a context type to a type is not safe, because a context type can have holes in it (e.g., the context might be `List<_>`).

2. The return type of the anonymous method should have been determined precisely (using type inference) by the resolver, so using the context type is not necessarily incorrect; the resolver might have chosen a different type based on the types appearing in `return` statements in the body.

File pkg/analyzer/lib/src/generated/resolver.dart
Line 4072, Patchset 9 (Latest): flowAnalysis.flow?.handleBreak(enclosingBody);
Paul Berry . unresolved

Please add a comment:
```
// TODO(paulberry): add a `FlowAnalysis.handleReturn` method so that the resolver
// doesn't have to pretend that this is a break statement in order to get correct
// behavior.
```

I will address this in a follow-up CL.

Open in Gerrit

Related details

Attention is currently required from:
  • Erik Ernst
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: I04bc3c852611dbefb885afce655dc00054709fb7
Gerrit-Change-Number: 482786
Gerrit-PatchSet: 9
Gerrit-Owner: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Paul Berry <paul...@google.com>
Gerrit-Attention: Erik Ernst <eer...@google.com>
Gerrit-Comment-Date: Mon, 02 Mar 2026 22:04:35 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
unsatisfied_requirement
open
diffy

Erik Ernst (Gerrit)

unread,
Mar 3, 2026, 12:45:54 PMMar 3
to Paul Berry, Commit Queue, dart-analys...@google.com, rev...@dartlang.org
Attention needed from Paul Berry

Erik Ernst added 4 comments

Patchset-level comments
Erik Ernst . resolved

PTAL - I made the requested changes as far as possible (for me, at this time ;-), and I need some more help in order to know that I'm going in the right direction.

File pkg/analyzer/lib/src/generated/error_verifier.dart
Line 125, Patchset 9 (Latest): final TypeImpl? _returnType;
Paul Berry . unresolved

It took me a while to figure out what this is for.

I *think* what it's for is to allow `ErrorVerifier.visitAnonymousMethodInvocation` to override the standard behavior of the `returnType` getter (which is to look up the return type in the element), because I guess anonymous method invocations don't have an associated element?

But if they don't have elements, why not? Our usual rule is that something needs to be an element if you can refer to it by name, OR if it's needed as the parent element to something you *can* refer to by name. If an anonymous method has a parameter, then that parameter must have a parameter element, and that parameter element should have a parent which is the anonymous method element, right?

Assuming that's true (that anonymous methods *do* have elements), then you shouldn't have to modify `EnclosingExecutableContext` at all; you should just be able to pass in the correct element when you call the constructor.

Erik Ernst

In an earlier iteration of this work I did create a new kind of element to represent the anonymous method. However, this caused several other requirements to arise: About 45 element visitors were suddenly broken, and there was a need to introduce a fragment to deliver from `declaredFragment`, and various other stuff that I don't remember in full detail.

I think we might have discussed this, but in any case I tried to get by without a new element class, thinking that it would be sufficient for the anonymous method to have a kind of element which is minimal by reusing an existing `...Element` class. In the end it should presumably just be a node in the tree such that there is no unexpected null value in a `parent`, and hopefully the formal parameter element doesn't really need any services from it.

However, I went back to this strategy and introduced a few private classes in error_verifier.dart starting from line 204. It just takes a couple of steps (and each step makes it stop with a new member which should have been there).

Could you give me a hint about a systematic method to discover how to build this connected graph of classes and objects that are needed in order to introduce a new kind of element?

Paul Berry . resolved

This seems wrong to me for a couple of reasons:

1. Converting a context type to a type is not safe, because a context type can have holes in it (e.g., the context might be `List<_>`).

2. The return type of the anonymous method should have been determined precisely (using type inference) by the resolver, so using the context type is not necessarily incorrect; the resolver might have chosen a different type based on the types appearing in `return` statements in the body.

Erik Ernst

Right, the correct return type is actually available from the enclosing `AnonymousMethodInvocationImpl.staticType`. I'll close this thread because the previous comment carries the required information about what is not yet done in the appropriate manner.

File pkg/analyzer/lib/src/generated/resolver.dart
Line 4072, Patchset 9 (Latest): flowAnalysis.flow?.handleBreak(enclosingBody);
Paul Berry . resolved

Please add a comment:
```
// TODO(paulberry): add a `FlowAnalysis.handleReturn` method so that the resolver
// doesn't have to pretend that this is a break statement in order to get correct
// behavior.
```

I will address this in a follow-up CL.

Erik Ernst

Done

Open in Gerrit

Related details

Attention is currently required from:
  • Paul Berry
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: I04bc3c852611dbefb885afce655dc00054709fb7
Gerrit-Change-Number: 482786
Gerrit-PatchSet: 9
Gerrit-Owner: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Paul Berry <paul...@google.com>
Gerrit-Attention: Paul Berry <paul...@google.com>
Gerrit-Comment-Date: Tue, 03 Mar 2026 17:45:47 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Paul Berry <paul...@google.com>
unsatisfied_requirement
open
diffy

Paul Berry (Gerrit)

unread,
Mar 3, 2026, 5:08:38 PMMar 3
to Erik Ernst, Konstantin Shcheglov, Commit Queue, dart-analys...@google.com, rev...@dartlang.org
Attention needed from Erik Ernst and Konstantin Shcheglov

Paul Berry added 1 comment

Patchset-level comments
File-level comment, Patchset 10 (Latest):
Paul Berry . resolved

Adding Konstantin for context. We are currently discussing what we want the element model to look like.

Open in Gerrit

Related details

Attention is currently required from:
  • Erik Ernst
  • Konstantin Shcheglov
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: I04bc3c852611dbefb885afce655dc00054709fb7
Gerrit-Change-Number: 482786
Gerrit-PatchSet: 10
Gerrit-Owner: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Konstantin Shcheglov <sche...@google.com>
Gerrit-Reviewer: Paul Berry <paul...@google.com>
Gerrit-Attention: Erik Ernst <eer...@google.com>
Gerrit-Attention: Konstantin Shcheglov <sche...@google.com>
Gerrit-Comment-Date: Tue, 03 Mar 2026 22:08:35 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
unsatisfied_requirement
open
diffy

Konstantin Shcheglov (Gerrit)

unread,
Mar 3, 2026, 5:25:21 PMMar 3
to Erik Ernst, Paul Berry, Commit Queue, dart-analys...@google.com, rev...@dartlang.org
Attention needed from Erik Ernst

Konstantin Shcheglov added 1 comment

File pkg/analyzer/lib/src/generated/error_verifier.dart
Line 125, Patchset 9: final TypeImpl? _returnType;
Paul Berry . unresolved

It took me a while to figure out what this is for.

I *think* what it's for is to allow `ErrorVerifier.visitAnonymousMethodInvocation` to override the standard behavior of the `returnType` getter (which is to look up the return type in the element), because I guess anonymous method invocations don't have an associated element?

But if they don't have elements, why not? Our usual rule is that something needs to be an element if you can refer to it by name, OR if it's needed as the parent element to something you *can* refer to by name. If an anonymous method has a parameter, then that parameter must have a parameter element, and that parameter element should have a parent which is the anonymous method element, right?

Assuming that's true (that anonymous methods *do* have elements), then you shouldn't have to modify `EnclosingExecutableContext` at all; you should just be able to pass in the correct element when you call the constructor.

Erik Ernst

In an earlier iteration of this work I did create a new kind of element to represent the anonymous method. However, this caused several other requirements to arise: About 45 element visitors were suddenly broken, and there was a need to introduce a fragment to deliver from `declaredFragment`, and various other stuff that I don't remember in full detail.

I think we might have discussed this, but in any case I tried to get by without a new element class, thinking that it would be sufficient for the anonymous method to have a kind of element which is minimal by reusing an existing `...Element` class. In the end it should presumably just be a node in the tree such that there is no unexpected null value in a `parent`, and hopefully the formal parameter element doesn't really need any services from it.

However, I went back to this strategy and introduced a few private classes in error_verifier.dart starting from line 204. It just takes a couple of steps (and each step makes it stop with a new member which should have been there).

Could you give me a hint about a systematic method to discover how to build this connected graph of classes and objects that are needed in order to introduce a new kind of element?

Konstantin Shcheglov
See how we build fragments and elements in `ElementBindingVisitor`, specifically `visitFunctionExpression`. Note that we create `LocalFunctionFragmentImpl` and then use it to wrap as enclosingFragment typeParameters and formalParameters.
```
var holder = ElementHolder(fragment);
_withElementHolder(holder, () {
super.visitFunctionExpression(node);
fragment.typeParameters = holder.typeParameters;
fragment.formalParameters = holder.formalParameters;
});
```

I think there is a lot of similarities with anonymous methods.

Open in Gerrit

Related details

Attention is currently required from:
  • Erik Ernst
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: I04bc3c852611dbefb885afce655dc00054709fb7
Gerrit-Change-Number: 482786
Gerrit-PatchSet: 10
Gerrit-Owner: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Konstantin Shcheglov <sche...@google.com>
Gerrit-Reviewer: Paul Berry <paul...@google.com>
Gerrit-Attention: Erik Ernst <eer...@google.com>
Gerrit-Comment-Date: Tue, 03 Mar 2026 22:25:17 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Paul Berry <paul...@google.com>
Comment-In-Reply-To: Erik Ernst <eer...@google.com>
unsatisfied_requirement
open
diffy

Konstantin Shcheglov (Gerrit)

unread,
Mar 3, 2026, 5:51:08 PMMar 3
to Erik Ernst, Paul Berry, Commit Queue, dart-analys...@google.com, rev...@dartlang.org
Attention needed from Erik Ernst

Konstantin Shcheglov added 1 comment

File pkg/analyzer/lib/src/generated/error_verifier.dart
Line 125, Patchset 9: final TypeImpl? _returnType;
Paul Berry . unresolved

It took me a while to figure out what this is for.

I *think* what it's for is to allow `ErrorVerifier.visitAnonymousMethodInvocation` to override the standard behavior of the `returnType` getter (which is to look up the return type in the element), because I guess anonymous method invocations don't have an associated element?

But if they don't have elements, why not? Our usual rule is that something needs to be an element if you can refer to it by name, OR if it's needed as the parent element to something you *can* refer to by name. If an anonymous method has a parameter, then that parameter must have a parameter element, and that parameter element should have a parent which is the anonymous method element, right?

Assuming that's true (that anonymous methods *do* have elements), then you shouldn't have to modify `EnclosingExecutableContext` at all; you should just be able to pass in the correct element when you call the constructor.

Erik Ernst

In an earlier iteration of this work I did create a new kind of element to represent the anonymous method. However, this caused several other requirements to arise: About 45 element visitors were suddenly broken, and there was a need to introduce a fragment to deliver from `declaredFragment`, and various other stuff that I don't remember in full detail.

I think we might have discussed this, but in any case I tried to get by without a new element class, thinking that it would be sufficient for the anonymous method to have a kind of element which is minimal by reusing an existing `...Element` class. In the end it should presumably just be a node in the tree such that there is no unexpected null value in a `parent`, and hopefully the formal parameter element doesn't really need any services from it.

However, I went back to this strategy and introduced a few private classes in error_verifier.dart starting from line 204. It just takes a couple of steps (and each step makes it stop with a new member which should have been there).

Could you give me a hint about a systematic method to discover how to build this connected graph of classes and objects that are needed in order to introduce a new kind of element?

Konstantin Shcheglov
See how we build fragments and elements in `ElementBindingVisitor`, specifically `visitFunctionExpression`. Note that we create `LocalFunctionFragmentImpl` and then use it to wrap as enclosingFragment typeParameters and formalParameters.
```
var holder = ElementHolder(fragment);
_withElementHolder(holder, () {
super.visitFunctionExpression(node);
fragment.typeParameters = holder.typeParameters;
fragment.formalParameters = holder.formalParameters;
});
```

I think there is a lot of similarities with anonymous methods.

Konstantin Shcheglov

You will need to add `LocalFunctionFragmentImpl declaredFragment` to `AnonymousMethodInvocation`. Which sounds unusual, as now invocation has its own declaration. I see the comment describes it in terms of `AnonymousMethod`, which would be more natural place for `declaredFragment` IMHO. But maybe it is just unusual to me.

FYI, we consider splitting `LocalFunctionElement` into `LocalExecutableElement` superclass with leaf subclasses `LocalFunctionElement` proper, `FunctionExpressionElement`, and `AnonymousMethodElement`. This will align elements with syntax, which sometimes is useful. Nothing for you to do here, for now we will continue using `LocalFunctionFragmentImpl` (and `LocalFunctionElementImpl` that it produces).

Open in Gerrit

Related details

Attention is currently required from:
  • Erik Ernst
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: I04bc3c852611dbefb885afce655dc00054709fb7
Gerrit-Change-Number: 482786
Gerrit-PatchSet: 10
Gerrit-Owner: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Konstantin Shcheglov <sche...@google.com>
Gerrit-Reviewer: Paul Berry <paul...@google.com>
Gerrit-Attention: Erik Ernst <eer...@google.com>
Gerrit-Comment-Date: Tue, 03 Mar 2026 22:51:05 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Paul Berry <paul...@google.com>
Comment-In-Reply-To: Erik Ernst <eer...@google.com>
Comment-In-Reply-To: Konstantin Shcheglov <sche...@google.com>
unsatisfied_requirement
open
diffy

Erik Ernst (Gerrit)

unread,
Mar 5, 2026, 12:21:52 PMMar 5
to Konstantin Shcheglov, Paul Berry, Commit Queue, dart-analys...@google.com, rev...@dartlang.org
Attention needed from Konstantin Shcheglov and Paul Berry

Erik Ernst added 2 comments

Patchset-level comments
Erik Ernst . resolved

No visible progress, just replying to very helpful advice! ;-D

File pkg/analyzer/lib/src/generated/error_verifier.dart
Line 125, Patchset 9: final TypeImpl? _returnType;
Paul Berry . unresolved

It took me a while to figure out what this is for.

I *think* what it's for is to allow `ErrorVerifier.visitAnonymousMethodInvocation` to override the standard behavior of the `returnType` getter (which is to look up the return type in the element), because I guess anonymous method invocations don't have an associated element?

But if they don't have elements, why not? Our usual rule is that something needs to be an element if you can refer to it by name, OR if it's needed as the parent element to something you *can* refer to by name. If an anonymous method has a parameter, then that parameter must have a parameter element, and that parameter element should have a parent which is the anonymous method element, right?

Assuming that's true (that anonymous methods *do* have elements), then you shouldn't have to modify `EnclosingExecutableContext` at all; you should just be able to pass in the correct element when you call the constructor.

Erik Ernst

In an earlier iteration of this work I did create a new kind of element to represent the anonymous method. However, this caused several other requirements to arise: About 45 element visitors were suddenly broken, and there was a need to introduce a fragment to deliver from `declaredFragment`, and various other stuff that I don't remember in full detail.

I think we might have discussed this, but in any case I tried to get by without a new element class, thinking that it would be sufficient for the anonymous method to have a kind of element which is minimal by reusing an existing `...Element` class. In the end it should presumably just be a node in the tree such that there is no unexpected null value in a `parent`, and hopefully the formal parameter element doesn't really need any services from it.

However, I went back to this strategy and introduced a few private classes in error_verifier.dart starting from line 204. It just takes a couple of steps (and each step makes it stop with a new member which should have been there).

Could you give me a hint about a systematic method to discover how to build this connected graph of classes and objects that are needed in order to introduce a new kind of element?

Konstantin Shcheglov
See how we build fragments and elements in `ElementBindingVisitor`, specifically `visitFunctionExpression`. Note that we create `LocalFunctionFragmentImpl` and then use it to wrap as enclosingFragment typeParameters and formalParameters.
```
var holder = ElementHolder(fragment);
_withElementHolder(holder, () {
super.visitFunctionExpression(node);
fragment.typeParameters = holder.typeParameters;
fragment.formalParameters = holder.formalParameters;
});
```

I think there is a lot of similarities with anonymous methods.

Konstantin Shcheglov

You will need to add `LocalFunctionFragmentImpl declaredFragment` to `AnonymousMethodInvocation`. Which sounds unusual, as now invocation has its own declaration. I see the comment describes it in terms of `AnonymousMethod`, which would be more natural place for `declaredFragment` IMHO. But maybe it is just unusual to me.

FYI, we consider splitting `LocalFunctionElement` into `LocalExecutableElement` superclass with leaf subclasses `LocalFunctionElement` proper, `FunctionExpressionElement`, and `AnonymousMethodElement`. This will align elements with syntax, which sometimes is useful. Nothing for you to do here, for now we will continue using `LocalFunctionFragmentImpl` (and `LocalFunctionElementImpl` that it produces).

Erik Ernst

Thanks, Konstantin!

I'm actually thinking that the naming is conceptually helpful because it refers to a particular constraint: The new AST nodes model "anonymous method invocations", and nothing models the "anonymous method" as a separate thing. This might help ensuring that the "anonymous method" is never considered to be like a function expression --- and that's what we want because it does allow us to get a better flow analysis and a better context type for returned expressions than we could hope for if we just treat it as a function literal which is invoked on the receiver.

Open in Gerrit

Related details

Attention is currently required from:
  • Konstantin Shcheglov
  • Paul Berry
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: I04bc3c852611dbefb885afce655dc00054709fb7
Gerrit-Change-Number: 482786
Gerrit-PatchSet: 10
Gerrit-Owner: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Konstantin Shcheglov <sche...@google.com>
Gerrit-Reviewer: Paul Berry <paul...@google.com>
Gerrit-Attention: Paul Berry <paul...@google.com>
Gerrit-Attention: Konstantin Shcheglov <sche...@google.com>
Gerrit-Comment-Date: Thu, 05 Mar 2026 17:21:47 +0000
unsatisfied_requirement
open
diffy

Erik Ernst (Gerrit)

unread,
Mar 12, 2026, 1:31:31 PMMar 12
to Konstantin Shcheglov, Paul Berry, Commit Queue, dart-analys...@google.com, rev...@dartlang.org
Attention needed from Konstantin Shcheglov and Paul Berry

Erik Ernst added 2 comments

Patchset-level comments
File-level comment, Patchset 12 (Latest):
Erik Ernst . resolved

I made the changes suggested in review comments, and all tests succeed, but surely it would be great to have more experienced eyes on the correctness of these changes. PTAL!

File pkg/analyzer/lib/src/generated/error_verifier.dart
Line 125, Patchset 9: final TypeImpl? _returnType;
Paul Berry . resolved

It took me a while to figure out what this is for.

I *think* what it's for is to allow `ErrorVerifier.visitAnonymousMethodInvocation` to override the standard behavior of the `returnType` getter (which is to look up the return type in the element), because I guess anonymous method invocations don't have an associated element?

But if they don't have elements, why not? Our usual rule is that something needs to be an element if you can refer to it by name, OR if it's needed as the parent element to something you *can* refer to by name. If an anonymous method has a parameter, then that parameter must have a parameter element, and that parameter element should have a parent which is the anonymous method element, right?

Assuming that's true (that anonymous methods *do* have elements), then you shouldn't have to modify `EnclosingExecutableContext` at all; you should just be able to pass in the correct element when you call the constructor.

Erik Ernst

In an earlier iteration of this work I did create a new kind of element to represent the anonymous method. However, this caused several other requirements to arise: About 45 element visitors were suddenly broken, and there was a need to introduce a fragment to deliver from `declaredFragment`, and various other stuff that I don't remember in full detail.

I think we might have discussed this, but in any case I tried to get by without a new element class, thinking that it would be sufficient for the anonymous method to have a kind of element which is minimal by reusing an existing `...Element` class. In the end it should presumably just be a node in the tree such that there is no unexpected null value in a `parent`, and hopefully the formal parameter element doesn't really need any services from it.

However, I went back to this strategy and introduced a few private classes in error_verifier.dart starting from line 204. It just takes a couple of steps (and each step makes it stop with a new member which should have been there).

Could you give me a hint about a systematic method to discover how to build this connected graph of classes and objects that are needed in order to introduce a new kind of element?

Konstantin Shcheglov
See how we build fragments and elements in `ElementBindingVisitor`, specifically `visitFunctionExpression`. Note that we create `LocalFunctionFragmentImpl` and then use it to wrap as enclosingFragment typeParameters and formalParameters.
```
var holder = ElementHolder(fragment);
_withElementHolder(holder, () {
super.visitFunctionExpression(node);
fragment.typeParameters = holder.typeParameters;
fragment.formalParameters = holder.formalParameters;
});
```

I think there is a lot of similarities with anonymous methods.

Konstantin Shcheglov

You will need to add `LocalFunctionFragmentImpl declaredFragment` to `AnonymousMethodInvocation`. Which sounds unusual, as now invocation has its own declaration. I see the comment describes it in terms of `AnonymousMethod`, which would be more natural place for `declaredFragment` IMHO. But maybe it is just unusual to me.

FYI, we consider splitting `LocalFunctionElement` into `LocalExecutableElement` superclass with leaf subclasses `LocalFunctionElement` proper, `FunctionExpressionElement`, and `AnonymousMethodElement`. This will align elements with syntax, which sometimes is useful. Nothing for you to do here, for now we will continue using `LocalFunctionFragmentImpl` (and `LocalFunctionElementImpl` that it produces).

Erik Ernst

Thanks, Konstantin!

I'm actually thinking that the naming is conceptually helpful because it refers to a particular constraint: The new AST nodes model "anonymous method invocations", and nothing models the "anonymous method" as a separate thing. This might help ensuring that the "anonymous method" is never considered to be like a function expression --- and that's what we want because it does allow us to get a better flow analysis and a better context type for returned expressions than we could hope for if we just treat it as a function literal which is invoked on the receiver.

Erik Ernst

I used the advice to update the `ElementBindingVisitor` and other things, and it is now (again) passing all tests. So I'll close this thread.

Open in Gerrit

Related details

Attention is currently required from:
  • Konstantin Shcheglov
  • Paul Berry
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: I04bc3c852611dbefb885afce655dc00054709fb7
Gerrit-Change-Number: 482786
Gerrit-PatchSet: 12
Gerrit-Owner: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Konstantin Shcheglov <sche...@google.com>
Gerrit-Reviewer: Paul Berry <paul...@google.com>
Gerrit-Attention: Paul Berry <paul...@google.com>
Gerrit-Attention: Konstantin Shcheglov <sche...@google.com>
Gerrit-Comment-Date: Thu, 12 Mar 2026 17:31:26 +0000
unsatisfied_requirement
open
diffy

Paul Berry (Gerrit)

unread,
Mar 12, 2026, 2:08:52 PMMar 12
to Erik Ernst, Konstantin Shcheglov, Commit Queue, dart-analys...@google.com, rev...@dartlang.org
Attention needed from Erik Ernst and Konstantin Shcheglov

Paul Berry voted and added 1 comment

Votes added by Paul Berry

Code-Review+1

1 comment

Patchset-level comments
Paul Berry . resolved

lgtm, but please wait for Konstantin's review before landing this, since he's picked up subtleties that I've missed.

Open in Gerrit

Related details

Attention is currently required from:
  • Erik Ernst
  • Konstantin Shcheglov
Submit Requirements:
    • requirement is not satisfiedCode-Owners
    • requirement satisfiedCode-Review
    • requirement satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: sdk
    Gerrit-Branch: main
    Gerrit-Change-Id: I04bc3c852611dbefb885afce655dc00054709fb7
    Gerrit-Change-Number: 482786
    Gerrit-PatchSet: 12
    Gerrit-Owner: Erik Ernst <eer...@google.com>
    Gerrit-Reviewer: Erik Ernst <eer...@google.com>
    Gerrit-Reviewer: Konstantin Shcheglov <sche...@google.com>
    Gerrit-Reviewer: Paul Berry <paul...@google.com>
    Gerrit-Attention: Erik Ernst <eer...@google.com>
    Gerrit-Attention: Konstantin Shcheglov <sche...@google.com>
    Gerrit-Comment-Date: Thu, 12 Mar 2026 18:08:48 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: Yes
    unsatisfied_requirement
    satisfied_requirement
    open
    diffy

    Paul Berry (Gerrit)

    unread,
    Mar 12, 2026, 3:18:15 PMMar 12
    to Erik Ernst, Konstantin Shcheglov, Commit Queue, dart-analys...@google.com, rev...@dartlang.org
    Attention needed from Erik Ernst and Konstantin Shcheglov

    Paul Berry added 1 comment

    Patchset-level comments
    Paul Berry . resolved

    BTW, the failure you're seeing on the `g3-cbuild-try` bot is likely due to the fact that your CL is based on the state of the repo from Feb 23. All the bots try to merge CLs up to main before testing them, but AIUI, `g3-cbuild-try` uses a less sophisticated merging algorithm than Gerrit does, so it sometimes hits merge conflicts even when Gerrit thinks there are none.

    You should be able to get a green trybot run by rebasing your CL onto the latest main.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Erik Ernst
    • Konstantin Shcheglov
    Submit Requirements:
    • requirement is not satisfiedCode-Owners
    • requirement satisfiedCode-Review
    • requirement satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: sdk
    Gerrit-Branch: main
    Gerrit-Change-Id: I04bc3c852611dbefb885afce655dc00054709fb7
    Gerrit-Change-Number: 482786
    Gerrit-PatchSet: 12
    Gerrit-Owner: Erik Ernst <eer...@google.com>
    Gerrit-Reviewer: Erik Ernst <eer...@google.com>
    Gerrit-Reviewer: Konstantin Shcheglov <sche...@google.com>
    Gerrit-Reviewer: Paul Berry <paul...@google.com>
    Gerrit-Attention: Erik Ernst <eer...@google.com>
    Gerrit-Attention: Konstantin Shcheglov <sche...@google.com>
    Gerrit-Comment-Date: Thu, 12 Mar 2026 19:18:13 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    unsatisfied_requirement
    satisfied_requirement
    open
    diffy

    Konstantin Shcheglov (Gerrit)

    unread,
    Mar 13, 2026, 2:35:22 AMMar 13
    to Erik Ernst, Paul Berry, Commit Queue, dart-analys...@google.com, rev...@dartlang.org
    Attention needed from Erik Ernst

    Konstantin Shcheglov voted Code-Review+1

    Code-Review+1
    Open in Gerrit

    Related details

    Attention is currently required from:
    • Erik Ernst
    Submit Requirements:
    • requirement is not satisfiedCode-Owners
    • requirement satisfiedCode-Review
    • requirement satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: sdk
    Gerrit-Branch: main
    Gerrit-Change-Id: I04bc3c852611dbefb885afce655dc00054709fb7
    Gerrit-Change-Number: 482786
    Gerrit-PatchSet: 12
    Gerrit-Owner: Erik Ernst <eer...@google.com>
    Gerrit-Reviewer: Erik Ernst <eer...@google.com>
    Gerrit-Reviewer: Konstantin Shcheglov <sche...@google.com>
    Gerrit-Reviewer: Paul Berry <paul...@google.com>
    Gerrit-Attention: Erik Ernst <eer...@google.com>
    Gerrit-Comment-Date: Fri, 13 Mar 2026 06:35:19 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: Yes
    unsatisfied_requirement
    satisfied_requirement
    open
    diffy

    Erik Ernst (Gerrit)

    unread,
    Mar 13, 2026, 4:30:34 AMMar 13
    to Samuel Rawlins, Konstantin Shcheglov, Paul Berry, Commit Queue, dart-analys...@google.com, rev...@dartlang.org
    Attention needed from Samuel Rawlins

    Erik Ernst added 1 comment

    Patchset-level comments
    File-level comment, Patchset 13 (Latest):
    Erik Ernst . resolved

    Hello Sam, this CL contains a small change to api.txt, could you take a look at that?

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Samuel Rawlins
    Submit Requirements:
    • requirement is not satisfiedCode-Owners
    • requirement satisfiedCode-Review
    • requirement satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: sdk
    Gerrit-Branch: main
    Gerrit-Change-Id: I04bc3c852611dbefb885afce655dc00054709fb7
    Gerrit-Change-Number: 482786
    Gerrit-PatchSet: 13
    Gerrit-Owner: Erik Ernst <eer...@google.com>
    Gerrit-Reviewer: Erik Ernst <eer...@google.com>
    Gerrit-Reviewer: Konstantin Shcheglov <sche...@google.com>
    Gerrit-Reviewer: Paul Berry <paul...@google.com>
    Gerrit-Reviewer: Samuel Rawlins <sraw...@google.com>
    Gerrit-Attention: Samuel Rawlins <sraw...@google.com>
    Gerrit-Comment-Date: Fri, 13 Mar 2026 08:30:30 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    unsatisfied_requirement
    satisfied_requirement
    open
    diffy

    Samuel Rawlins (Gerrit)

    unread,
    Mar 13, 2026, 11:40:36 AMMar 13
    to Erik Ernst, Konstantin Shcheglov, Paul Berry, Commit Queue, dart-analys...@google.com, rev...@dartlang.org
    Attention needed from Erik Ernst

    Samuel Rawlins voted Code-Review+1

    Code-Review+1
    Open in Gerrit

    Related details

    Attention is currently required from:
    • Erik Ernst
    Submit Requirements:
    • requirement satisfiedCode-Owners
    • requirement satisfiedCode-Review
    • requirement satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: sdk
    Gerrit-Branch: main
    Gerrit-Change-Id: I04bc3c852611dbefb885afce655dc00054709fb7
    Gerrit-Change-Number: 482786
    Gerrit-PatchSet: 14
    Gerrit-Owner: Erik Ernst <eer...@google.com>
    Gerrit-Reviewer: Erik Ernst <eer...@google.com>
    Gerrit-Reviewer: Konstantin Shcheglov <sche...@google.com>
    Gerrit-Reviewer: Paul Berry <paul...@google.com>
    Gerrit-Reviewer: Samuel Rawlins <sraw...@google.com>
    Gerrit-Attention: Erik Ernst <eer...@google.com>
    Gerrit-Comment-Date: Fri, 13 Mar 2026 15:40:33 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: Yes
    satisfied_requirement
    open
    diffy

    Erik Ernst (Gerrit)

    unread,
    Mar 13, 2026, 11:54:03 AMMar 13
    to Samuel Rawlins, Konstantin Shcheglov, Paul Berry, Commit Queue, dart-analys...@google.com, rev...@dartlang.org

    Erik Ernst voted Commit-Queue+2

    Commit-Queue+2
    Open in Gerrit

    Related details

    Attention set is empty
    Submit Requirements:
    • requirement satisfiedCode-Owners
    • requirement satisfiedCode-Review
    • requirement satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: sdk
    Gerrit-Branch: main
    Gerrit-Change-Id: I04bc3c852611dbefb885afce655dc00054709fb7
    Gerrit-Change-Number: 482786
    Gerrit-PatchSet: 14
    Gerrit-Owner: Erik Ernst <eer...@google.com>
    Gerrit-Reviewer: Erik Ernst <eer...@google.com>
    Gerrit-Reviewer: Konstantin Shcheglov <sche...@google.com>
    Gerrit-Reviewer: Paul Berry <paul...@google.com>
    Gerrit-Reviewer: Samuel Rawlins <sraw...@google.com>
    Gerrit-Comment-Date: Fri, 13 Mar 2026 15:53:59 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: Yes
    satisfied_requirement
    open
    diffy

    Commit Queue (Gerrit)

    unread,
    Mar 13, 2026, 11:54:23 AMMar 13
    to Erik Ernst, Samuel Rawlins, Konstantin Shcheglov, Paul Berry, dart-analys...@google.com, rev...@dartlang.org

    Commit Queue submitted the change

    Change information

    Commit message:
    Take steps to support anonymous block bodies

    This CL adds support for anonymous block bodies (as in `e.{...}`) by
    generalizing the flow analysis to handle begin/end of anonymous block
    bodies and treating them similarly to labeled statements (and treating
    `return` statements using `handleBreak`). It generalizes `handleBreak`
    and the internal make `_StatementToContext` to handle `Node` keys rather
    than just `Statement` keys, such that an anonymous block body can be the
    context. It adds a `bodyContext` instance variable to
    `AnonymousBodyImpl` to be used during flow analysis of anonymous block
    bodies. `BodyInferenceContext` gets a new factory constructor in order
    to allow an anonymous block body to be the context. Finally,
    `ErrorVerifier` is generalized to handle the case where a return
    statement is returning from an anonymous block body.
    Change-Id: I04bc3c852611dbefb885afce655dc00054709fb7
    Reviewed-by: Konstantin Shcheglov <sche...@google.com>
    Reviewed-by: Samuel Rawlins <sraw...@google.com>
    Reviewed-by: Paul Berry <paul...@google.com>
    Commit-Queue: Erik Ernst <eer...@google.com>
    Files:
    • M pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
    • M pkg/analyzer/api.txt
    • M pkg/analyzer/lib/src/dart/ast/ast.dart
    • M pkg/analyzer/lib/src/dart/resolver/body_inference_context.dart
    • M pkg/analyzer/lib/src/dart/resolver/element_binding_visitor.dart
    • M pkg/analyzer/lib/src/generated/error_verifier.dart
    • M pkg/analyzer/lib/src/generated/resolver.dart
    • A tests/language/anonymous_methods/block/cascaded_test.dart
    • A tests/language/anonymous_methods/block/context_test.dart
    • A tests/language/anonymous_methods/block/null_aware_cascaded_test.dart
    • A tests/language/anonymous_methods/block/null_aware_plain_test.dart
    • A tests/language/anonymous_methods/block/plain_test.dart
    • A tests/language/anonymous_methods/block/promotion_test.dart
    • A tests/language/anonymous_methods/block/this_not_enclosing_test.dart
    • M tests/language/anonymous_methods/expression/promotion_test.dart
    Change size: XL
    Delta: 15 files changed, 1296 insertions(+), 32 deletions(-)
    Branch: refs/heads/main
    Submit Requirements:
    • requirement satisfiedCode-Review: +1 by Paul Berry, +1 by Konstantin Shcheglov, +1 by Samuel Rawlins
    Open in Gerrit
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: merged
    Gerrit-Project: sdk
    Gerrit-Branch: main
    Gerrit-Change-Id: I04bc3c852611dbefb885afce655dc00054709fb7
    Gerrit-Change-Number: 482786
    Gerrit-PatchSet: 15
    Gerrit-Owner: Erik Ernst <eer...@google.com>
    open
    diffy
    satisfied_requirement
    Reply all
    Reply to author
    Forward
    0 new messages