Skip to content

go: don't change the libraries in 1.18 #48918

@robpike

Description

@robpike
Contributor

The 1.18 release of the Go language is likely to include by far the biggest change to the language since its creation: parametric polymorphism, colloquially called generics. There has been much discussion about how the core libraries will adapt, and how to make that adaptation. See #45955 and #48594 for example, and there are others already and sure to be more soon.

How to use these ideas in the standard library requires great thought and planning. Putting them in the library now also adds a significant burden to rolling out the release.

I propose that we do not update the libraries in 1.18.

The reason is simple and compelling: It's too much to do all at once, and we might get it wrong. The language changes have been worked on in some form for over a decade, but the library changes are very new, and we have no experience with the use of the new types in Go on which to base a strong case for their design. Yes, we can reason about them at length and much has been done. Experience with other languages helps, but one thing Go has taught us is that it grows its own ways of doing things.

For generics, we don't know what those new ways are yet. Also, the compatibility promise makes the cost of getting any detail wrong quite high. We should wait, watch, and learn.

Instead, I propose we still design, build, test, and use new libraries for slices, maps, channels, and so on, but start by putting them in the golang/x/exp repository. That way, these new libraries - which are truly experimental at this stage - can be tested in production, but can be changed, adapted, and grown for a cycle or two, letting the whole community try them out, if they are interested and willing to accept a little instability, without requiring every detail of every component to be ready from day one. Once they have soaked a bit, and updated through experience, we move them into the main repo as we have done with other externally-grown packages, but with the confidence that they work well in practice and are deserving of our compatibility promise.

I realize everyone wants to get their hands on the fun of the new language feature, and is looking forward to fixing some of the issues in the core libraries that will be less clumsy once it arrives, but I strongly believe it is best to take it slow for now. Use, learn, study, and move cautiously.

Activity

ALTree

ALTree commented on Oct 12, 2021

@ALTree
Member

Agree. For example, it looked like we were going to add a few new things like constraints.Slice and constraints.Map, which I found really ugly (but thought were necessary), but now after #48424 it looks like they may be not needed (See #48424 (comment)), which is great! And this happened last week (#48424 was accepted 5 days ago).

To me this suggests we don't yet fully understand how the current generics implementation (and possible refinements that may be implemented in the near future) would influence the design of these new libraries; so it may be premature to commit to an API for them. Putting them in x/exp seems like a prudent move.

added
NeedsDecisionFeedback is required from experts, contributors, and/or the community before a change can be made.
on Oct 12, 2021
added this to the Go1.18 milestone on Oct 12, 2021
earthboundkid

earthboundkid commented on Oct 12, 2021

@earthboundkid
Contributor

The slices package has been whittled down to a very functional core. For example, it has no Map or Filter because those weren’t obviously useful. I think it’s good to ship as is. Dropping it now just adds delay for no real reason.

Similarly, if constraints isn’t part of 1.18, there will be a lot of independent redefinitions of orderable types. I don’t think we’re going to learn from experience much that could change that package now.

I agree though that container/set can wait for another cycle (iteration is still up in the air), and probably many or all other changes.

mvdan

mvdan commented on Oct 12, 2021

@mvdan
Member

This reminds me of the transition done to error values via https://golang.org/x/xerrors, which I think worked really well.

Just one question: would these x packages allow backwards incompatible changes? If so, I think putting in x/exp and clearly documenting them as such would be fine. If they'll follow backwards compatibility guarantees, much like x/xerrors did, then perhaps I'd place them under a new module such as x/generics or x/typeparams.

I'd personally lean towards a new module with backwards compatibility guarantees. Otherwise, it would be risky for Go modules to start using and relying on them, as they may break at any moment. Especially when it comes to libraries, as they can't "pin" a specific version due to MVS. If we learn from past mistakes and want to remove or redesign APIs, we should simply deprecate, and do the backwards incompatible changes in bulk when moving the APIs to the standard library.

jaloren

jaloren commented on Oct 12, 2021

@jaloren

I concur with this proposal. More concretely, I doubt we should be adding generic libraries or updating existing ones until we have an answer to #48287. And getting an answer to that discussion likely requires time and experimentation from the community .

The one exception may be the constraints library, which strike me as an essential part of the generics design and would severely degrade developer ergonomics without it.

Having x/generics module with backwards compat guarantees sounds like an excellent idea.

mvdan

mvdan commented on Oct 12, 2021

@mvdan
Member

Another advantage of an external module is that, if a proposed new API gets accepted and implemented, users on Go 1.18 or later can start relying on it the moment it hits the master branch, instead of waiting 3+ months until the next Go release is out with its standard library changes.

andig

andig commented on Oct 12, 2021

@andig
Contributor

How to use these ideas in the standard library requires great thought and planning. Putting them in the library now also adds a significant burden to rolling out the release.
I propose that we do not update the libraries in 1.18.

