Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upRFC: Policy on semver and API evolution #1105
Conversation
This comment has been minimized.
This comment has been minimized.
|
@bstrie, I know you were interested in this. |
This comment has been minimized.
This comment has been minimized.
|
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
reviewed
May 4, 2015
| 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 |
This comment has been minimized.
This comment has been minimized.
sfackler
May 4, 2015
Member
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.
This comment has been minimized.
This comment has been minimized.
aturon
May 11, 2015
Author
Member
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.
sfackler
reviewed
May 5, 2015
| currently private. (Tuple structs with mixtures of public and private fields are | ||
| bad practice in any case.) | ||
|
|
||
| #### Minor change: going from a tuple struct with all private fields (with at least one field) to a normal struct, or vice versa. |
This comment has been minimized.
This comment has been minimized.
sfackler
May 5, 2015
Member
We could also update the compiler to allow both Foo(..) and Foo {..} if all fields are private. If the type's "totally opaque", it kind of makes sense that the kind of struct would be hidden as well.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
nikomatsakis
May 5, 2015
Contributor
Strictly speaking, Foo(..) looks up a match in the value namespace, I believe, though perhaps that is not necessary given our current semantics (basically, for anything where the Foo(..) pattern would be legal, it could also check the type namespace now).
huonw
reviewed
May 5, 2015
|
|
||
| #### Minor change: adding/removing crate dependencies. | ||
|
|
||
| The author is not aware of any possible breakage in altering dependencies (which |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
lilyball
May 5, 2015
Contributor
Perhaps this should just be covered under something like
Major change: any change that requires a nightly when the crate did not previously require a nightly
This includes introducing #[feature] for the first time, or adding/upgrading a dependency which requires a nightly.
This comment has been minimized.
This comment has been minimized.
cmr
May 10, 2015
Member
Additionally, adding/removing dependencies can modify the cargo feature set (not #[feature]) exposed to upstream, which can implicitly cause breaking changes if you accidentally used a #[cfg]d off function.
This comment has been minimized.
This comment has been minimized.
aturon
May 12, 2015
Author
Member
@huonw @kballard Thanks, I will take @kballard's suggestion for the wording here.
@cmr That is an interesting scenario, but I don't think it should be considered a major change: if other crates were relying on the feature without specifying it, they're basically breaking the model (and can be easily fixed by opting into the feature themselves).
huonw
reviewed
May 5, 2015
|
|
||
| Of course, much of the effect of renaming/moving/removing can be achieved by | ||
| instead using deprecation and `pub use`, and the standard library should not be | ||
| afraid to do so!In the long run, we should consider hiding at least some old |
This comment has been minimized.
This comment has been minimized.
sfackler
reviewed
May 5, 2015
| ``` | ||
|
|
||
| because existing uses of `Foo` are shorthand for `Foo<u8>` which yields the | ||
| identical field type. |
This comment has been minimized.
This comment has been minimized.
sfackler
May 5, 2015
Member
This is not actually the case right now since #213 isn't fully implemented:
enum Foo<S = i32> {
Bar,
Baz(S)
}
fn f<S>(_: Foo<S>) {}
fn main() {
f(Foo::Bar);
}~ ❯ rustc test.rs
test.rs:9:5: 9:6 error: unable to infer enough type information about `_`; type annotations required [E0282]
test.rs:9 f(Foo::Bar);
^
error: aborting due to previous error
This comment has been minimized.
This comment has been minimized.
petrochenkov
May 5, 2015
Contributor
Yep, until default type parameters drive type inference, generalization can cause surprisingly large breakage. For example heterogeneous comparisons for Option can't be implemented now because they would require type annotations on None in every comparison and that's a lot of annotations.
Default parameters is an important backward compatibility tool, I hope they'll be finished sooner.
huonw
reviewed
May 5, 2015
|
|
||
| For tuple structs, this is only a minor change if furthermore *all* fields are | ||
| currently private. (Tuple structs with mixtures of public and private fields are | ||
| bad practice in any case.) |
This comment has been minimized.
This comment has been minimized.
reem
reviewed
May 5, 2015
| See "[Signatures in type definitions](#signatures-in-type-definitions)" for some | ||
| general remarks about changes to the actual types in an `enum` definition. | ||
|
|
||
| #### Major change: adding new variants. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
sfackler
May 5, 2015
Member
ErrorKind has an unstable variant that prevents stable code from exhaustively matching on it: https://github.com/rust-lang/rust/blob/master/src/libstd/io/error.rs#L118-L123
sfackler
reviewed
May 5, 2015
| considered a breaking change. Crate authors should consider using Cargo | ||
| "features" for their crate to make such use opt-in. | ||
|
|
||
| #### Minor change: adding/removing crate dependencies. |
This comment has been minimized.
This comment has been minimized.
sfackler
May 5, 2015
Member
A somewhat related concept would be changing the major version of a dependency. It seems like that could be either a minor or major change depending on if the crate is visible in your crate's public API or not.
This comment has been minimized.
This comment has been minimized.
lilyball
May 5, 2015
Contributor
Does Cargo allow multiple versions of the same crate to exist in a single dependency tree, or does it restrict each crate to only resolving to a single version? My assumption has been the latter (although some language package managers do the former, such as npm). If it's the latter, then any major version upgrade for a dependency could be a breaking change if the dependency already exists anywhere else in the upstream crate's dependency tree.
By the same logic, the addition of any dependency (using anything other than * as the version requirement) could be a breaking change.
This comment has been minimized.
This comment has been minimized.
alexcrichton
May 5, 2015
Member
Cargo allows multiple versions of a project, but each version must be semver incompatible with all other activated versions. For example 1.0.0 and 2.0.0 are allowed, but 1.0.0 and 1.1.0 is not.
This comment has been minimized.
This comment has been minimized.
lilyball
May 5, 2015
Contributor
Interesting. So it sounds like it's still possible for the addition/upgrade of a dependency to be an incompatible change if the version requirement depends on anything other than the major version number, e.g. foo = ">1.1.0" would be a breaking change if a different project in the dependency tree had foo = "=1.0.5".
This comment has been minimized.
This comment has been minimized.
aturon
May 12, 2015
Author
Member
Hm, this is a very interesting and somewhat thorny point.
My inclination would be to say that it's a minor change to increase the minor version number as long as the spec is of the form >X.Y.Z, and basically assume that a fully locked-down spec like =X.Y.Z is a corner case that opts out of the API stability guarantees.
Thoughts?
huonw
reviewed
May 5, 2015
|
|
||
| According to the basic principles of this RFC, such a change is minor: it is | ||
| always possible to annotate the call `t.foo()` to be more explicit *in advance* | ||
| using UFCS: `<Trait2>::foo(t)`. This kind of annotation could be done |
This comment has been minimized.
This comment has been minimized.
huonw
May 5, 2015
Member
This would have to be Trait2::foo(t) or <T as Trait2>::foo(t), wouldn't it? (Otherwise it's trying to go via the trait object type?)
huonw
reviewed
May 5, 2015
| All of the changes mentioned below are considered major changes in the context | ||
| of trait methods, since they can break implementors. | ||
|
|
||
| #### Major change: adding new arguments. |
This comment has been minimized.
This comment has been minimized.
huonw
reviewed
May 5, 2015
| #### Minor change: introducing new lint warnings/errors | ||
|
|
||
| Lints are considered advisory, and changes that cause downstream code to receive | ||
| additional lint warnings/errors are still considered "minor" changes. |
This comment has been minimized.
This comment has been minimized.
huonw
May 5, 2015
Member
Worth discussing #[deny(...)] causing compilation errors in more detail? (cc #1029 )
This comment has been minimized.
This comment has been minimized.
aturon
May 12, 2015
Author
Member
I'm not sure whether this RFC is the right place to tackle that infrastructure, but I'll at least put in a reference.
huonw
reviewed
May 5, 2015
|
|
||
| One line of defense against a "minor" change causing significant breakage is the | ||
| nightly release channel: we can get feedback about breakage long before it makes | ||
| even into a beta release. |
This comment has been minimized.
This comment has been minimized.
lilyball
reviewed
May 5, 2015
| #### Major change: adding a private field when all current fields are public. | ||
|
|
||
| This change has the effect of making external struct literals impossible to | ||
| write, which can break code irreparably. |
This comment has been minimized.
This comment has been minimized.
lilyball
May 5, 2015
Contributor
FWIW, there is a way around this. The obvious answer is to implement Default for the struct, allowing literals of the form Foo { a: 1, b: 2, ..Default::default() }.
This solution won't work for struct literals found in const or statics (although a const containing a default value for the struct would). But there's plenty of other changes you can make to structs that would break struct literals found in const or static but not break struct literals found elsewhere (for example, adding a public field that has no public value that can be used in a const or static). Given that, requiring that any change not break the ability to use struct literals in const / static might be considered overly restrictive (especially as most types will never find themselves used in that fashion). And if that restriction is not enforced, then it seems plausible to treat a pre-existing implementation of Default as allowing for changes that would otherwise break struct literals.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
lilyball
May 12, 2015
Contributor
@pnkfelix Oh. I actually had never even seen RFC 736. I missed that change completely.
Incidentally, is there some reason that this was disallowed completely, instead of only for types that aren't Copy? Using FRU for a Copy type is equivalent to copying it and mutating the public fields. I'll file an RFC on it. (Update: Filed as #1117)
This comment has been minimized.
This comment has been minimized.
pnkfelix
May 12, 2015
Member
@kballard (i don't think there was any reason beyond adopting the "simplest" change that could possibly work, where "simplest" is measured according to some hand-wavy ordering w.r.t. the description of the language itself)
Gankro
reviewed
May 5, 2015
| ## Behavioral issues | ||
|
|
||
| - Is it permitted to change a contract from "abort" to "panic"? What about from | ||
| "panic" to "return an `Err`"? |
This comment has been minimized.
This comment has been minimized.
Gankro
May 5, 2015
Contributor
Exceedingly little code can even distinguish between an abort and a panic, so I wouldn't expect this to be a serious problem in practice. The only thing I can see being trouble is unsafe code, which can legitimately rely on the fact that something aborted to avoid setting up guards against unwinding. In such a case this could lead to UB! However if we had no_unwind assertions or something unsafe code could at least guard against such a change. Although adding no_unwind assertions would make this change even-more-breaking!
panic -> Err seems like a tricky semantic change that can cause weird error-handling bugs. For one, if API A declares that it panics on input X, and API B uses API A but also transitively reports the panic in one of its APIs for input Y, its documentation will at best be incorrect after an upgrade: it no longer panics on Y.
Otherwise you may just get bad error handling results from things like "what I thought was an effectively exhaustive match no longer is (new Error kinds are possible -- basically a soft version of adding a variant to an enum)" or "The system reports frobs are out of sync on error X since this is the only possibility in 1.0, but since 1.1 it can now also mean frams are misaligned (old Error kinds are now more overloaded)". This seems like a major breaking change from a semantic perspective.
oli-obk
reviewed
May 5, 2015
| ``` | ||
|
|
||
| This is especially useful for the case where multiple modules being glob | ||
| imported happen to export items with the same name. |
This comment has been minimized.
This comment has been minimized.
oli-obk
May 5, 2015
Contributor
This could rather be solved by importing neither, but noting the name. When the code uses an item with that name, an error "item not imported due to conflicting glob imports" could list all possibilities and suggest adding an explicit use
This comment has been minimized.
This comment has been minimized.
P1start
reviewed
May 5, 2015
|
|
||
| #### Major change: adding new fields to a variant. | ||
|
|
||
| If the enum is public, so is the full contents of all of its variants. As per |
This comment has been minimized.
This comment has been minimized.
P1start
reviewed
May 5, 2015
| At the moment, Rust does not provide defaulted arguments, so any change in arity | ||
| is a breaking change. | ||
|
|
||
| #### Minor change: introducing a new type parameter. |
This comment has been minimized.
This comment has been minimized.
P1start
May 5, 2015
Contributor
I believe that considering this a minor change this goes against the overview’s ‘principles of the policy’:
That means that any breakage in a minor release must be very "shallow": it must always be possible to locally fix the problem through some kind of disambiguation that could have been done in advance (by using more explicit forms) or other annotation (like disabling a lint). It means that minor changes can never leave you in a state that requires breaking changes to your own code.
As far as I know, there’s not always a way of ‘fix[ing] the problem through some kind of disambiguation that could have been done in advance’ for this kind of change. To explain with an example, if the breaking change example mentioned in the RFC (adding an extra type parameter to fn foo<T>) occurred in the standard library between, say, Rust 1.3 and 1.4, and my library (which depended on std) had code that called foo with an explicit type parameter (like foo::<u8>()), I’d have no way of fixing my code in a way that continues to support Rust 1.3 but also supports the newest version of Rust. In other words, I’d have to make a choice between supporting the older versions of Rust that I supported and supporting the newer versions (which have an extra type parameter on foo).
The section mentioned above does say ‘in principle’, but it also says that the RFC should suggest ‘additional tooling or language support’, neither of which seems to be outlined in the RFC to address this particular problem.
This comment has been minimized.
This comment has been minimized.
oli-obk
May 5, 2015
Contributor
In almost all situations I can think of, you can probably use type ascription either in the parameters or in the return value. Any situations where this isn't enough probably have global state and are abusing generic code.
This comment has been minimized.
This comment has been minimized.
P1start
May 6, 2015
Contributor
I disagree. To give a more concrete example, imagine that std provided a function for calculating the hash of a value:
pub fn hash<T>(value: &T) -> u64 where T: Hash {
let mut h = SomeHasher::new();
value.hash(&mut h);
h.finish()
}Let’s pretend that I have a library (which depends on std) that has code that looks like hash::<u8>(1). Now, in Rust 1.4, the function above has a new type parameter added to make it generic over the hasher used:
pub fn hash<T, H>(value: &T) -> u64 where H: Default + Hasher, T: Hash {
let mut h: H = Default::default();
value.hash(&mut h);
h.finish()
}According to the RFC, this would be a minor change. However, there is no way for me to update my code in a way that supports both 1.3 and 1.4—in 1.4, I have to specify the second type parameter, but in 1.3, I can’t.
I suppose this doesn’t apply to most functions (only those where not all type parameters can be inferred), but I think that the RFC should at least specify that this is only a minor change if there is a way of inferring the type of all type parameters (new and old).
This comment has been minimized.
This comment has been minimized.
lilyball
May 7, 2015
Contributor
@P1start Your example there can infer its type parameter, and your example invocation hash::<u8>(1) won't work to begin with.
This comment has been minimized.
This comment has been minimized.
huonw
May 8, 2015
Member
I wonder if we could allow hinting only a prefix of the generic type parameters, this would make situations like this where the new type parameter is inferrable always just work. I have at least one API where this would be useful myself (functions are usually called like either foo::<X, _>(), with the _ essentially never needing to be specified).
This comment has been minimized.
This comment has been minimized.
P1start
May 8, 2015
Contributor
@kballard The second type parameter doesn’t seem to be inferred when using std’s existing Hash[er] traits. And the invocation should have been hash::<u8>(&1) (but that’s just a mistake and is beside the point).
This comment has been minimized.
This comment has been minimized.
lilyball
May 8, 2015
Contributor
@P1start I was referring to that first code snippet. With the second code snippet, the addition of a non-inferrable type parameter would of course be a breaking change, and I would expect anyone making such a change to provide a default value for the type parameter (or if they really don't want to, then to consider it a major version bump).
This comment has been minimized.
This comment has been minimized.
|
@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
reviewed
May 5, 2015
| 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, |
This comment has been minimized.
This comment has been minimized.
nagisa
May 5, 2015
Contributor
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.
This comment has been minimized.
This comment has been minimized.
pnkfelix
May 11, 2015
Member
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.
SimonSapin
reviewed
May 5, 2015
| "panic" to "return an `Err`"? | ||
|
|
||
| - Should we try to lay out more specific guidance for behavioral changes at this | ||
| point? |
This comment has been minimized.
This comment has been minimized.
SimonSapin
May 5, 2015
Contributor
There are behavior changes like #23951 Changing the meaning of the count to splitn that are not breaking per the definition in this RFC (they do not cause downstream code to fail to compile), but still should be considered major as they break basic expectations that downstream code could reasonably make.
Unfortunately I don’t see a clear criteria to distinguish those from behavior changes that are more reasonable or expected like changing results of char::is_alphabetic when updating to a new Unicode version.
This comment has been minimized.
This comment has been minimized.
aturon
May 5, 2015
Author
Member
@SimonSapin Did you see the earlier section on behavioral changes? The rough guideline would be that changes that break the explicit, documented behavioral contract of a function are considered breaking.
This comment has been minimized.
This comment has been minimized.
|
I very much love this RFC. Nice work @aturon! |
Havvy
reviewed
May 6, 2015
| 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 |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
theemathas
commented
May 6, 2015
|
What happens if someone finds another way to cause unsafty using safe code and the standard library? We already had |
tbu-
reviewed
May 6, 2015
|
|
||
| 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). |
This comment has been minimized.
This comment has been minimized.
tbu-
May 6, 2015
Contributor
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.
This comment has been minimized.
This comment has been minimized.
huonw
May 6, 2015
Member
I suspect that is the same problem discussed below: https://github.com/rust-lang/rfcs/pull/1105/files#r29635875
This comment has been minimized.
This comment has been minimized.
|
Should this mention changing an object-safe trait in such a way that it is no longer object-safe? |
This comment has been minimized.
This comment has been minimized.
theemathas
commented
May 6, 2015
|
What about changing an unsafe function to a safe function? |
This comment has been minimized.
This comment has been minimized.
ruuda
commented
May 7, 2015
|
There are two angles to versioning, and I think the difference is important:
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:
|
This comment has been minimized.
This comment has been minimized.
|
It would be kind of nice to include a machine readable API change file in minor updates. Cargo could use this to at least prevent silent breakage. Theoretically, cargo could also use this to automatically disambiguate but I don't know if we really want to rewrite user code and take responsibility for any bugs that might result (we'd have to be REALLY careful and would probably want to prompt the user for every change). |
alexcrichton
referenced this pull request
May 17, 2015
Merged
syntax: Remove unused `packed` attribute #25541
aturon
added
the
T-libs
label
May 22, 2015
mdinger
referenced this pull request
May 22, 2015
Open
IntoIterator should be implemented for [T; N] not just references #25725
This comment has been minimized.
This comment has been minimized.
|
Sorry for the delayed responses, I'm digging out from a bunch of stuff near the 1.0 release. One general question that @wycats has raised offline with me is: do we need to require a full implementation of elaboration before we can fully embrace the policy here? Certainly this RFC is strengthened by various implementation work (glob import refinements probably being the most important), but my feeling is that we can adopt this basic framework even without working elaboration, but be especially judicious with checking changes against Crater for breakage. But I'd be curious to hear others' thoughts on this. Regarding macros: this is definitely something we should think about, but I'm much less confident about what to say there at the moment, and we are also relatively conservative about the macros we export from
Hm, I don't think so -- most of the breakage in the runup to 1.0 would fall into the "requires major version bump", I believe.
That's a good point. It may be worth further specifying which minor changes need a look on Crater. In particular, simply adding a public item shouldn't require it, even though it could break glob imports -- partly because we should make globs more robust, but partly because we wouldn't be deterred from making a change for that reason (I don't think). Whereas adding a defaulted method to a trait should definitely be tested on Crater for conflicts. Regarding the existing regression reports: I was imagining this happening during prototyping/early implementation, rather than after landing in nightly. But maybe it's enough to land PRs directly to nightly as assess the breakage there, and then consider yanking breaking changes well before stabilization. One other thing to keep in mind: a stable build still ships with all of the nightly APIs; it just lints on them. That means that basically all breaking changes would be immediately apparent on stable builds too; there's not a lot of margin for error here.
Yes, it's possible, though @nrc took some pains to future-proof resolution for exactly this reason. And yes, I think these can largely be considered "bug fixes". But we should try to do them soon.
Yes, I would agree -- in particular, if we assume that upgrading from 1.0 to 1.1 is itself not breaking (in a major way), then requiring that upgrade shouldn't count either.
Yep, we definitely need some implementation work in this area to make this RFC fully fly.
Seems fair, but even better would be to land the equivalent first-class language features. :) |
This comment has been minimized.
This comment has been minimized.
comex
commented
May 29, 2015
|
An idea: The original version of #1122 proposed having a Rust version attribute in each crate's Cargo.toml. That has since been removed in favor of a more minimal PR, but suppose it ends up happening. What if rustc automatically versioned the standard library based on that number, preventing minor changes from actually breaking anything (in a better way than elaborated source, see below)? All
The last two sound a bit ugly, but I think it should be fairly rare for such changes to existing items to be made in the first place. Implementation of the type inference change sounds like it could be a challenge. Edit: (...Perhaps a better solution for those would be to just allow entirely separate declarations that apply to versions < and >= X, rather than any messing with type inference or template parameters.) So why go to this effort, if all minor changes are designed to break little code in the first place? A few reasons:
Edit: The same mechanisms could be adapted for use by independent crates. They ought to have equivalent ways to mark things stable or not anyway... nothing special about the standard library in its desire to introduce experimental features without committing to them. |
alexcrichton
added
the
final-comment-period
label
Jun 2, 2015
This comment has been minimized.
This comment has been minimized.
|
This RFC is now entering the week-long final-comment period. |
This comment has been minimized.
This comment has been minimized.
|
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) .) |
This comment has been minimized.
This comment has been minimized.
|
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! |
alexcrichton
merged commit 384e749
into
rust-lang:master
Jun 10, 2015
bluss
referenced this pull request
Jul 6, 2015
Closed
nightly rustc breaks stable code for some type inferences #26279
oli-obk
referenced this pull request
Aug 18, 2015
Merged
turn statically known erroneous code into a warning and continue normal code-generation #1229
aturon
referenced this pull request
Sep 25, 2015
Open
Amend API semver RFC to discuss "OIBITs" #1295
This comment has been minimized.
This comment has been minimized.
|
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. |
aturon commentedMay 4, 2015
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