Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.
Sign upproposal: cmd/doc: add "// Unstable:" prefix convention #34409
Comments
Due to the lack of stability guarantees provided for service Server and Client interfaces, as hightlighted in #2318 and #3024, this change adds a godoc line that both warns users and suggests the canonical workaround. The structure of the godoc text is styled after an open proposal, golang/go#34409, thus may need to be changed, but attempts to play well with the tooling ecosystem, as was done for deprecated with golang/go#10909.
Due to the lack of stability guarantees provided for service Server and Client interfaces, as hightlighted in grpc/grpc-go#2318 and grpc/grpc-go#3024, this change adds a godoc line that both warns users and suggests the canonical workaround. The structure of the godoc text is styled after an open proposal, golang/go#34409, thus may need to be changed, but attempts to play well with the tooling ecosystem, as was done for deprecated with golang/go#10909.
Due to the lack of stability guarantees provided for service Server and Client interfaces, as hightlighted in grpc/grpc-go#2318 and grpc/grpc-go#3024, this change adds a godoc line that both warns users and suggests the canonical workaround. The structure of the godoc text is styled after an open proposal, golang/go#34409, thus may need to be changed, but attempts to play well with the tooling ecosystem, as was done for deprecated with golang/go#10909.
This comment has been minimized.
This comment has been minimized.
cc @jba We've talked about having apidiff ignore changes to definitions that are annotated like this. I imagine it would be useful for other tools as well. |
This comment has been minimized.
This comment has been minimized.
What are next steps for getting approval for this proposal? |
This comment has been minimized.
This comment has been minimized.
@carnott-snap I don't think this really needs to go through the formal proposal process. It's something we agree on and discussed already as part of the apidiff and gorelease design. I think the next step would be for this to be implemented in This should be documented somewhere, but I'm not sure where yet. We should have documentation on preparing a release, linked from https://golang.org/doc/. That should basically be a checklist, and gorelease can refer to it in error messages. These stability comments could be mentioned there. About the specifics on the comments: I agree that |
This comment has been minimized.
This comment has been minimized.
Is it worth getting this closed/tagged as
Does Google want to own the dev work? If not, I am happy to contribute.
Long term it would be nice to mentioning this as part of the module release docs item in #33637. But for now, I think we can follow the lead that
Totally agree, may be worth getting a wider audience, but one acceptable word seems better than two perfect ones.
IIRC, doc comments rules will not allow it to be the first paragraph, though |
This comment has been minimized.
This comment has been minimized.
Adding "// Unstable:" has a much larger effect than "// Deprecated:". "// Unstable" is much more invasive. It says "even though you might think otherwise, I reserve the right to change the types/code here in the future or delete it entirely and break your uses." If you don't see the comment, it's a very big deal: you upgrade and your code breaks. The big question is not what the comment syntax should be but whether we want to bless this kind of user-hurting behavior at all. An alternative would be to develop experimental changes like this on explicitly experimental version tags (v1.6.1-unstable, for example), keeping the unstable code completely out of the stable tag. Another alternative would be to put the name into the defined symbols, like "mypkg.UnstableFoo", like we did for types like testing.InternalBenchmark (before internal directories). It's impossible to miss the Unstable when it's in the name. We should very carefully consider what the right way is to let package authors experiment without hurting users. A simple comment does not seem like enough. (I realize that the idea is tools would surface the comment etc but then that's just more mechanism on top, whereas versions or symbol names that explicitly say unstable reuse existing mechanism.) |
This comment has been minimized.
This comment has been minimized.
Note that there are already at least a few examples of unstable definitions in the standard library. For example, consider:
|
This comment has been minimized.
This comment has been minimized.
As another data point, there are also several symbols in the
These definitions are only meant to be called by generated code that is tightly coupled with the However, some definitions like the ones Bryan mentioned may have their own definition of compatibility. According to apidiff, changing the value of an integer constant is an incompatible change because it may be used as an array length. Using |
This comment has been minimized.
This comment has been minimized.
@rsc I'm not sure what the next step is. It doesn't sound like the proposal committee has accepted or rejected this. What information would be useful in making a decision? |
This comment has been minimized.
This comment has been minimized.
As a data point. In the protobuf module, there are several types or functions explicitly marked as being for internal use only. However, they must be exported in order for generated code to access them. We reserve the right to change those APIs with the caveat that we don't break existing usages that were properly generated by protoc-gen-go. Whether this convention is adopted or not, this type of sharp edge already exists. In v1 the sharp edge is awful since the internal functions is placed alongside public functions in the |
This comment has been minimized.
This comment has been minimized.
@jayconrod I think that what might be helpful is a reason why you can't use names like |
This comment has been minimized.
This comment has been minimized.
@ianlancetaylor My expectation is that I'm planning to ship an experimental version of |
This comment has been minimized.
This comment has been minimized.
Sorry if this is an unhelpful comment, but the cmd/api tool in the standard library does have a way to suppress false positives, for the kinds of examples that @bcmills cites above. See the files in https://golang.org/api/ . |
This comment has been minimized.
This comment has been minimized.
|
This comment has been minimized.
This comment has been minimized.
I didn't mean anything special about the exact word |
This comment has been minimized.
This comment has been minimized.
The (IMO pretty major) downside of putting words like (It's the same reason we don't distinguish between |
This comment has been minimized.
This comment has been minimized.
It's much better to use branches for experimental features. This makes 2 worlds(stable and experimental) independent and reduces possible mistakes for the user. As Russ mentioned above: comment is too weak to protect user from incorrect usage. Extending previous comment by Bryan: In other words: comments or unstable api increases code entropy which increases code maintainability. |
This comment has been minimized.
This comment has been minimized.
I built this proposal around documentation to make adoption less invasive. This was partially based on experience with the protobuf libraries, where they define custom compatibility guarantees. I agree condoning unstable interfaces is troublesome, but many projects require it, and I wanted a canonical way to label/identify it, both for users and tooling. It may be helpful to isolate the use cases that exist for instability: (please correct me if I left anything out or if this is a false trichotomy)
I think we all agree that we want stable packages, but even the standard library is developing experimental or long term unstable features. Most examples use documentation to signal their stability, so this seemed intuitive and canonical. What emphasis should be placed on supporting existing patterns, as opposed to preventing undesirable behaviour? Outstanding concerns:
|
This comment has been minimized.
This comment has been minimized.
The proposal committee's job is to help steer a discussion toward consensus, not to decide on their own. It sounds like there is no consensus here yet. I wrote a lot about this topic at https://research.swtch.com/proposals-experiment. It's very important that people know they are using experimental features. Otherwise we run the risk of hitting the situation Rust did where everyone was on "unstable". I have the same concern about the "exp" build tag in #35704: it's too easy to lapse into where everything uses this. Actually the build tag may be worse, since if any dependency super far down uses exp, you have to do the same. So basically everyone will have to use it. |
This comment has been minimized.
This comment has been minimized.
I would like to be clear about the purposes of the two tickets being discussed:
My concern is that the current state of things is not good. Major tools are actively developing and releasing unstable features, by
Would a
I have worked with Rust myself and do not see this today. Are there any lessons we can learn from their experiences? My understanding was that they had a lot of important features that needed to be stabilised, e.g. async, and that finally unlocking things from the nightly compiler was the fix.
Since #35704 is trying to solve a different problem, would you mind continuing the discussion there? I broke it out partially because I saw two heterogeneous problems (pre-release and custom compatibility) that felt like they may should be solved differently. |
What did you see today?
Many projects have different stability guarantees for the exported symbols in a package. Others rely on generated code that cannot, or will not, give stability guarantees. As such, most authors will document this pre-release or instability in doc strings, but the syntax and conventions are all over the place.
The standard library likes to reference the
Go compatibility promise
orGo 1 compatibility guidelines
, since it is bound by them, however these do not work well for community packages. Other terms likenon-portable
andEXPERIMENTAL
are descriptive and well explained inunsafe
andsyscall/js
respectively.Some community libraries have used terms like
// Alpha: ...
,// Beta: ...
, and// Unstable: ...
, which work as well. There could be an argument for not releasing pre-release features on a stable branch, but other times like with the proto client/serverinterfaces
, instability is a guarantee that must be worked around.What would you like to see?
Similar to
// Deprecated: ...
, I would like to see the stabilization of supported comment tags for unstable symbols.They support the same three formats that same three formats that deprecation has.
These tags should also allow such symbols to be excluded from the
gorelease
tool.A single tag should be sufficient:
// Unstable: ...
When interacting with released, finalized symbol that cannot or will not be stabilized, the description can provide stability workarounds, alternatives, or what guarantees should be expected.
When interacting with pre-release features, a proposed timeline can be given or alternatives for customers requiring stability guarantees.
What did not work?
The
// Alpha: ...
and// Beta: ...
options looked promising, since they would only be used for temporary instability as part of the release process. The two terms overload one another (what is the difference between alpha, beta, and// PreRelease: ...
?), leading to confusion. Furthermore, the programmatic benefits of knowing an API will stabilize in a future release is not that useful, "is it unstable now?" is more important.The
// Experimental: ...
syntax used by the standard library implies the notion that the feature will eventually be stabilized. This further overloads it with alpha, beta, etc. and does not fit the needs of the above gRPC interfaces.The
// NonPortable: ...
syntax is too domain specific tounsafe
to make sense for purely semantic changes to packages. It makes sense forunsafe
, but does not generalize