I understood rob doesn't want to change the existing libraries. It seems a good idea to introduce new ones and potentially NOT promise to keep them or their api for one or two releases. That will gain more real-world feedback.

thepudds

thepudds commented on Oct 12, 2021

@thepudds
Member

For example, it looked like we were going to add a few new things like constraints.Slice and constraints.Map, which I found really ugly (but thought were necessary), but now after #48424 it looks like they may be not needed (See #48424 (comment)), which is great! And this happened last week (#48424 was accepted 5 days ago).

Minor: that proposal is in "likely accept", and not yet accepted, though there is a prototype.

Separately, if the new packages do start at x/… (x/generics, x/exp or something else), hopefully they could be tagged to clearly communicate to tools and to humans any backwards compatibility intentions that apply at that import path location (e.g., perhaps something like v0.1.0 ~soon, and v1.0.0 when go1.18 is released, with an option to move to v2 at the x/… location if warranted, which helps with library importers and so on).

When those capabilities land in the standard library, or if there is a v1 to v2 change at x/…, ideally migration for clients could be handled via cmd/go’s hopefully-not-too-distant automatic API migration (initially described here and more recently discussed here).

EDIT: FWIW, I think everything I wrote above is cleaner if the repo is not x/exp, but instead new separate x/something repo(s).

doggedOwl

doggedOwl commented on Oct 12, 2021

@doggedOwl

Why does it have to be a blanket decision? There are some proposed changes that might need some more work and for those it's reasonable to be in x/* but IMO there are some proposals like the slices package who are reasonably well defined and would be very helpful to have since the start.

mvdan

mvdan commented on Oct 12, 2021

@mvdan
Member

@doggedOwl one way to look at it is that Go 1.18 is already a huge release, with generics in the language and fuzzing support. And drawing the line around what generic APIs are fully ready to be frozen is hard, especially when we have had close to no experience with them being used in the wild.

bitfield

bitfield commented on Oct 12, 2021

@bitfield

I made the following comment on #45955, which I think supports Rob's point:

The first step in designing any API... should be to write a number of non-trivial programs using it; ideally, programs that solve real problems. The right design will tend to emerge from looking at those programs (or, at worst, it will save you a few iterations on the design).
I suggest that we find, or try to come up with, some realistic programs involving slice operations, and see what they would look like using the various proposed APIs in the slices library. This is likely to make their advantages and disadvantages much clearer to the casual reader.

Unfortunately, responders to that issue were not able, or not willing, to supply any such programs (so far as I'm aware). I think the best way to get them is to put something in the x tree, as suggested, and let people use it for a while.

The kind of programs I'm talking about are not merely examples cooked up to demonstrate how a certain feature would work. They are demonstrations that such a feature is necessary, widely useful, and worth the cost in additional complexityβ€”a quality bar that has traditionally applied to all Go proposals, not just this one. I see no reason it shouldn't apply here.

Not to labour the point, but it's always surprising to me how long and carefully I can think about some design a priori, and then the moment I actually try to use it, I find it's instantly obvious that I've designed the wrong thing. That's not just me being dumb (though of course that's a factor): it's simply inevitable.

Releasing a draft API in 'experimental' mode is exactly the right thing to do here. When it becomes clear to us all that that API needs to change in several important respects (I'm happy to put money on this outcome if anyone seriously doubts it), it will still be possible to make those changes. The moment it goes into the standard library, that door is closed forever.

Measure twice, cut once.

ianlancetaylor

ianlancetaylor commented on Oct 12, 2021

@ianlancetaylor
Contributor

@carlmjohnson I agree that container/set should not go into 1.18. I just edited the discussion (#47331) to say as much.

I am also inclined to say that we should not add type parameters to any existing standard library packages for 1.18, especially given #48287.

But I do personally think that we need the constraints package at least in 1.18. Many uses of type parameters are going to need the constraints package. I see no advantage to using an x repo for constraints, which will force us to retain a pair of packages for some time going forward.

So I think that for 1.18 this proposal is really about the slices and maps packages. Just my own opinion, of course.

neild

neild commented on Oct 12, 2021

@neild
Contributor

Putting the proposed Go 1.13 error changes in golang.org/x/exp/xerrors was very useful for validating the API before committing to it.

However, applying the compatibility guarantee to the x/exp package made it impossible to iterate on the API. The eventual changes to the errors package in Go 1.13 differed from the xerrors prototype in various ways, but xerrors only permitted validating that initial draft. I think this was a mistake.

Testing out new designs in x/exp or some other non-std repo is an excellent idea, but next time let's do it in a way that allows us to iterate on the design, whether that means frequent versioning (set/v1, set/v2, etc.) or accepting that incompatible changes will be made to the experimental package to keep it in sync with the eventual design.

43 remaining items

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsDecisionFeedback is required from experts, contributors, and/or the community before a change can be made.genericsIssue is related to generics

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @JakubOboza@borud@neild@bitfield@andig

        Issue actions

          go: don't change the libraries in 1.18 Β· Issue #48918 Β· golang/go