RFC: Policy on semver and API evolution by aturon · Pull Request #1105 · rust-lang/rfcs (original) (raw)

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation99 Commits15 Checks0 Files changed

Conversation

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters

[ Show hidden characters]({{ revealButtonHref }})

aturon

This RFC proposes a comprehensive set of guidelines for which changes to
stable APIs are considered breaking from a semver perspective, and which are
not. These guidelines are intended for both the standard library and for the
crates.io ecosystem.

This does not mean that the standard library should be completely free to make
non-semver-breaking changes; there are sometimes still risks of ecosystem pain
that need to be taken into account. Rather, this RFC makes explicit an initial
set of changes that absolutely cannot be made without a semver bump.

Along the way, it also discusses some interactions with potential language
features that can help mitigate pain for non-breaking changes.

The RFC covers only API issues; other issues related to language features,
lints, type inference, command line arguments, Cargo, and so on are considered
out of scope.

Rendered

@aturon

@aturon

@aturon

cc @reem @carllerche -- I think both of you have also expressed some opinions on this topic as well. (This is an important piece of policy, so I want to ensure good visibility).

sfackler

to disambiguate are not automatically "major" changes. (But in such cases, one
must evaluate how widespread these "minor" changes are).
* In principle, it should be possible to produce a version of the code for any

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A slightly weaker way of phrasing this would be "given knowledge of any change, it should be possible to write a version of your code that works both before and after that change". It seems to me like that phrasing is significantly more important to guarantee than the version written, since it means libraries won't be "forced" to abandon old versions of Rust to support new versions.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's also an important constraint, and I'll try to rewrite to clarify.

That said, what's gradually becoming clear to me with this RFC is that we may be able to make a strictly stronger guarantee: that all minor but breaking changes can be worked around automatically with an elaboration process. (I think with a couple of very minor language features, we can get there.) Having a strong guarantee that you don't have to go make changes to your dependencies when you upgrade Rust -- while allowing the standard library to grow -- seems like a great place to be.

@nikomatsakis

@aturon I'll go over in detail, but one thought I had is that it might be useful to elaborate a kind of "best practices for forwards compatibility". That's probably not part of this RFC, but it might help illuminate nonetheless.

nagisa

Along the way, it also discusses some interactions with potential language
features that can help mitigate pain for non-breaking changes.
The RFC covers only API issues; other issues related to language features,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: redundant paragraph. Language, lints, type inference, CLI are not part of standard library (first paragraph), nor they are a part of crates.io ecosystem.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the past, for better or worse, sometimes changes to things like command line arguments to rustc were for various reasons classified as "library issues" (as opposed to language issues).

(Also, the list here covers things that might be part of semantic versioning for the Rust language itself -- I think the rules there still remain unwritten. So given that the title of this RFC is "policy on semver ...", it is natural for a reader to perhaps wonder if these issues are in fact addressed...)

While the first paragraph does indeed restrict the domain to "standard library" and "crates.io ecosystem", I think this paragraph can stay -- perhaps just modify it to make it clear that this paragraph is in fact a consequence a fact that all these things are not part of the standard library nor crates.io ecosystem.

@BurntSushi

I very much love this RFC. Nice work @aturon!

Havvy

Adding any item without a default will immediately break all trait implementations.
It's possible that in the future we will allow some kind of
"[sealing](#sealed-traits)" to say that a trait can only be used as a bound, not

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This link is dead.

@theemathas

What happens if someone finds another way to cause unsafty using safe code and the standard library? We already had thread::scoped and Vec::drain.

tbu-

As with "[Signatures in type definitions](#signatures-in-type-definitions)",
traits are permitted to add new type parameters as long as defaults are provided
(which is backwards compatible).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not true, consider the change to Iterator::sum, which (even though it specifies a default for the type parameter) can't be inferred everywhere.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@apasel422

Should this mention changing an object-safe trait in such a way that it is no longer object-safe?

@theemathas

What about changing an unsafe function to a safe function?

@ruuda

There are two angles to versioning, and I think the difference is important:

  1. Given that the next release will not be major, can we include this change?
  2. Given that we are going to include this change, what should the version number for the next release be?

If I understand the release train model correctly, the version number is determined before changes that will be included in that version are made, so Rust is in scenario 1. If major bumps are going to be uncommon, then it makes sense to downplay some technically breaking changes as minor.

For Crates.io, I expect the vast majority of crates to be in scenario 2. I think the pragmatic approach is a good one; adding a public item without changing anything else certainly feels like a new feature, not like a backwards incompatible change. However, to play the devil’s advocate: there appears to be a hidden assumption that a major version bump is bad and should be avoided. I agree that backwards incompatible changes should be avoided if possible, but this RFC is about naming only. If a change is technically breaking and will be included in the next release, the only question is what the version number should be. Why downplay technically breaking changes as minor? To quote the sidebar rules:

5 . Chill out! A programming language version number is a silly thing to get upset over.

@alexcrichton

This RFC is now entering the week-long final-comment period.

@huonw

I'm in favour, but I think that we will definitely want to be "quick" to make amendments (to the process, even if we don't literally change the text here) in future as we gain more experience, and as the ecosystem/community changes.

(I'm also a little nervous about #1105 (comment) .)

@comex comex mentioned this pull request

Jun 5, 2015

@alexcrichton

The consensus of the library subteam is to merge this RFC. We may tweak the specifics here and there over time, but there is broad consensus among the core ideas behind this RFC and minor updates are always fine to make later!

@bluss bluss mentioned this pull request

Jul 6, 2015

@aturon

It occurred to me today that this RFC did not take into account the impact of "OIBIT" traits (which have a .. impl). In particular, these traits can introduce downstream sensitivity to every aspect of a data type's representation, even if that representation is private.

Effectively, OIBITs make it possible for downstream crates to make promises on behalf of upstream crates that can easily be broken.

I don't think this should change anything about the policy itself, but it'd be worth amending the RFC to discuss it.

RFC issue

@sgrif sgrif mentioned this pull request

Dec 12, 2017

sgrif added a commit to sgrif/rfcs that referenced this pull request

May 30, 2018

@sgrif

RFC rust-lang#1023 introduced rules that exclude impls which should clearly be valid. It also used some ambiguous language around what is a breaking change, that ended up being completely ignored and contradicted by rust-lang#1105. This RFC seeks to clarify what is or isn't a breaking change when it comes to implementing an existing trait, and conservatively expands the orphan rules to allow impls which do not violate coherence, and fit within the original goals of rust-lang#1023.

[Rendered]

sgrif added a commit to sgrif/rfcs that referenced this pull request

May 30, 2018

@sgrif

RFC rust-lang#1023 introduced rules that exclude impls which should clearly be valid. It also used some ambiguous language around what is a breaking change, that ended up being completely ignored and contradicted by rust-lang#1105. This RFC seeks to clarify what is or isn't a breaking change when it comes to implementing an existing trait, and conservatively expands the orphan rules to allow impls which do not violate coherence, and fit within the original goals of rust-lang#1023.

@sgrif sgrif mentioned this pull request

May 30, 2018

@Ixrec Ixrec mentioned this pull request

Dec 11, 2018

This was referenced

Jan 17, 2020

@lcdr lcdr mentioned this pull request

Sep 1, 2021

@lcdr lcdr mentioned this pull request

Oct 28, 2021

6 tasks

Labels

A-stability

Proposals relating to policy and changes about stability of features.

A-versioning

Versioning related proposals & ideas

final-comment-period

Will be merged/postponed/closed in ~10 calendar days unless new substational objections are raised.

T-libs-api

Relevant to the library API team, which will review and decide on the RFC.