[XL] Change in dart/sdk[main]: Support the feature 'anonymous methods' in the analyzer

0 views
Skip to first unread message

Erik Ernst (Gerrit)

unread,
Sep 22, 2025, 10:31:14 AMSep 22
to Commit Queue, Paul Berry, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org

Erik Ernst added 1 comment

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

flutter-analyze-try currently fails with "Running command: ".../dart analyze --fatal-infos" in .../packages/packages/google_maps_flutter/google_maps_flutter_web Analyzing google_maps_flutter_web... error - example/integration_test/overlay_test.dart:44:31 - A value of type 'Size?' can't be assigned to a variable of type 'Size'. Try changing the type of the variable, or casting the right-hand type to 'Size'. - invalid_assignment", and that seems to be a bug in `overlay_test.dart`.

Open in Gerrit

Related details

Attention set is empty
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: I0e90a9356508044766d5f4c6e3c413bccbe61796
Gerrit-Change-Number: 449821
Gerrit-PatchSet: 15
Gerrit-Owner: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Erik Ernst <eer...@google.com>
Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
Gerrit-CC: Paul Berry <paul...@google.com>
Gerrit-Comment-Date: Mon, 22 Sep 2025 14:31:07 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
unsatisfied_requirement
open
diffy

Brian Wilkerson (Gerrit)

unread,
Sep 22, 2025, 11:17:00 AMSep 22
to Erik Ernst, Brian Wilkerson, Commit Queue, Paul Berry, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
Attention needed from Erik Ernst

Brian Wilkerson added 1 comment

Patchset-level comments
Brian Wilkerson . resolved

Is there a specification of the feature that I can read?

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: I0e90a9356508044766d5f4c6e3c413bccbe61796
Gerrit-Change-Number: 449821
Gerrit-PatchSet: 15
Gerrit-Owner: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Erik Ernst <eer...@google.com>
Gerrit-CC: Brian Wilkerson <brianwi...@google.com>
Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
Gerrit-CC: Paul Berry <paul...@google.com>
Gerrit-Attention: Erik Ernst <eer...@google.com>
Gerrit-Comment-Date: Mon, 22 Sep 2025 15:16:55 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
unsatisfied_requirement
open
diffy

Brian Wilkerson (Gerrit)

unread,
Sep 22, 2025, 11:20:33 AMSep 22
to Erik Ernst, Brian Wilkerson, Commit Queue, Paul Berry, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
Attention needed from Erik Ernst

Brian Wilkerson added 1 comment

File pkg/analyzer/messages.yaml
Line 716, Patchset 15 (Latest): problemMessage: The formal parameter list of an anonymous method must have exactly one non-optional, positional formal parameter.
Brian Wilkerson . unresolved

Consider "non-optional" --> "required" (here and elsewhere). We use the term "required" in other places, so it ought to be clear to users.

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: I0e90a9356508044766d5f4c6e3c413bccbe61796
Gerrit-Change-Number: 449821
Gerrit-PatchSet: 15
Gerrit-Owner: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Erik Ernst <eer...@google.com>
Gerrit-CC: Brian Wilkerson <brianwi...@google.com>
Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
Gerrit-CC: Paul Berry <paul...@google.com>
Gerrit-Attention: Erik Ernst <eer...@google.com>
Gerrit-Comment-Date: Mon, 22 Sep 2025 15:20:29 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
unsatisfied_requirement
open
diffy

Erik Ernst (Gerrit)

unread,
Sep 22, 2025, 11:21:29 AMSep 22
to Brian Wilkerson, Commit Queue, Paul Berry, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
Attention needed from Brian Wilkerson

Erik Ernst added 1 comment

Patchset-level comments
Brian Wilkerson . resolved

Is there a specification of the feature that I can read?

Erik Ernst

At this time we only have the Github issue where this feature is proposed: https://github.com/dart-lang/language/issues/260. I wanted to explore the typing and inference based on an actual implementation, but a feature specification in the usual style is planned. Also, the language team will surely debate the proposal for a while.

Open in Gerrit

Related details

Attention is currently required from:
  • Brian Wilkerson
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: I0e90a9356508044766d5f4c6e3c413bccbe61796
Gerrit-Change-Number: 449821
Gerrit-PatchSet: 15
Gerrit-Owner: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Erik Ernst <eer...@google.com>
Gerrit-CC: Brian Wilkerson <brianwi...@google.com>
Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
Gerrit-CC: Paul Berry <paul...@google.com>
Gerrit-Attention: Brian Wilkerson <brianwi...@google.com>
Gerrit-Comment-Date: Mon, 22 Sep 2025 15:21:22 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Brian Wilkerson <brianwi...@google.com>
unsatisfied_requirement
open
diffy

Erik Ernst (Gerrit)

unread,
Sep 22, 2025, 11:35:45 AMSep 22
to Brian Wilkerson, Commit Queue, Paul Berry, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
Attention needed from Brian Wilkerson

Erik Ernst added 1 comment

File pkg/analyzer/messages.yaml
Line 716, Patchset 15: problemMessage: The formal parameter list of an anonymous method must have exactly one non-optional, positional formal parameter.
Brian Wilkerson . resolved

Consider "non-optional" --> "required" (here and elsewhere). We use the term "required" in other places, so it ought to be clear to users.

Erik Ernst

OK, done!

Open in Gerrit

Related details

Attention is currently required from:
  • Brian Wilkerson
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: I0e90a9356508044766d5f4c6e3c413bccbe61796
Gerrit-Change-Number: 449821
Gerrit-PatchSet: 16
Gerrit-Owner: Erik Ernst <eer...@google.com>
Gerrit-Reviewer: Erik Ernst <eer...@google.com>
Gerrit-CC: Brian Wilkerson <brianwi...@google.com>
Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
Gerrit-CC: Paul Berry <paul...@google.com>
Gerrit-Attention: Brian Wilkerson <brianwi...@google.com>
Gerrit-Comment-Date: Mon, 22 Sep 2025 15:35:33 +0000
unsatisfied_requirement
open
diffy

Brian Wilkerson (Gerrit)

unread,
Sep 22, 2025, 12:10:28 PMSep 22
to Erik Ernst, Brian Wilkerson, Commit Queue, Paul Berry, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
Attention needed from Erik Ernst

Brian Wilkerson voted and added 1 comment

Votes added by Brian Wilkerson

Code-Review+1

1 comment

Patchset-level comments
File-level comment, Patchset 16 (Latest):
Brian Wilkerson . resolved

