Skip to content

spec: for-range iterator yield function requires bool result - consider generalizing to any boolean type #71164

Description

@griesemer

Per the spec, a "for-range" statement using an iterator requires the iterator's yield function to return bool not an arbitrary (user-defined) boolean:

Range expression                                       1st value                2nd value

array or slice      a  [n]E, *[n]E, or []E             index    i  int          a[i]       E
string              s  string type                     index    i  int          see below  rune
map                 m  map[K]V                         key      k  K            m[k]       V
channel             c  chan E, <-chan E                element  e  E
integer value       n  integer type, or untyped int    value    i  see below
function, 0 values  f  func(func() bool)
function, 1 value   f  func(func(V) bool)              value    v  V
function, 2 values  f  func(func(K, V) bool)           key      k  K            v          V

We should generalize this to any boolean type, similarly to how we allow any string type (not just string) when we range of strings.

Note that the original implementation of the type-checker accepted any boolean type, but the compiler's front-end had a problem with it (#71131). The (temporary) fix for that issue was to adjust the type-checker to match the spec literally. This avoided a compiler panic.

We should change the spec to reflect the original intent, and then revert the fix for #71131.

Activity

  1. added
    LanguageChangeSuggested changes to the Go language
    NeedsDecisionFeedback is required from experts, contributors, and/or the community before a change can be made.
    on Jan 7, 2025
  2. added this to the Backlog milestone on Jan 7, 2025
  3. self-assigned this
    on Jan 7, 2025
  4. modified the milestones: Backlog, Go1.25 on Jan 7, 2025
  5. added
    early-in-cycleA change that should be done early in the 3 month dev cycle.
    on Jan 7, 2025
  6. gopherbot commented on Jan 7, 2025

    @gopherbot
    Contributor

    Change https://go.dev/cl/640599 mentions this issue: go/types, types2: require iterator yield to return bool (work-around)

  7. gabyhelp commented on Jan 7, 2025

    @gabyhelp
  8. dolmen commented on Jan 8, 2025

    @dolmen
    Contributor

    We should generalize this to any boolean type, similarly to how we allow any string type (not just string) when we range of strings.

    I'm not convinced by this. Generalizing implies a incompatible change that will affect introspecting at runtime (using reflect) functions that might be iterators.

    So could you develop why allowing any bool derived type would be better? What use case does that open?

  9. griesemer commented on Jan 8, 2025

    @griesemer
    ContributorAuthor

    The implementation (type checkers, at least) were written from the start to accept any boolean type. The compiler front-end has a bug that causes it to panic when a user-defined boolean is used (#71131). Fixing that bug at this stage of the 1.24 release cycle is risky, so we opted for reporting an error in the type-checker, which is very safe, and which avoids a compiler panic in favor of a very clear error message. We should really fix the compiler front-end (early 1.25 cycle) and then we can also relax this restriction again. I don't know that there are particular issues with reflect at this point since such code didn't work anyway.

  10. seankhliao commented on Jan 8, 2025

    @seankhliao
    Member

    Is allowing this really good for the ecosystem? these iterators wouldn't be assignable to iter.Seq / iter.Seq2 and would not be composable with any of the iterator helpers out there.
    It seems strange to allow for covariant result types in this specific corner of the language when its disallowed elsewhere with a faq entry for it.

  11. griesemer commented on Jan 8, 2025

    @griesemer
    ContributorAuthor

    @seankhliao That is a good point - I haven't thought about that (I simply opened this issue to document that we changed the original implementation, which allowed for user-defined types, were it not for the bug in the compiler front-end).

    We may want to leave things as they are now (TBD).

    As an aside, we wouldn't bring in covariance into the language, we'd just allow any boolean type as result type for the specific yield function. But of course, that yield function wouldn't play well with iter.Seq and iter.Seq2.

  12. rothelius commented on Jan 8, 2025

    @rothelius

    To be fair, this is already an issue one level up, with named yield func types:
    https://go.dev/play/p/3euYnrwXP1P

  13. added
    LanguageProposalIssues describing a requested change to the Go language specification.
    on Jan 10, 2025
  14. gopherbot commented on Feb 3, 2025

    @gopherbot
    Contributor

    This issue is currently labeled as early-in-cycle for Go 1.25.
    That time is now, so a friendly reminder to look at it again.

  15. rogpeppe commented on Feb 28, 2025

    @rogpeppe
    Contributor

    FWIW I agree with @seankhliao's reservations. I'd like to see a solid use case for this before it happens, whatever the intention of the original code.

  16. modified the milestones: Go1.25, Backlog on Jun 10, 2025
  17. rothelius commented on Oct 31, 2025

    @rothelius

    FWIW I agree with @seankhliao's reservations. I'd like to see a solid use case for this before it happens, whatever the intention of the original code.

    Even before Go 1.23 introduced functional iterators we were implementing iterators similarly, aided, for clarity, by:

    package controlflow
    
    type ControlFlow = bool
    
    const (
    	Continue ControlFlow = true
    	Break ControlFlow = false
    )
    

    We were lucky that ControlFlow was an alias for bool and not a new type, so our old library iterators could often be used with the new for range syntax. But the alternative would also have been quite reasonable code.

  18. griesemer commented on Feb 19, 2026

    @griesemer
    ContributorAuthor

    Depending on the outcome here we may need to reconsider #77542.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

LanguageChangeSuggested changes to the Go languageLanguageProposalIssues describing a requested change to the Go language specification.NeedsDecisionFeedback is required from experts, contributors, and/or the community before a change can be made.early-in-cycleA change that should be done early in the 3 month dev cycle.

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions