Repository navigation
spec: for-range iterator yield function requires bool result - consider generalizing to any boolean type #71164
Description
Activity
- addedLanguageChangeSuggested changes to the Go languageSuggested changes to the Go languageNeedsDecisionFeedback is required from experts, contributors, and/or the community before a change can be made.Feedback is required from experts, contributors, and/or the community before a change can be made.
on Jan 7, 2025 - addedearly-in-cycleA change that should be done early in the 3 month dev cycle.A change that should be done early in the 3 month dev cycle.
on Jan 7, 2025 Change https://go.dev/cl/640599 mentions this issue:
go/types, types2: require iterator yield to return bool (work-around)Related Issues
Related Code Changes
- go/types, types2: require iterator yield to return bool (work-around)
- spec: document for range loop over functions
Related Documentation
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Reacted by Robert GriesemerWe 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?
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.
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.Reacted by Mateusz Poliwczak, Tom Thorogood, Robert Griesemer, Alan Donovan, Eric Lagergren, Olivier Mengué, Will Faught and fzipp@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.Seqanditer.Seq2.- added a commit that references this issue
on Jan 8, 2025 To be fair, this is already an issue one level up, with named yield func types:
https://go.dev/play/p/3euYnrwXP1PReacted by Robert Griesemer and zigo101- addedLanguageProposalIssues describing a requested change to the Go language specification.Issues describing a requested change to the Go language specification.
on Jan 10, 2025 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.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.
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
ControlFlowwas an alias forbooland not a new type, so our old library iterators could often be used with the newfor rangesyntax. But the alternative would also have been quite reasonable code.Depending on the outcome here we may need to reconsider #77542.
Per the spec, a "for-range" statement using an iterator requires the iterator's
yieldfunction to returnboolnot an arbitrary (user-defined) boolean: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.