The `analysis_server` and `api.txt` changes lgtm.

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: I0e90a9356508044766d5f4c6e3c413bccbe61796
    Gerrit-Change-Number: 449821
    Gerrit-PatchSet: 16
    Gerrit-Owner: Erik Ernst <eer...@google.com>
    Gerrit-Reviewer: Brian Wilkerson <brianwi...@google.com>
    Gerrit-Reviewer: Erik Ernst <eer...@google.com>
    Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
    Gerrit-CC: Paul Berry <paul...@google.com>
    Gerrit-Attention: Erik Ernst <eer...@google.com>
    Gerrit-Comment-Date: Mon, 22 Sep 2025 16:10:24 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: Yes
    unsatisfied_requirement
    satisfied_requirement
    open
    diffy

    Paul Berry (Gerrit)

    unread,
    Oct 13, 2025, 1:31:17 PMOct 13
    to Erik Ernst, Brian Wilkerson, Commit Queue, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
    Attention needed from Brian Wilkerson and Erik Ernst

    Paul Berry added 1 comment

    Patchset-level comments
    File-level comment, Patchset 22 (Latest):
    Paul Berry . unresolved

    FYI, https://dart-review.googlesource.com/c/sdk/+/454660 updates the analyzer code generator to add `@experimental` when generating visit methods. If you rebase atop that CL, that should take care of the failures in the pkg-linux-release-try bot. When you do so, you will have to add `import 'package:meta/meta.dart';` to `pkg/analyzer/lib/dart/ast/visitor.dart` and `pkg/analyzer/lib/src/lint/linter_visitor.dart`.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Brian Wilkerson
    • 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: I0e90a9356508044766d5f4c6e3c413bccbe61796
      Gerrit-Change-Number: 449821
      Gerrit-PatchSet: 22
      Gerrit-Owner: Erik Ernst <eer...@google.com>
      Gerrit-Reviewer: Brian Wilkerson <brianwi...@google.com>
      Gerrit-Reviewer: Erik Ernst <eer...@google.com>
      Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
      Gerrit-CC: Paul Berry <paul...@google.com>
      Gerrit-Attention: Brian Wilkerson <brianwi...@google.com>
      Gerrit-Attention: Erik Ernst <eer...@google.com>
      Gerrit-Comment-Date: Mon, 13 Oct 2025 17:31:13 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      unsatisfied_requirement
      open
      diffy

      Paul Berry (Gerrit)

      unread,
      Oct 13, 2025, 8:13:05 PMOct 13
      to Erik Ernst, Brian Wilkerson, Commit Queue, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
      Attention needed from Brian Wilkerson and Erik Ernst

      Paul Berry added 1 comment

      Patchset-level comments
      Paul Berry . unresolved

      FYI, https://dart-review.googlesource.com/c/sdk/+/454660 updates the analyzer code generator to add `@experimental` when generating visit methods. If you rebase atop that CL, that should take care of the failures in the pkg-linux-release-try bot. When you do so, you will have to add `import 'package:meta/meta.dart';` to `pkg/analyzer/lib/dart/ast/visitor.dart` and `pkg/analyzer/lib/src/lint/linter_visitor.dart`.

      Paul Berry

      It turns out that Konstantin was already working on a fix for this issue, so I abandoned my change eh favor of his. His change is https://dart-review.googlesource.com/c/sdk/+/454700. It just landed, so you should be able to just rebase and re-run the code generator (`pkg/analyzer/tool/ast/generate.dart`).

      Also, I think you will also need to add `import 'package:meta/meta.dart';` to `pkg/analyzer/lib/analysis_rule/rule_visitor_registry.dart`.

      Gerrit-Comment-Date: Tue, 14 Oct 2025 00:13:02 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Paul Berry <paul...@google.com>
      unsatisfied_requirement
      open
      diffy

      Brian Wilkerson (Gerrit)

      unread,
      Oct 14, 2025, 12:24:11 PMOct 14
      to Erik Ernst, Brian Wilkerson, Commit Queue, Paul Berry, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
      Attention needed from Erik Ernst

      Brian Wilkerson voted and added 4 comments

      Votes added by Brian Wilkerson

      Code-Review+1

      4 comments

      Patchset-level comments
      Brian Wilkerson . resolved

      Neither of these comments are critical, but I'd like to see them addressed before we ship so it might be easier to address them now.

      File pkg/analyzer/lib/src/dart/ast/ast.dart
      Line 481, Patchset 22 (Latest):/// [Expression] '.' [Block]
      Brian Wilkerson . unresolved

      "Block" --> "FunctionExpression"?

      File pkg/analyzer/messages.yaml
      Line 717, Patchset 22 (Latest): correctionMessage: Try declaring one positional parameter, and make it required.
      Brian Wilkerson . resolved

      If we ship this, it might be useful to have correction messages that are a little more specific. I'm thinking of messages like

      • Try making the parameter be positional.
      • Try making the parameter be required.
      • Try adding a single required positional parameter. (when there are no parameters)
      • Try removing all but one of the parameters. (when there are multiple)
      Line 721, Patchset 22 (Latest): Type p0: the name of the type of the receiver
      Brian Wilkerson . unresolved

      "p0" --> "receiverType"
      "p1" --> "parameterType"

      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: I0e90a9356508044766d5f4c6e3c413bccbe61796
        Gerrit-Change-Number: 449821
        Gerrit-PatchSet: 22
        Gerrit-Owner: Erik Ernst <eer...@google.com>
        Gerrit-Reviewer: Brian Wilkerson <brianwi...@google.com>
        Gerrit-Reviewer: Erik Ernst <eer...@google.com>
        Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
        Gerrit-CC: Paul Berry <paul...@google.com>
        Gerrit-Attention: Erik Ernst <eer...@google.com>
        Gerrit-Comment-Date: Tue, 14 Oct 2025 16:24:07 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: Yes
        unsatisfied_requirement
        satisfied_requirement
        open
        diffy

        Erik Ernst (Gerrit)

        unread,
        Oct 15, 2025, 10:30:20 AMOct 15
        to Brian Wilkerson, Commit Queue, Paul Berry, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
        Attention needed from Brian Wilkerson and Paul Berry

        Erik Ernst added 5 comments

        Patchset-level comments

        FYI, https://dart-review.googlesource.com/c/sdk/+/454660 updates the analyzer code generator to add `@experimental` when generating visit methods. If you rebase atop that CL, that should take care of the failures in the pkg-linux-release-try bot. When you do so, you will have to add `import 'package:meta/meta.dart';` to `pkg/analyzer/lib/dart/ast/visitor.dart` and `pkg/analyzer/lib/src/lint/linter_visitor.dart`.

        Paul Berry

        It turns out that Konstantin was already working on a fix for this issue, so I abandoned my change eh favor of his. His change is https://dart-review.googlesource.com/c/sdk/+/454700. It just landed, so you should be able to just rebase and re-run the code generator (`pkg/analyzer/tool/ast/generate.dart`).

        Also, I think you will also need to add `import 'package:meta/meta.dart';` to `pkg/analyzer/lib/analysis_rule/rule_visitor_registry.dart`.

        Erik Ernst

        I added a couple of imports (visitor.dart and such need to import the package meta), and it seems to work.

        File-level comment, Patchset 22:
        Erik Ernst . resolved

        Review response. Rebasing, too.

        File pkg/analyzer/lib/src/dart/ast/ast.dart
        Line 481, Patchset 22:/// [Expression] '.' [Block]
        Brian Wilkerson . resolved

        "Block" --> "FunctionExpression"?

        Erik Ernst

        Good catch!

        We can't just change this to `[FunctionExpression]`. If we do that then we can't use constructs like `receiver.{ code; }`. It's _allowed_, though, and this comment should definitely be updated to match the latest changes.

        Done.

        File pkg/analyzer/messages.yaml
        Line 717, Patchset 22: correctionMessage: Try declaring one positional parameter, and make it required.
        Brian Wilkerson . resolved

        If we ship this, it might be useful to have correction messages that are a little more specific. I'm thinking of messages like

        • Try making the parameter be positional.
        • Try making the parameter be required.
        • Try adding a single required positional parameter. (when there are no parameters)
        • Try removing all but one of the parameters. (when there are multiple)
        Erik Ernst

        Makes sense! Put it into my TODO list.

        Line 721, Patchset 22: Type p0: the name of the type of the receiver
        Brian Wilkerson . resolved

        "p0" --> "receiverType"
        "p1" --> "parameterType"

        Erik Ernst

        Done.

        Open in Gerrit

        Related details

        Attention is currently required from:
        • Brian Wilkerson
        • 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: I0e90a9356508044766d5f4c6e3c413bccbe61796
          Gerrit-Change-Number: 449821
          Gerrit-PatchSet: 22
          Gerrit-Owner: Erik Ernst <eer...@google.com>
          Gerrit-Reviewer: Brian Wilkerson <brianwi...@google.com>
          Gerrit-Reviewer: Erik Ernst <eer...@google.com>
          Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
          Gerrit-CC: Paul Berry <paul...@google.com>
          Gerrit-Attention: Brian Wilkerson <brianwi...@google.com>
          Gerrit-Attention: Paul Berry <paul...@google.com>
          Gerrit-Comment-Date: Wed, 15 Oct 2025 14:30:13 +0000
          Gerrit-HasComments: Yes
          Gerrit-Has-Labels: No
          Comment-In-Reply-To: Brian Wilkerson <brianwi...@google.com>
          Comment-In-Reply-To: Paul Berry <paul...@google.com>
          unsatisfied_requirement
          open
          diffy

          Erik Ernst (Gerrit)

          unread,
          Oct 23, 2025, 11:58:44 AM (9 days ago) Oct 23
          to Johnni Winther, Brian Wilkerson, Commit Queue, Paul Berry, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
          Attention needed from Brian Wilkerson, Johnni Winther, Konstantin Shcheglov and Paul Berry

          Erik Ernst added 1 comment

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

          Hello Brian, Johnny, Paul, and Konstantin,

          this CL uses `@experimental` and doesn't trigger any diagnostics in that area (or any area). It provides support for the feature 'anonymous methods' (currently only implemented fully in the analyzer, but I intend to implement it in the CFE as well). It's enabled by `--enable-experiment=anonymous-methods`. It would be great if I can land the CL such that it's easier for anyone who is interested in exploring the feature to do that.

          The language team hasn't accepted the feature at this time, but we're looking at it, and Leaf supports landing the implementation as a vehicle for exploration.

          So how should this be done in order to make sure that it causes the smallest possible disruption for you? I could simply ask for reviews of this CL, or I could split it into smaller pieces and land them sequentially, whatever works better for all of you.

          Open in Gerrit

          Related details

          Attention is currently required from:
          • Brian Wilkerson
          • Johnni Winther
          • 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: I0e90a9356508044766d5f4c6e3c413bccbe61796
          Gerrit-Change-Number: 449821
          Gerrit-PatchSet: 42
          Gerrit-Owner: Erik Ernst <eer...@google.com>
          Gerrit-Reviewer: Brian Wilkerson <brianwi...@google.com>
          Gerrit-Reviewer: Erik Ernst <eer...@google.com>
          Gerrit-Reviewer: Johnni Winther <johnni...@google.com>
          Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
          Gerrit-CC: Paul Berry <paul...@google.com>
          Gerrit-Attention: Brian Wilkerson <brianwi...@google.com>
          Gerrit-Attention: Paul Berry <paul...@google.com>
          Gerrit-Attention: Konstantin Shcheglov <sche...@google.com>
          Gerrit-Attention: Johnni Winther <johnni...@google.com>
          Gerrit-Comment-Date: Thu, 23 Oct 2025 15:58:35 +0000
          Gerrit-HasComments: Yes
          Gerrit-Has-Labels: No
          unsatisfied_requirement
          open
          diffy

          Brian Wilkerson (Gerrit)

          unread,
          Oct 23, 2025, 12:24:25 PM (9 days ago) Oct 23
          to Erik Ernst, Brian Wilkerson, Johnni Winther, Commit Queue, Paul Berry, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
          Attention needed from Erik Ernst, Johnni Winther, Konstantin Shcheglov and Paul Berry

          Brian Wilkerson voted and added 2 comments

          Votes added by Brian Wilkerson

          Code-Review+1

          2 comments

          Patchset-level comments
          Brian Wilkerson . resolved

          The server and linter pieces lgtm.

          File pkg/linter/lib/src/util/scope.dart
          Line 95, Patchset 42 (Latest): currentAstNode.parameterName == null) {
          Brian Wilkerson . unresolved

          I don't understand the purpose of this part of the condition. Consider adding a comment explaining it.

          Open in Gerrit

          Related details

          Attention is currently required from:
          • Erik Ernst
          • Johnni Winther
          • Konstantin Shcheglov
          • Paul Berry
            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: I0e90a9356508044766d5f4c6e3c413bccbe61796
              Gerrit-Change-Number: 449821
              Gerrit-PatchSet: 42
              Gerrit-Owner: Erik Ernst <eer...@google.com>
              Gerrit-Reviewer: Brian Wilkerson <brianwi...@google.com>
              Gerrit-Reviewer: Erik Ernst <eer...@google.com>
              Gerrit-Reviewer: Johnni Winther <johnni...@google.com>
              Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
              Gerrit-CC: Paul Berry <paul...@google.com>
              Gerrit-Attention: Paul Berry <paul...@google.com>
              Gerrit-Attention: Erik Ernst <eer...@google.com>
              Gerrit-Attention: Konstantin Shcheglov <sche...@google.com>
              Gerrit-Attention: Johnni Winther <johnni...@google.com>
              Gerrit-Comment-Date: Thu, 23 Oct 2025 16:24:22 +0000
              Gerrit-HasComments: Yes
              Gerrit-Has-Labels: Yes
              unsatisfied_requirement
              satisfied_requirement
              open
              diffy

              Konstantin Shcheglov (Gerrit)

              unread,
              Oct 23, 2025, 12:28:52 PM (9 days ago) Oct 23
              to Erik Ernst, Brian Wilkerson, Johnni Winther, Commit Queue, Paul Berry, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
              Attention needed from Erik Ernst, Johnni Winther and Paul Berry

              Konstantin Shcheglov added 1 comment

              Patchset-level comments
              Konstantin Shcheglov . unresolved

              I have a few concerns about this CL.

              1. We need reference to the specification in the CL description.

              2. We need analyzer tests for parsing, see `ClassDeclarationParserTest`, although here it is not a top-level declaration. But something similar to see AST, parser errors, and recovery.

              3. We need analyzer tests for resolution, see `MethodInvocationResolutionTest`.

              4. The number of changes required to `Scope` and all the places where we use it makes it too complicated. Without good understanding scope rule for this feature I cannot recommend anything specific, but in general a more palatable implementation would be to do some single action like creating a new `XyzScope` at the point where we enter anonymouse block.

              Open in Gerrit

              Related details

              Attention is currently required from:
              • Erik Ernst
              • Johnni Winther
              • Paul Berry
              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: I0e90a9356508044766d5f4c6e3c413bccbe61796
              Gerrit-Change-Number: 449821
              Gerrit-PatchSet: 42
              Gerrit-Owner: Erik Ernst <eer...@google.com>
              Gerrit-Reviewer: Brian Wilkerson <brianwi...@google.com>
              Gerrit-Reviewer: Erik Ernst <eer...@google.com>
              Gerrit-Reviewer: Johnni Winther <johnni...@google.com>
              Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
              Gerrit-CC: Paul Berry <paul...@google.com>
              Gerrit-Attention: Paul Berry <paul...@google.com>
              Gerrit-Attention: Erik Ernst <eer...@google.com>
              Gerrit-Attention: Johnni Winther <johnni...@google.com>
              Gerrit-Comment-Date: Thu, 23 Oct 2025 16:28:48 +0000
              Gerrit-HasComments: Yes
              Gerrit-Has-Labels: No
              unsatisfied_requirement
              satisfied_requirement
              open
              diffy

              Johnni Winther (Gerrit)

              unread,
              Oct 27, 2025, 9:04:23 AM (5 days ago) Oct 27
              to Erik Ernst, Brian Wilkerson, Commit Queue, Paul Berry, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
              Attention needed from Erik Ernst and Paul Berry

              Johnni Winther added 10 comments

              File pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
              Line 2069, Patchset 42 (Latest): void endAnonymousMethodInvocation(Token token, Token? functionDefinition) {
              Johnni Winther . unresolved

              Rename `token` to `beginToken` and add a `endToken` at the end of the parameter list.

              File pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
              Line 6859, Patchset 42 (Latest): if (isAnonymousMethodsFeatureEnabled &&
              Johnni Winther . unresolved

              Add a TODO to remove this from the condition and instead call `reportExperimentNotEnabled` once these feature is planned for release.

              Line 6863, Patchset 42 (Latest): if (afterDot.isA(TokenType.OPEN_PAREN)) {
              Johnni Winther . unresolved

              Add a listener method

                  void beginAnonymousMethodInvocation(Token token);

              and call it here with `dot` as argument.

              Line 6864, Patchset 42 (Latest): token = parseFormalParameters(dot, MemberKind.Local);
              Johnni Winther . unresolved

              Why might want a now member kind `MemberKind.AnonymousMethod` for this.

              Line 7235, Patchset 42 (Latest): } else if (isAnonymousMethodsFeatureEnabled &&
              Johnni Winther . unresolved

              Add a TODO to remove this from the condition and instead call `reportExperimentNotEnabled` once these feature is planned for release.

              Line 7239, Patchset 42 (Latest): Token afterDots = token.next!;
              Johnni Winther . unresolved

              Call `beginAnymousMethodInvocation(cascadeOperator)` here.

              Line 7280, Patchset 42 (Latest): if (isAnonymousMethodsFeatureEnabled &&
              Johnni Winther . unresolved

              Add a TODO to remove this from the condition and instead call `reportExperimentNotEnabled` once these feature is planned for release.

              Line 7284, Patchset 42 (Latest): if (afterPeriod.isA(TokenType.OPEN_PAREN)) {
              Johnni Winther . unresolved

              Call `beginAnonymousMethodInvocation(period)` here.

              File pkg/analyzer/lib/dart/element/scope.dart
              Line 16, Patchset 42 (Latest): ScopeLookupResult lookup(String id, {bool skipInstanceMembers = false});
              Johnni Winther . unresolved

              Since we cannot mark this as experimental we should add a new method (possibly only to `ScopeImpl`) that handle the new scenario:

                  @experimental
              ScopeLookupResult lookupWithoutInstanceMembers(String id);
              File pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
              Line 747, Patchset 42 (Latest):extension on AstNode {
              bool get _isInAnonymousMethod {
              AstNode? currentAstNode = this;
              while (currentAstNode != null) {
              if (currentAstNode is AnonymousMethodInvocation &&
              currentAstNode.parameterName == null) {
              return true;
              }
              currentAstNode = currentAstNode.parent;
              }
              return false;
              }
              }
              Johnni Winther . unresolved

              We need to store this information in the visitor during traversal to avoid running up the parent relation on each lookup.

              This applies to all similar cases below.

              Open in Gerrit

              Related details

              Attention is currently required from:
              • Erik Ernst
              • Paul Berry
              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: I0e90a9356508044766d5f4c6e3c413bccbe61796
              Gerrit-Change-Number: 449821
              Gerrit-PatchSet: 42
              Gerrit-Owner: Erik Ernst <eer...@google.com>
              Gerrit-Reviewer: Brian Wilkerson <brianwi...@google.com>
              Gerrit-Reviewer: Erik Ernst <eer...@google.com>
              Gerrit-Reviewer: Johnni Winther <johnni...@google.com>
              Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
              Gerrit-CC: Paul Berry <paul...@google.com>
              Gerrit-Attention: Paul Berry <paul...@google.com>
              Gerrit-Attention: Erik Ernst <eer...@google.com>
              Gerrit-Comment-Date: Mon, 27 Oct 2025 13:04:16 +0000
              Gerrit-HasComments: Yes
              Gerrit-Has-Labels: No
              unsatisfied_requirement
              satisfied_requirement
              open
              diffy

              Paul Berry (Gerrit)

              unread,
              Oct 27, 2025, 8:01:18 PM (4 days ago) Oct 27
              to Erik Ernst, Brian Wilkerson, Johnni Winther, Commit Queue, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
              Attention needed from Erik Ernst

              Paul Berry added 17 comments

              File pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
              Line 2069, Patchset 44 (Latest): void endAnonymousMethodInvocation(Token token, Token? functionDefinition) {
              Paul Berry . unresolved

              I realize that the existing code doesn't often live up to this standard, but I find it really helpful when these listener methods can have documentation indicating the sequence of substructures that the listener can expect to find on the stack.

              E.g., something like:
              ```
              /// Called after the parser has consumed an anonymous method invocation.
              /// Substructures:
              /// - The target of the invocation.
              /// - formal parameters (possibly implicit--see [handleImplicitFormalParameters]).
              /// - The body of the anonymous method (either an expression or a block).
              ```

              Also, I think there should have a named boolean parameter to indicate whether the body is an expression or a block. Without it, the listener is forced to use an `if` test to figure out what kind of body it is.

              File pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
              Line 6859, Patchset 44 (Latest): if (isAnonymousMethodsFeatureEnabled &&
              Paul Berry . unresolved

              There's a lot of code duplication among lines 6859-6878, 7235-7257, and 7279-7302. Can this logic be consolidated into a single helper method?

              Line 6874, Patchset 44 (Latest): assert(afterParameters.isA(TokenType.FUNCTION));
              Paul Berry . unresolved

              I'm having trouble convincing myself that this assertion is correct. I think that if we're trying to parse `.(...)`, followed by *any* token other than `{`, then we will get to this line of code. So instead we need to do something like:

              ```
              } else if (afterParameters.isA(TokenType.FUNCTION)) {
              functionDefinition = afterParameters;
              token = parseExpression(afterParameters);
              } else {
              // Some kind of recovery logic
              }
              ```

              Similar issue at lines 7250 and 7298.

              File pkg/analyzer/lib/dart/analysis/features.dart
              Line 13, Patchset 44 (Latest): static final anonymous_methods = ExperimentalFeatures.anonymous_methods;
              Paul Berry . resolved

              No action needed from you right now, but I wonder if we should we mark this (and other fields pertaining to experimental features) as `@experimental`. I'm going to ask this question at the next developer experience / model team sync.

              File pkg/analyzer/lib/dart/element/scope.dart
              Line 16, Patchset 42: ScopeLookupResult lookup(String id, {bool skipInstanceMembers = false});
              Johnni Winther . unresolved

              Since we cannot mark this as experimental we should add a new method (possibly only to `ScopeImpl`) that handle the new scenario:

                  @experimental
              ScopeLookupResult lookupWithoutInstanceMembers(String id);
              Paul Berry

              @johnni...@google.com
              Why can't we mark this as experimental? I just tried it out and it seemed to work fine.

              Assuming I'm not missing something, I think we should just mark this as experimental.

              Also, I think the name `skipInstanceMembers` is confusing, because it suggests that if an instance member is ofund, the lookup will continue looking for a match at top level. How about if we rename this parameter to `noResultForInstanceMembers`?

              File pkg/analyzer/lib/src/dart/ast/ast.dart
              Line 480, Patchset 44 (Latest): FunctionExpression get functionExpression;
              Paul Berry . unresolved

              There's no function expression in the grammar here, and I don't think we should synthesize one. Especially because the `FunctionExpression` class has two getters that don't really make sense for anonymous methods: `declaredFragment` and `typeParameters`.

              I think this should be replaced with `FormalParameterList? get formalParameters;` and `FunctionBody get body;`.

              Line 495, Patchset 44 (Latest): Token? get parameterName;
              Paul Berry . unresolved

              Each input token should appear in the AST structure exactly once. This token is already inside the formal parameter list, so it should be removed from here.

              Line 521, Patchset 44 (Latest): with DotShorthandMixin
              Paul Berry . unresolved

              I don't think this should be here. Anonymous methods can't be dot short hand invocations.

              File pkg/analyzer/lib/src/dart/element/scope.dart
              Line 280, Patchset 44 (Latest): return ScopeLookupResultImpl(getter: null, setter: null);
              Paul Berry . unresolved

              This seems wrong to me. This causes us to treat getters and setters as no result, whether they are static or not. I think what you want to do is to treat getters, setters, _and_ methods as no result, but only if they are _not static_.

              File pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
              Line 463, Patchset 44 (Latest): .lookup(node.name, skipInstanceMembers: node._isInAnonymousMethod)
              Paul Berry . unresolved

              I'm getting a little concerned about the number of call sites that need to pass the correct value of `skipInstanceMembers`. I wonder if it would be better to remove this optional parameter, and instead change the logic that implements "implicit `this`" so that when inside an anonymous method, if the identifier is inside an anonymous method, it does a fresh lookup based on the type of `this`.

              That would be a more direct implementation of the semantics we've been discussing, and it would avoid having to add this boolean parameter to the analyzer public API.

              Line 747, Patchset 42:extension on AstNode {

              bool get _isInAnonymousMethod {
              AstNode? currentAstNode = this;
              while (currentAstNode != null) {
              if (currentAstNode is AnonymousMethodInvocation &&
              currentAstNode.parameterName == null) {
              return true;
              }
              currentAstNode = currentAstNode.parent;
              }
              return false;
              }
              }
              Johnni Winther . unresolved

              We need to store this information in the visitor during traversal to avoid running up the parent relation on each lookup.

              This applies to all similar cases below.

              Paul Berry

              +1

              File pkg/analyzer/lib/src/dart/resolver/named_type_resolver.dart
              Line 92, Patchset 44 (Latest): .lookup(prefixName, skipInstanceMembers: true)
              Paul Berry . unresolved

              We shouldn't pass `skipInstanceMembers: true` here. We should pass `true` when in an anonymous method, and `false` otherwise, as we do at other call sites.

              I believe that passing `true` here will reduce the quality of error messages, because for code like `class C { int? x; x? foo; }`, instead of reporting `x isn't a type` (as we do today), we'll report `undefined class x`.

              File pkg/analyzer/lib/src/fasta/ast_builder.dart
              Line 975, Patchset 44 (Latest): formals = createDefaultFormalParameterList();
              Paul Berry . unresolved

              We should be really careful about creating extra AST structures in non-recovery scenarios. A lot of analysis server features rely on the AST structure directly reflecting the input syntax. Really, we ought to call the analyzer's AST structure a "concrete syntax tree".

              In this case, I don't see any harm in leaving `formals` null if the user didn't supply a formal parameter list. This line can be deleted, along with line 985. In which case the local function `createDefaultFormalParameterList` can also be deleted.

              Line 1005, Patchset 44 (Latest): functionDefinition: SyntheticStringToken(
              Paul Berry . unresolved

              I'm confused about why we need to create a synthetic token here. Wasn't the `=>` token in the input syntax? If so, we should use it.

              File pkg/analyzer/lib/src/generated/resolver.dart
              Line 1863, Patchset 44 (Latest): if (isDotShorthand(node)) {
              Paul Berry . unresolved

              I think it should be possible to drop this if-statement, and the corresponding one on line 1920. Anonymous methods can never be dot shorthands.

              Line 1887, Patchset 44 (Latest): node.parameterName?.stringValue ?? 'this',
              Paul Berry . unresolved

              Change `this` to `value`. This string won't appear anywhere but in error messages if the analyzer needs to describe the expected function type, and I think it will be confusing to users if a parameter called "this" appears in the parameter position of a function type.

              Line 1904, Patchset 44 (Latest): analyzeExpression(
              Paul Berry . unresolved

              We shouldn't be analyzing the "function expression" here. This will trigger a bunch of flow analysis logic that makes sense for things that are genuine function expressions (like demoting captured variables), which don't make sense for anonymous methods. We should probably just call `FunctionBodyImpl.resolve` directly.

              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: I0e90a9356508044766d5f4c6e3c413bccbe61796
              Gerrit-Change-Number: 449821
              Gerrit-PatchSet: 44
              Gerrit-Owner: Erik Ernst <eer...@google.com>
              Gerrit-Reviewer: Brian Wilkerson <brianwi...@google.com>
              Gerrit-Reviewer: Erik Ernst <eer...@google.com>
              Gerrit-Reviewer: Johnni Winther <johnni...@google.com>
              Gerrit-Reviewer: Paul Berry <paul...@google.com>
              Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
              Gerrit-Attention: Erik Ernst <eer...@google.com>
              Gerrit-Comment-Date: Tue, 28 Oct 2025 00:01:13 +0000
              Gerrit-HasComments: Yes
              Gerrit-Has-Labels: No
              Comment-In-Reply-To: Johnni Winther <johnni...@google.com>
              unsatisfied_requirement
              satisfied_requirement
              open
              diffy

              Erik Ernst (Gerrit)

              unread,
              Oct 28, 2025, 6:20:07 AM (4 days ago) Oct 28
              to Paul Berry, Brian Wilkerson, Johnni Winther, Commit Queue, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
              Attention needed from Konstantin Shcheglov

              Erik Ernst added 3 comments

              Patchset-level comments
              File-level comment, Patchset 42:
              Erik Ernst . resolved

              Thanks for very useful feedback!

              Konstantin Shcheglov . unresolved

              I have a few concerns about this CL.

              1. We need reference to the specification in the CL description.

              2. We need analyzer tests for parsing, see `ClassDeclarationParserTest`, although here it is not a top-level declaration. But something similar to see AST, parser errors, and recovery.

              3. We need analyzer tests for resolution, see `MethodInvocationResolutionTest`.

              4. The number of changes required to `Scope` and all the places where we use it makes it too complicated. Without good understanding scope rule for this feature I cannot recommend anything specific, but in general a more palatable implementation would be to do some single action like creating a new `XyzScope` at the point where we enter anonymouse block.

              Erik Ernst

              Very good! I wasn't sure about the conventions around where and how to write tests, whether it would have to be in this first CL or could be in subsequent ones, etc, so this information is very useful.

              The specification is under construction, I expect to have a usable document this week.

              I'll take a look at `ClassDeclarationParserTest` and use the tests I have and/or write new ones, and similarly for `MethodInvocationResolutionTest`.

              The changes to the lexical lookup rules may be expressible in a different way. I don't think it is realistic to implement a new kind of scope which would be the current scope of the anonymous method body itself, because the fact that a lexical lookup _starts_ inside an anonymous method should give rise to a different behavior in the body scope of the enclosing class/etc (if any), which could be any number of steps out into enclosing scopes from the place where the search started. The fundamental design choice here is that there is at most one notion of `this` at any given location in code. Currently, in a top-level function, there's no `this`, but if we write an anonymous method then there is one, and it denotes the receiver of the anonymous method invocation (in `e.{... this ...}`, that occurrence of `this` denotes the result of evaluating `e`). This means that if we look up a name `id` from the body of an anonymous method and find (several layers out) an instance member named `id` of the enclosing class, then the search should stop (that is, we don't search the library scope), and the result should be that nothing was found (because we don't have access to the `this` of the class, only the `this` of the anonymous method).

              Paul considered the possibility that this would just fall out automatically if we keep the lexical lookup rules unchanged, and I'll experiment with that. However, that seems to be somewhat dangerous because we may then search for an `id` from an anonymous method, find a declaration of `id` in the enclosing class which is an instance member, return a `ScopeLookupResultImpl` with that as the `getter`, and then we need to know that we're _not_ supposed to call that getter using `this.id` (because `this` does not denote the object that has such a getter), but we're supposed to proceed with the analysis of `this.id` taking the new meaning of `this` into account.

              So the specification may seem to allow for the lexical lookup to go through this scenario and just remain unchanged, but the actual implementation of `Scope.lookup` does return that getter, and that surely can't be right.

              This further motivates the work on the specification, such that we can all know what's the intended behavior. ;-)

              File pkg/linter/lib/src/util/scope.dart
              Line 95, Patchset 42: currentAstNode.parameterName == null) {
              Brian Wilkerson . resolved

              I don't understand the purpose of this part of the condition. Consider adding a comment explaining it.

              Erik Ernst

              Sure, I added a DartDoc comment on `_isInAnonymousMethod`. The point is that the lexical lookup is different when the receiver is named (as in `e.(self) {...}`) and when it is implicit (as in `e.{...}` where the receiver is `this` and may be induced implicitly on expressions).

              Open in Gerrit

              Related details

              Attention is currently required from:
              • 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: I0e90a9356508044766d5f4c6e3c413bccbe61796
              Gerrit-Change-Number: 449821
              Gerrit-PatchSet: 42
              Gerrit-Owner: Erik Ernst <eer...@google.com>
              Gerrit-Reviewer: Brian Wilkerson <brianwi...@google.com>
              Gerrit-Reviewer: Erik Ernst <eer...@google.com>
              Gerrit-Reviewer: Johnni Winther <johnni...@google.com>
              Gerrit-Reviewer: Paul Berry <paul...@google.com>
              Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
              Gerrit-Attention: Konstantin Shcheglov <sche...@google.com>
              Gerrit-Comment-Date: Tue, 28 Oct 2025 10:19:59 +0000
              Gerrit-HasComments: Yes
              Gerrit-Has-Labels: No
              Comment-In-Reply-To: Brian Wilkerson <brianwi...@google.com>
              Comment-In-Reply-To: Konstantin Shcheglov <sche...@google.com>
              unsatisfied_requirement
              satisfied_requirement
              open
              diffy

              Konstantin Shcheglov (Gerrit)

              unread,
              Oct 28, 2025, 1:52:32 PM (3 days ago) Oct 28
              to Erik Ernst, Paul Berry, Brian Wilkerson, Johnni Winther, Commit Queue, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
              Attention needed from Erik Ernst

              Konstantin Shcheglov added 1 comment

              Patchset-level comments
              Konstantin Shcheglov . unresolved

              I have a few concerns about this CL.

              1. We need reference to the specification in the CL description.

              2. We need analyzer tests for parsing, see `ClassDeclarationParserTest`, although here it is not a top-level declaration. But something similar to see AST, parser errors, and recovery.

              3. We need analyzer tests for resolution, see `MethodInvocationResolutionTest`.

              4. The number of changes required to `Scope` and all the places where we use it makes it too complicated. Without good understanding scope rule for this feature I cannot recommend anything specific, but in general a more palatable implementation would be to do some single action like creating a new `XyzScope` at the point where we enter anonymouse block.

              Erik Ernst

              Very good! I wasn't sure about the conventions around where and how to write tests, whether it would have to be in this first CL or could be in subsequent ones, etc, so this information is very useful.

              The specification is under construction, I expect to have a usable document this week.

              I'll take a look at `ClassDeclarationParserTest` and use the tests I have and/or write new ones, and similarly for `MethodInvocationResolutionTest`.

              The changes to the lexical lookup rules may be expressible in a different way. I don't think it is realistic to implement a new kind of scope which would be the current scope of the anonymous method body itself, because the fact that a lexical lookup _starts_ inside an anonymous method should give rise to a different behavior in the body scope of the enclosing class/etc (if any), which could be any number of steps out into enclosing scopes from the place where the search started. The fundamental design choice here is that there is at most one notion of `this` at any given location in code. Currently, in a top-level function, there's no `this`, but if we write an anonymous method then there is one, and it denotes the receiver of the anonymous method invocation (in `e.{... this ...}`, that occurrence of `this` denotes the result of evaluating `e`). This means that if we look up a name `id` from the body of an anonymous method and find (several layers out) an instance member named `id` of the enclosing class, then the search should stop (that is, we don't search the library scope), and the result should be that nothing was found (because we don't have access to the `this` of the class, only the `this` of the anonymous method).

              Paul considered the possibility that this would just fall out automatically if we keep the lexical lookup rules unchanged, and I'll experiment with that. However, that seems to be somewhat dangerous because we may then search for an `id` from an anonymous method, find a declaration of `id` in the enclosing class which is an instance member, return a `ScopeLookupResultImpl` with that as the `getter`, and then we need to know that we're _not_ supposed to call that getter using `this.id` (because `this` does not denote the object that has such a getter), but we're supposed to proceed with the analysis of `this.id` taking the new meaning of `this` into account.

              So the specification may seem to allow for the lexical lookup to go through this scenario and just remain unchanged, but the actual implementation of `Scope.lookup` does return that getter, and that surely can't be right.

              This further motivates the work on the specification, such that we can all know what's the intended behavior. ;-)

              Konstantin Shcheglov

              If we have `AnonymousMethodScope(FunctionBodyScope(InstanceScope(LibraryScope)))`, does it mean that we should just turn off `InstanceScope`, so that it does not lookup anything itself, and always asks the parent? Maybe this is what we should do: before creating `AnonymousMethodScope` instance, walk its parents chain, and mark `InstanceScope` as disabled, and when discarding `AnonymousMethodScope` re-enable `InstanceScope`.

              I read what you wrote above, and suspect that I might have wrong understanding of the scoping rules here, but the idea might still be applicable: do something with scopes in one place, don't force multiple places to pass a flag.

              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: I0e90a9356508044766d5f4c6e3c413bccbe61796
              Gerrit-Change-Number: 449821
              Gerrit-PatchSet: 48
              Gerrit-Owner: Erik Ernst <eer...@google.com>
              Gerrit-Reviewer: Brian Wilkerson <brianwi...@google.com>
              Gerrit-Reviewer: Erik Ernst <eer...@google.com>
              Gerrit-Reviewer: Johnni Winther <johnni...@google.com>
              Gerrit-Reviewer: Paul Berry <paul...@google.com>
              Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
              Gerrit-Attention: Erik Ernst <eer...@google.com>
              Gerrit-Comment-Date: Tue, 28 Oct 2025 17:52:27 +0000
              Gerrit-HasComments: Yes
              Gerrit-Has-Labels: No
              Comment-In-Reply-To: Erik Ernst <eer...@google.com>
              Comment-In-Reply-To: Konstantin Shcheglov <sche...@google.com>
              unsatisfied_requirement
              satisfied_requirement
              open
              diffy

              Paul Berry (Gerrit)

              unread,
              Oct 28, 2025, 6:15:10 PM (3 days ago) Oct 28
              to Erik Ernst, Brian Wilkerson, Johnni Winther, Commit Queue, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
              Attention needed from Erik Ernst

              Paul Berry added 1 comment

              File pkg/analyzer/lib/dart/analysis/features.dart
              Line 13, Patchset 44: static final anonymous_methods = ExperimentalFeatures.anonymous_methods;
              Paul Berry . unresolved

              No action needed from you right now, but I wonder if we should we mark this (and other fields pertaining to experimental features) as `@experimental`. I'm going to ask this question at the next developer experience / model team sync.

              Paul Berry

              I discussed this with Brian, Johnni, and Konstantin today, and we decided that this static field should be marked `@experimental`.

              Here's our reasoning: for features like `anonymous_methods`, that are being worked on but haven't been officially approved by the language team, we want to make sure that in the future, if we decide not to move forward with the feature, we will be able to remove the feature flag without having to do a major version bump of the analyzer. For features like `declaring_constructors`, that _have_ been officially approved but whose implementation is still in progress, we won't mark the `Feature` field as `@experimental`.

              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: I0e90a9356508044766d5f4c6e3c413bccbe61796
              Gerrit-Change-Number: 449821
              Gerrit-PatchSet: 48
              Gerrit-Owner: Erik Ernst <eer...@google.com>
              Gerrit-Reviewer: Brian Wilkerson <brianwi...@google.com>
              Gerrit-Reviewer: Erik Ernst <eer...@google.com>
              Gerrit-Reviewer: Johnni Winther <johnni...@google.com>
              Gerrit-Reviewer: Paul Berry <paul...@google.com>
              Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
              Gerrit-Attention: Erik Ernst <eer...@google.com>
              Gerrit-Comment-Date: Tue, 28 Oct 2025 22:15:06 +0000
              Gerrit-HasComments: Yes
              Gerrit-Has-Labels: No
              Comment-In-Reply-To: Paul Berry <paul...@google.com>
              unsatisfied_requirement
              satisfied_requirement
              open
              diffy

              Erik Ernst (Gerrit)

              unread,
              Oct 30, 2025, 8:40:30 AM (2 days ago) Oct 30
              to Paul Berry, Brian Wilkerson, Johnni Winther, Commit Queue, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
              Attention needed from Johnni Winther, Konstantin Shcheglov and Paul Berry

              Erik Ernst added 24 comments

              Patchset-level comments
              Konstantin Shcheglov . unresolved

              I have a few concerns about this CL.

              1. We need reference to the specification in the CL description.

              2. We need analyzer tests for parsing, see `ClassDeclarationParserTest`, although here it is not a top-level declaration. But something similar to see AST, parser errors, and recovery.

              3. We need analyzer tests for resolution, see `MethodInvocationResolutionTest`.

              4. The number of changes required to `Scope` and all the places where we use it makes it too complicated. Without good understanding scope rule for this feature I cannot recommend anything specific, but in general a more palatable implementation would be to do some single action like creating a new `XyzScope` at the point where we enter anonymouse block.

              Erik Ernst

              Very good! I wasn't sure about the conventions around where and how to write tests, whether it would have to be in this first CL or could be in subsequent ones, etc, so this information is very useful.

              The specification is under construction, I expect to have a usable document this week.

              I'll take a look at `ClassDeclarationParserTest` and use the tests I have and/or write new ones, and similarly for `MethodInvocationResolutionTest`.

              The changes to the lexical lookup rules may be expressible in a different way. I don't think it is realistic to implement a new kind of scope which would be the current scope of the anonymous method body itself, because the fact that a lexical lookup _starts_ inside an anonymous method should give rise to a different behavior in the body scope of the enclosing class/etc (if any), which could be any number of steps out into enclosing scopes from the place where the search started. The fundamental design choice here is that there is at most one notion of `this` at any given location in code. Currently, in a top-level function, there's no `this`, but if we write an anonymous method then there is one, and it denotes the receiver of the anonymous method invocation (in `e.{... this ...}`, that occurrence of `this` denotes the result of evaluating `e`). This means that if we look up a name `id` from the body of an anonymous method and find (several layers out) an instance member named `id` of the enclosing class, then the search should stop (that is, we don't search the library scope), and the result should be that nothing was found (because we don't have access to the `this` of the class, only the `this` of the anonymous method).

              Paul considered the possibility that this would just fall out automatically if we keep the lexical lookup rules unchanged, and I'll experiment with that. However, that seems to be somewhat dangerous because we may then search for an `id` from an anonymous method, find a declaration of `id` in the enclosing class which is an instance member, return a `ScopeLookupResultImpl` with that as the `getter`, and then we need to know that we're _not_ supposed to call that getter using `this.id` (because `this` does not denote the object that has such a getter), but we're supposed to proceed with the analysis of `this.id` taking the new meaning of `this` into account.

              So the specification may seem to allow for the lexical lookup to go through this scenario and just remain unchanged, but the actual implementation of `Scope.lookup` does return that getter, and that surely can't be right.

              This further motivates the work on the specification, such that we can all know what's the intended behavior. ;-)

              Konstantin Shcheglov

              If we have `AnonymousMethodScope(FunctionBodyScope(InstanceScope(LibraryScope)))`, does it mean that we should just turn off `InstanceScope`, so that it does not lookup anything itself, and always asks the parent? Maybe this is what we should do: before creating `AnonymousMethodScope` instance, walk its parents chain, and mark `InstanceScope` as disabled, and when discarding `AnonymousMethodScope` re-enable `InstanceScope`.

              I read what you wrote above, and suspect that I might have wrong understanding of the scoping rules here, but the idea might still be applicable: do something with scopes in one place, don't force multiple places to pass a flag.

              Erik Ernst

              The instance scope should not be turned off when a search originates inside an anonymous method scope, because this would allow a reference to a name `id` to resolve to a declaration in the library scope, even in the case where there is an instance member named `id` declared in the current class. For example, with `int x = 1; class A { String x = ''; void foo() { x.length; /*OK*/ true.{ x.isEven; }; }}` the innermost reference to `x` (part of `x.isEven`) should give rise to an "unknown name" error, it should not resolve to the top-level `x`. So we should treat an instance member of the enclosing class with the required basename as evidence that the search is over and nothing was found, we should not proceed to search the library scope. This result should then give rise to an analysis of `this.id`, which may or may not yield a instance member of the actual `this` in the anonymous method (here: of `true`, so there's no `x`) or an extension member (on `bool`).

              Paul thought that this might actually be the behavior that we'd obtain without changing anything about lexical lookup. The specification does indeed handle the case where an instance member is found in the lexically enclosing syntax by returning "found nothing" and relying on further work based on `this.id`. However, I can see that `EnclosedScope.lookup` returns the getter (rather than getter:null,setter:null) in this situation, which is the reason why I went down the path where `Scope.lookup` is modified. Here's the example:

                  class A {
              int i13579 = 1;
              }
                  class B extends A {
              int j13579 = 2;
              void foo() => i13579 + j13579;
              }

              The method `EnclosedScope.lookup` had the following extra code:

                  if (id.endsWith("13579")) {
              int level = 0;
              Scope? parent = this;
              while (parent != null && parent is EnclosedScope) {
              ++level;
              parent = parent.parent;
              }
              print(
              '>>> $runtimeType($level), getter: $getter, setter: $setter',
              ); // DEBUG
              }

              And it does print out that a getter `j13579` was found, and then it returns a `ScopeLookupResult` holding that getter.

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

              I've addressed a number of comments and taken a step forward in others. There are still more comments that I haven't looked at.

              File pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
              Line 2069, Patchset 42: void endAnonymousMethodInvocation(Token token, Token? functionDefinition) {
              Johnni Winther . resolved

              Rename `token` to `beginToken` and add a `endToken` at the end of the parameter list.

              Erik Ernst

              Done

              Line 2069, Patchset 44: void endAnonymousMethodInvocation(Token token, Token? functionDefinition) {
              Paul Berry . resolved

              I realize that the existing code doesn't often live up to this standard, but I find it really helpful when these listener methods can have documentation indicating the sequence of substructures that the listener can expect to find on the stack.

              E.g., something like:
              ```
              /// Called after the parser has consumed an anonymous method invocation.
              /// Substructures:
              /// - The target of the invocation.
              /// - formal parameters (possibly implicit--see [handleImplicitFormalParameters]).
              /// - The body of the anonymous method (either an expression or a block).
              ```

              Also, I think there should have a named boolean parameter to indicate whether the body is an expression or a block. Without it, the listener is forced to use an `if` test to figure out what kind of body it is.

              Erik Ernst

              Done

              File pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
              Line 6859, Patchset 42: if (isAnonymousMethodsFeatureEnabled &&
              Johnni Winther . resolved

              Add a TODO to remove this from the condition and instead call `reportExperimentNotEnabled` once these feature is planned for release.

              Erik Ernst

              Done

              Line 6859, Patchset 44: if (isAnonymousMethodsFeatureEnabled &&
              Paul Berry . resolved

              There's a lot of code duplication among lines 6859-6878, 7235-7257, and 7279-7302. Can this logic be consolidated into a single helper method?

              Erik Ernst

              Of course, good catch! They were more similar than I had noticed. Done.

              Line 6863, Patchset 42: if (afterDot.isA(TokenType.OPEN_PAREN)) {
              Johnni Winther . resolved

              Add a listener method

                  void beginAnonymousMethodInvocation(Token token);

              and call it here with `dot` as argument.

              Erik Ernst

              Done, added the invocation of the new listener method before the if statement.

              Line 6864, Patchset 42: token = parseFormalParameters(dot, MemberKind.Local);
              Johnni Winther . unresolved

              Why might want a now member kind `MemberKind.AnonymousMethod` for this.

              Erik Ernst

              I'd need a bit of extra info about the implications of doing this (as in "having added `MemberKind.AnonymousMethod`, which other locations will now need to be updated?"). I haven't done anything yet.

              Line 7235, Patchset 42: } else if (isAnonymousMethodsFeatureEnabled &&
              Johnni Winther . resolved

              Add a TODO to remove this from the condition and instead call `reportExperimentNotEnabled` once these feature is planned for release.

              Erik Ernst

              Done, added the TODO in the else part

              Line 7239, Patchset 42: Token afterDots = token.next!;
              Johnni Winther . resolved

              Call `beginAnymousMethodInvocation(cascadeOperator)` here.

              Erik Ernst

              Done

              Line 7280, Patchset 42: if (isAnonymousMethodsFeatureEnabled &&
              Johnni Winther . resolved

              Add a TODO to remove this from the condition and instead call `reportExperimentNotEnabled` once these feature is planned for release.

              Erik Ernst

              Done

              Line 7284, Patchset 42: if (afterPeriod.isA(TokenType.OPEN_PAREN)) {
              Johnni Winther . resolved

              Call `beginAnonymousMethodInvocation(period)` here.

              Erik Ernst

              Done

              File pkg/analyzer/lib/dart/analysis/features.dart
              Line 13, Patchset 44: static final anonymous_methods = ExperimentalFeatures.anonymous_methods;
              Paul Berry . resolved

              No action needed from you right now, but I wonder if we should we mark this (and other fields pertaining to experimental features) as `@experimental`. I'm going to ask this question at the next developer experience / model team sync.

              Paul Berry

              I discussed this with Brian, Johnni, and Konstantin today, and we decided that this static field should be marked `@experimental`.

              Here's our reasoning: for features like `anonymous_methods`, that are being worked on but haven't been officially approved by the language team, we want to make sure that in the future, if we decide not to move forward with the feature, we will be able to remove the feature flag without having to do a major version bump of the analyzer. For features like `declaring_constructors`, that _have_ been officially approved but whose implementation is still in progress, we won't mark the `Feature` field as `@experimental`.

              Erik Ernst

              Makes sense, done!

              File pkg/analyzer/lib/dart/element/scope.dart
              Line 16, Patchset 42: ScopeLookupResult lookup(String id, {bool skipInstanceMembers = false});
              Johnni Winther . unresolved

              Since we cannot mark this as experimental we should add a new method (possibly only to `ScopeImpl`) that handle the new scenario:

                  @experimental
              ScopeLookupResult lookupWithoutInstanceMembers(String id);
              Paul Berry

              @johnni...@google.com
              Why can't we mark this as experimental? I just tried it out and it seemed to work fine.

              Assuming I'm not missing something, I think we should just mark this as experimental.

              Also, I think the name `skipInstanceMembers` is confusing, because it suggests that if an instance member is ofund, the lookup will continue looking for a match at top level. How about if we rename this parameter to `noResultForInstanceMembers`?

              Erik Ernst

              I marked the optional parameter as experimental. Was that what you intended?

              File pkg/analyzer/lib/src/dart/ast/ast.dart
              Line 480, Patchset 44: FunctionExpression get functionExpression;
              Paul Berry . unresolved

              There's no function expression in the grammar here, and I don't think we should synthesize one. Especially because the `FunctionExpression` class has two getters that don't really make sense for anonymous methods: `declaredFragment` and `typeParameters`.

              I think this should be replaced with `FormalParameterList? get formalParameters;` and `FunctionBody get body;`.

              Erik Ernst

              I do create a function expression in order to be able to perform type inference on it, but it might not need to be in the interface of the public class.

              The function expression is helpful in order to be able to perform static analysis on the body in the case where the parameter is declared explicitly (`e.(name) {...}`).

              It is also helpful when type inference is performed on the body: An anonymous method invocation like `e.{ CODE }` works very much like `() { CODE } (e)` where the `CODE` in the body is analyzed with access to a `this` whose type is the static type `T` of `e`. However, `() { CODE } (e)` will analyze the function literal with an unknown return type. With the function expression, it can be subject to type inference using a context type of `C Function(T)` where `C` is the context type schema of the anonymous method invocation as a whole.

              Similarly for `e.(p) { CODE }`, which works very much like `(T p) { CODE } (e)`. In this case the function expression is literally present in the code, and it makes sense to perform the static analysis on it using the support for static analysis on function expressions (such that `p` is in scope and has type `T`). Again, the context type schema of the expression as a whole occurs as the return type in the context type schema for type inference of the function expression.

              That said, I do recognize that there is no guarantee that an anonymous method invocation contains a function expression.

              Further advice is obviously very welcome!

              Line 495, Patchset 44: Token? get parameterName;
              Paul Berry . resolved

              Each input token should appear in the AST structure exactly once. This token is already inside the formal parameter list, so it should be removed from here.

              Erik Ernst

              Done, it was sufficient to have a bool instance variable keeping track of the existence of said parameter declaration.

              Line 521, Patchset 44: with DotShorthandMixin
              Paul Berry . resolved

              I don't think this should be here. Anonymous methods can't be dot short hand invocations.

              Erik Ernst

              Right, I thought they might, but it's probably not useful. Done.

              File pkg/analyzer/lib/src/dart/element/scope.dart
              Line 280, Patchset 44: return ScopeLookupResultImpl(getter: null, setter: null);
              Paul Berry . unresolved

              This seems wrong to me. This causes us to treat getters and setters as no result, whether they are static or not. I think what you want to do is to treat getters, setters, _and_ methods as no result, but only if they are _not static_.

              Erik Ernst

              I added a static member to the class and noted that it did not show up in the `getters` so my conclusion was that static members are not included in this scope. Are static members expected to be found in an `InstanceScope`?

              File pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
              Line 463, Patchset 44: .lookup(node.name, skipInstanceMembers: node._isInAnonymousMethod)
              Paul Berry . unresolved

              I'm getting a little concerned about the number of call sites that need to pass the correct value of `skipInstanceMembers`. I wonder if it would be better to remove this optional parameter, and instead change the logic that implements "implicit `this`" so that when inside an anonymous method, if the identifier is inside an anonymous method, it does a fresh lookup based on the type of `this`.

              That would be a more direct implementation of the semantics we've been discussing, and it would avoid having to add this boolean parameter to the analyzer public API.

              Erik Ernst

              We can't expect to be inside an anonymous method when the instance member of the enclosing class is encountered (and used to determine that the search is complete, and nothing was found).

              Line 747, Patchset 42:extension on AstNode {
              bool get _isInAnonymousMethod {
              AstNode? currentAstNode = this;
              while (currentAstNode != null) {
              if (currentAstNode is AnonymousMethodInvocation &&
              currentAstNode.parameterName == null) {
              return true;
              }
              currentAstNode = currentAstNode.parent;
              }
              return false;
              }
              }
              Johnni Winther . unresolved

              We need to store this information in the visitor during traversal to avoid running up the parent relation on each lookup.

              This applies to all similar cases below.

              Paul Berry

              +1

              Erik Ernst

              I definitely expected that ;-), but didn't know how to do it in a reasonable way. Right now I haven't done it yet. I thought it would be stored as a bit on each simple identifier, or a bit in each scope, but it sounds like there is a better way to do it using a parameter on `visit` and `accept`?

              File pkg/analyzer/lib/src/dart/resolver/named_type_resolver.dart
              Line 92, Patchset 44: .lookup(prefixName, skipInstanceMembers: true)
              Paul Berry . resolved

              We shouldn't pass `skipInstanceMembers: true` here. We should pass `true` when in an anonymous method, and `false` otherwise, as we do at other call sites.

              I believe that passing `true` here will reduce the quality of error messages, because for code like `class C { int? x; x? foo; }`, instead of reporting `x isn't a type` (as we do today), we'll report `undefined class x`.

              Erik Ernst

              Of course, done!

              File pkg/analyzer/lib/src/fasta/ast_builder.dart
              Line 1005, Patchset 44: functionDefinition: SyntheticStringToken(
              Paul Berry . resolved

              I'm confused about why we need to create a synthetic token here. Wasn't the `=>` token in the input syntax? If so, we should use it.

              Erik Ernst

              Done.

              File pkg/analyzer/lib/src/generated/resolver.dart
              Line 1863, Patchset 44: if (isDotShorthand(node)) {
              Paul Berry . unresolved

              I think it should be possible to drop this if-statement, and the corresponding one on line 1920. Anonymous methods can never be dot shorthands.

              Erik Ernst

              So we can't have `.m.{ CODE }` with context type `C` where `C.m` is a static method? Wouldn't that be a situation where `isDotShorthand(node)` is true?

              Line 1887, Patchset 44: node.parameterName?.stringValue ?? 'this',
              Paul Berry . resolved

              Change `this` to `value`. This string won't appear anywhere but in error messages if the analyzer needs to describe the expected function type, and I think it will be confusing to users if a parameter called "this" appears in the parameter position of a function type.

              Erik Ernst

              Done

              Open in Gerrit

              Related details

              Attention is currently required from:
              • Johnni Winther
              • 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: I0e90a9356508044766d5f4c6e3c413bccbe61796
                Gerrit-Change-Number: 449821
                Gerrit-PatchSet: 51
                Gerrit-Owner: Erik Ernst <eer...@google.com>
                Gerrit-Reviewer: Brian Wilkerson <brianwi...@google.com>
                Gerrit-Reviewer: Erik Ernst <eer...@google.com>
                Gerrit-Reviewer: Johnni Winther <johnni...@google.com>
                Gerrit-Reviewer: Paul Berry <paul...@google.com>
                Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
                Gerrit-Attention: Paul Berry <paul...@google.com>
                Gerrit-Attention: Konstantin Shcheglov <sche...@google.com>
                Gerrit-Attention: Johnni Winther <johnni...@google.com>
                Gerrit-Comment-Date: Thu, 30 Oct 2025 12:40:21 +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>
                Comment-In-Reply-To: Johnni Winther <johnni...@google.com>
                unsatisfied_requirement
                open
                diffy

                Johnni Winther (Gerrit)

                unread,
                Oct 30, 2025, 10:39:13 AM (2 days ago) Oct 30
                to Erik Ernst, Paul Berry, Brian Wilkerson, Commit Queue, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
                Attention needed from Erik Ernst, Konstantin Shcheglov and Paul Berry

                Johnni Winther added 1 comment

                File pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
                Line 747, Patchset 42:extension on AstNode {
                bool get _isInAnonymousMethod {
                AstNode? currentAstNode = this;
                while (currentAstNode != null) {
                if (currentAstNode is AnonymousMethodInvocation &&
                currentAstNode.parameterName == null) {
                return true;
                }
                currentAstNode = currentAstNode.parent;
                }
                return false;
                }
                }
                Johnni Winther . unresolved

                We need to store this information in the visitor during traversal to avoid running up the parent relation on each lookup.

                This applies to all similar cases below.

                Paul Berry

                +1

                Erik Ernst

                I definitely expected that ;-), but didn't know how to do it in a reasonable way. Right now I haven't done it yet. I thought it would be stored as a bit on each simple identifier, or a bit in each scope, but it sounds like there is a better way to do it using a parameter on `visit` and `accept`?

                Johnni Winther

                One way of doing this is to record it in a field on the visitor.

                This could be provided as a mixin:

                    mixin InAnynomousMethodMixin {
                int _inAnonymousMethodCounter = 0;

                void enterAnonymousMethod() {
                _inAnonymousMethodCounter++;
                }

                void exitAnonymousMethod() {
                _inAnonymousMethodCounter--;
                }

                bool get isInAnonymousMethod => _inAnonymousMethodCounter > 0;
                }

                which you then have to mixin and call in visitors

                    class ResolutionVisitor 
                extends RecursiveAstVisitor<void>
                with InAnonymousMethodMixin
                {
                ...
                @override
                void visitAnonymousMethod(AnonymousMethod node) {
                node.target?.accept(this);
                enterAnonymousMethod();
                node.functionExpression.accept(this);
                exitAnoymousMethod();
                }
                ...
                }
                Open in Gerrit

                Related details

                Attention is currently required from:
                • Erik Ernst
                • 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: I0e90a9356508044766d5f4c6e3c413bccbe61796
                Gerrit-Change-Number: 449821
                Gerrit-PatchSet: 52
                Gerrit-Owner: Erik Ernst <eer...@google.com>
                Gerrit-Reviewer: Brian Wilkerson <brianwi...@google.com>
                Gerrit-Reviewer: Erik Ernst <eer...@google.com>
                Gerrit-Reviewer: Johnni Winther <johnni...@google.com>
                Gerrit-Reviewer: Paul Berry <paul...@google.com>
                Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
                Gerrit-Attention: Paul Berry <paul...@google.com>
                Gerrit-Attention: Erik Ernst <eer...@google.com>
                Gerrit-Attention: Konstantin Shcheglov <sche...@google.com>
                Gerrit-Comment-Date: Thu, 30 Oct 2025 14:39:07 +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: Johnni Winther <johnni...@google.com>
                unsatisfied_requirement
                open
                diffy

                Konstantin Shcheglov (Gerrit)

                unread,
                Oct 30, 2025, 12:57:47 PM (2 days ago) Oct 30
                to Erik Ernst, Paul Berry, Brian Wilkerson, Johnni Winther, Commit Queue, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
                Attention needed from Erik Ernst and Paul Berry

                Konstantin Shcheglov added 1 comment

                Patchset-level comments
                Konstantin Shcheglov

                Well, "turn off" could be defined in any way we want it :-)

                If the behavior we want is: when we find some `x` in the `InstanceScope` when it is "turned off", then it does not ask its parent (library scope); then we could do
                ```
                class InstanceScope extends EnclosedScope {
                bool isTurnedOff = false;
                  InstanceScope(super.parent, InstanceElement element) {
                element.getters.forEach(_addGetter);
                element.setters.forEach(_addSetter);
                element.methods.forEach(_addGetter);
                }
                  @override
                ScopeLookupResult lookup(String id) {
                if (isTurnedOff) {
                if (_getters[id] != null || _setters[id] != null) {

                return ScopeLookupResultImpl(getter: null, setter: null);
                }
                }
                    return super.lookup(id);
                }
                }
                ```
                Open in Gerrit

                Related details

                Attention is currently required from:
                • Erik Ernst
                • 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: I0e90a9356508044766d5f4c6e3c413bccbe61796
                Gerrit-Change-Number: 449821
                Gerrit-PatchSet: 52
                Gerrit-Owner: Erik Ernst <eer...@google.com>
                Gerrit-Reviewer: Brian Wilkerson <brianwi...@google.com>
                Gerrit-Reviewer: Erik Ernst <eer...@google.com>
                Gerrit-Reviewer: Johnni Winther <johnni...@google.com>
                Gerrit-Reviewer: Paul Berry <paul...@google.com>
                Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
                Gerrit-Attention: Paul Berry <paul...@google.com>
                Gerrit-Attention: Erik Ernst <eer...@google.com>
                Gerrit-Comment-Date: Thu, 30 Oct 2025 16:57:43 +0000
                Gerrit-HasComments: Yes
                Gerrit-Has-Labels: No
                unsatisfied_requirement
                open
                diffy

                Paul Berry (Gerrit)

                unread,
                Oct 30, 2025, 4:47:54 PM (2 days ago) Oct 30
                to Erik Ernst, Brian Wilkerson, Johnni Winther, Commit Queue, Konstantin Shcheglov, dart-analys...@google.com, dart-fe-te...@google.com, dart-uxr...@google.com, rev...@dartlang.org
                Attention needed from Erik Ernst

                Paul Berry added 7 comments

                Patchset-level comments
                File-level comment, Patchset 52 (Latest):
                Paul Berry . unresolved

                It's taking me a long time to review each iteration of this CL. How would you feel about splitting it up into a series of smaller CLs so that we can review and land the feature incrementally?

                File pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
                Line 7112, Patchset 52 (Latest): assert(afterParameters.isA(TokenType.FUNCTION));
                Paul Berry . unresolved

                Thanks for refactoring this out to its own method! Note that my concern about the assertion (from https://dart-review.googlesource.com/c/sdk/+/449821/comment/81220eff_3578818c/) remains.

                File pkg/analyzer/lib/dart/element/scope.dart
                Line 16, Patchset 42: ScopeLookupResult lookup(String id, {bool skipInstanceMembers = false});
                Johnni Winther . unresolved

                Since we cannot mark this as experimental we should add a new method (possibly only to `ScopeImpl`) that handle the new scenario:

                    @experimental
                ScopeLookupResult lookupWithoutInstanceMembers(String id);
                Paul Berry

                @johnni...@google.com
                Why can't we mark this as experimental? I just tried it out and it seemed to work fine.

                Assuming I'm not missing something, I think we should just mark this as experimental.

                Also, I think the name `skipInstanceMembers` is confusing, because it suggests that if an instance member is ofund, the lookup will continue looking for a match at top level. How about if we rename this parameter to `noResultForInstanceMembers`?

                Erik Ernst

                I marked the optional parameter as experimental. Was that what you intended?

                Paul Berry

                Yes, thanks!

                File pkg/analyzer/lib/src/dart/ast/ast.dart
                Line 480, Patchset 44: FunctionExpression get functionExpression;
                Paul Berry . unresolved

                There's no function expression in the grammar here, and I don't think we should synthesize one. Especially because the `FunctionExpression` class has two getters that don't really make sense for anonymous methods: `declaredFragment` and `typeParameters`.

                I think this should be replaced with `FormalParameterList? get formalParameters;` and `FunctionBody get body;`.

                Erik Ernst

                I do create a function expression in order to be able to perform type inference on it, but it might not need to be in the interface of the public class.

                The function expression is helpful in order to be able to perform static analysis on the body in the case where the parameter is declared explicitly (`e.(name) {...}`).

                It is also helpful when type inference is performed on the body: An anonymous method invocation like `e.{ CODE }` works very much like `() { CODE } (e)` where the `CODE` in the body is analyzed with access to a `this` whose type is the static type `T` of `e`. However, `() { CODE } (e)` will analyze the function literal with an unknown return type. With the function expression, it can be subject to type inference using a context type of `C Function(T)` where `C` is the context type schema of the anonymous method invocation as a whole.

                Similarly for `e.(p) { CODE }`, which works very much like `(T p) { CODE } (e)`. In this case the function expression is literally present in the code, and it makes sense to perform the static analysis on it using the support for static analysis on function expressions (such that `p` is in scope and has type `T`). Again, the context type schema of the expression as a whole occurs as the return type in the context type schema for type inference of the function expression.

                That said, I do recognize that there is no guarantee that an anonymous method invocation contains a function expression.

                Further advice is obviously very welcome!

                Paul Berry

                IMHO, a very important principle of the design of the analyzer is that unlike a compiler, it does not lower the code it's analyzing to an intermediate representation in order to do analysis. The reason this is important is because it ensures that any feedback provided by the analyzer (e.g., to the analysis server) accurately reflects the syntactic structure of the code the user provided. This ensures that error and warning locations will be correct, aids in code completions and refactorings in the analysis server, and makes lints easier to write.

                Because I think this is such an important design principle, I'm going to push back pretty hard against creating a function expression here, especially for the case of `e.{ CODE }`, which really doesn't look syntactically like a function expression at all.

                Another reason I think we shouldn't use a function expression here is that the flow analysis we're going to want to do for both `e.{ CODE }` and `e.(p) { CODE }` is pretty substantially different from the flow analysis we would do for function expressions. For example, flow analysis considers any local variable written to by a function expression to be "write captured", and thus it disables all promotions of that local variable inside the function expression and in any flow control paths that follow it. This is necessary for soundness, because in principle after a closure is created, it could in principle execute at any time. Whereas for anonymous methods, since they execute exactly once, at the site where they appear, any local variable writes that occur inside them should be treated as ordinary variable writes, not as write captures.

                Can you go into more detail about what goes wrong if you _don't_ create the synthetic function expression? For example, maybe the are some methods in the resolver that make sense to call when analyzing an anonymous method, and those methods expects to be passed a function expression? If we could look at those methods in detail, I'd be glad to make concrete suggestions about how to generalize them to work with anonymous methods.

                File pkg/analyzer/lib/src/dart/element/scope.dart
                Line 280, Patchset 44: return ScopeLookupResultImpl(getter: null, setter: null);
                Paul Berry . unresolved

                This seems wrong to me. This causes us to treat getters and setters as no result, whether they are static or not. I think what you want to do is to treat getters, setters, _and_ methods as no result, but only if they are _not static_.

                Erik Ernst

                I added a static member to the class and noted that it did not show up in the `getters` so my conclusion was that static members are not included in this scope. Are static members expected to be found in an `InstanceScope`?

                Paul Berry

                That's what I would expect, yes. I would be interested in seeing your test case where a static member of the calss didn't show up in `getters`.

                File pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
                Line 463, Patchset 44: .lookup(node.name, skipInstanceMembers: node._isInAnonymousMethod)
                Paul Berry . unresolved

                I'm getting a little concerned about the number of call sites that need to pass the correct value of `skipInstanceMembers`. I wonder if it would be better to remove this optional parameter, and instead change the logic that implements "implicit `this`" so that when inside an anonymous method, if the identifier is inside an anonymous method, it does a fresh lookup based on the type of `this`.

                That would be a more direct implementation of the semantics we've been discussing, and it would avoid having to add this boolean parameter to the analyzer public API.

                Erik Ernst

                We can't expect to be inside an anonymous method when the instance member of the enclosing class is encountered (and used to determine that the search is complete, and nothing was found).

                Paul Berry
                I'm sorry, I'm not following you here. What I'm proposing is that when resolving a bare identifier:
                - We first call `nameScope.lookup`.
                - If the returned element is something other than an instance member (e.g. a static member, a local variable, or a top level declaration), then we proceed as usual.
                - If the returned element _is_ an instance member:
                - We check if we are in an anonymous method.
                - If we are not in an anonymous method, the we proceed as usual.
                - If we _are_ in an anonymous method, then we proceed as though `nameScope.lookup` had found nothing.
                File pkg/analyzer/lib/src/generated/resolver.dart
                Line 1863, Patchset 44: if (isDotShorthand(node)) {
                Paul Berry . unresolved

                I think it should be possible to drop this if-statement, and the corresponding one on line 1920. Anonymous methods can never be dot shorthands.

                Erik Ernst

                So we can't have `.m.{ CODE }` with context type `C` where `C.m` is a static method? Wouldn't that be a situation where `isDotShorthand(node)` is true?

                Paul Berry

                Ah, sorry. I misunderstood. Yes, I think you are right.

                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: I0e90a9356508044766d5f4c6e3c413bccbe61796
                Gerrit-Change-Number: 449821
                Gerrit-PatchSet: 52
                Gerrit-Owner: Erik Ernst <eer...@google.com>
                Gerrit-Reviewer: Brian Wilkerson <brianwi...@google.com>
                Gerrit-Reviewer: Erik Ernst <eer...@google.com>
                Gerrit-Reviewer: Johnni Winther <johnni...@google.com>
                Gerrit-Reviewer: Paul Berry <paul...@google.com>
                Gerrit-CC: Konstantin Shcheglov <sche...@google.com>
                Gerrit-Attention: Erik Ernst <eer...@google.com>
                Gerrit-Comment-Date: Thu, 30 Oct 2025 20:47:49 +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: Johnni Winther <johnni...@google.com>
                unsatisfied_requirement
                open
                diffy
                Reply all
                Reply to author
                Forward
                0 new messages