# RFC: give up on SemVer

**URL:** https://discourse.julialang.org/t/rfc-give-up-on-semver/103536
**Category:** Internals & Design
**Tags:** semver
**Created:** [September 5, 2023, 8:25am UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536 "2023-09-05T08:25:41Z")
**Posts on this page:** 17
**Page:** 2

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [September 5, 2023, 7:14pm UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/22 "2023-09-05T19:14:06Z")

</div>

> [@ShalokShalom](#):
>
> I imagined we could version individual functions.

For `using Library` or `Library.addition` to not break, it would have to export only version 1 forever. And I think it’ll hurt productivity if we have to specify explicit numbers one by one just to avoid code breaking in new versions.

> [@Tamas\_Papp](#):
>
> You make a valid point, so let me rephrase: changes to Julia which could have been considered technically breaking for real-life code have been so _minor_ that in practice they do not matter much, especially because their impact has been assessed before merging them.

Where is the line, though? As fierce the argument has been about SemVer, I think we’re all in agreement that “we can break anything” is not the way to go, that there is a point between that and ideal SemVer adherence (,and closer to the latter). But how do we calculate and agree on whether a breaking change is minor? Should we make a list of measures that we should do before considering a breaking change e.g. deprecating obsolete names?

---

<div class="post-metadata">

### Author: ![ShalokShalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shalokshalom/32/52462_2.png) [@ShalokShalom](https://discourse.julialang.org/u/ShalokShalom)
#### Post date: [September 5, 2023, 7:20pm UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/23 "2023-09-05T19:20:07Z")

</div>

> [@Benny](#):
>
> For `using Library` or `Library.addition` to not break, it would have to export only version 1 forever.

I honestly think `using` is a horrible mistake anyway, but that leads to another topic.  
Does it break `import`?

> [@Benny](#):
>
> And I think it’ll hurt productivity if we have to specify explicit numbers one by one just to avoid code breaking in new versions.

Well, do we really want to live in a world, where things break so often, that “it hinders productivity” when we enter the version, at which the function still worked?

And this even includes, that you assume we would rather just use the old version, rather than updating.  
As said in another thread, has the Linux kernel solved to stay API compatible for a couple of decades.  
Why does this seem to be not such a priority in Julia?

A lot of the criticism I read, has talked about that topic.  
It seems like it pushes people away.

Isn’t this something to tackle?

---

<div class="post-metadata">

### Author: ![ShalokShalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shalokshalom/32/52462_2.png) [@ShalokShalom](https://discourse.julialang.org/u/ShalokShalom)
#### Post date: [September 5, 2023, 7:23pm UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/24 "2023-09-05T19:23:54Z")

</div>

> [@Benny](#):
>
> But how do we calculate and agree on whether a breaking change is minor? Should we make a list of measures that we should do before considering a breaking change, e.g. deprecating obsolete names?

The Elm video I posted, makes a proposal to exactly that.

The API break is determined by a change in the type system, and I imagine we could add tests to the equation.

Once you break the API in Elm, by changing the type signature, you automatically push the package with a major version increase.

This is done by the packaging tool.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [September 5, 2023, 7:29pm UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/25 "2023-09-05T19:29:59Z")

</div>

> [@ShalokShalom](#):
>
> Does it break `import`?

Yes, that’s why I said `Library.addition`.

> [@ShalokShalom](#):
>
> And this even includes, that you assume we would rather just use the old version, rather than updating.

It’s not that we would rather default to version 1 forever, it’s necessary to avoid breaking code across versions. If I write `Library.addition(1,2)`, and upgrading `Library` makes that code give a different result, then it’s breaking. The only way to avoid that is to guarantee the same results across all the versions, in which case it’s just public API and there’s absolutely no reason to keep any obsolete versions. I think that’s what you intended in your example (put text in code blocks instead of screenshots, makes it easier to quote), and FYI changing `addition(x,y)=x+y` to `addition(a,b)=a+b` is not a breaking change. This isn’t different from how things are done already.

---

<div class="post-metadata">

### Author: ![ShalokShalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shalokshalom/32/52462_2.png) [@ShalokShalom](https://discourse.julialang.org/u/ShalokShalom)
#### Post date: [September 5, 2023, 7:34pm UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/26 "2023-09-05T19:34:15Z")

</div>

Yeah, I didn’t intend to write breaking change, just threw out some lines.  
Its late here, and I think my point was more about making the functions versioned, rather the libraries.  
It might be, that this has no sensible benefits.

---

<div class="post-metadata">

### Author: ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)
#### Post date: [September 5, 2023, 7:53pm UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/27 "2023-09-05T19:53:22Z")

</div>

In order to give a more objective basis to this discussion, it would be very nice to have a list of those “technically breaking changes” that have been included so far in Julia releases. In this moment I don’t even know if it is a long or a short list.

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [September 5, 2023, 7:56pm UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/28 "2023-09-05T19:56:57Z")

</div>

[https://github.com/JuliaLang/julia/issues?q=is%3Amerged+label%3A%22minor+change%22+](https://github.com/JuliaLang/julia/issues?q=is%3Amerged+label%3A%22minor+change%22+)

---

<div class="post-metadata">

### Author: ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)
#### Post date: [September 5, 2023, 8:07pm UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/29 "2023-09-05T20:07:10Z")

</div>

Thanks, but that is the list of changes labelled as “minor”. Are all those changes technically breaking in the sense that @Tamas_Papp meant?

---

<div class="post-metadata">

### Author: ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)
#### Post date: [September 5, 2023, 8:13pm UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/30 "2023-09-05T20:13:03Z")

</div>

> [@Tamas\_Papp](#):
>
> **We should be upfront and explicit about this, instead of pretending that we stick to SemVer.**
> 
> What should Julia promise instead? I am opening this discussion to work that out, but my basic proposal is that as long as the major version number does not change, breaking changes will be
> 
> 1. infrequent, and only happen for minor releases ✅
> 2. announced in a prominent position in the release notes,
> 3. relatively minor and cosmetic ✅
> 4. checked for registered packages, the authors of which will be notified in advance ✅
> 5. easy to locate and potentially update with tooling,
> 6. easy to work around so that all versions can be supported ✅

I don’t understand how this is a change to the status quo. Reasonable people already understand that any change whatsoever [may be breaking](https://xkcd.com/1172/). Semver are soft guarantees, up to the judgement of the maintainers. That’s basically what the [risk tolerance](https://julialang.org/blog/2019/08/release-process/#risk_tolerance_personas) post is about. Announcing “we don’t follow Semver” sends the wrong message. You can be an honest person without always replying every mundane question with 100% accuracy.

As industrial julia users, the minor breaking changes to julia so far have been entirely in line with expectations. Sometimes we hold off on upgrading. That’s just a regular Monday in software engineering.

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [September 5, 2023, 8:14pm UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/31 "2023-09-05T20:14:03Z")

</div>

> [@mbauman](#):
>
> [Issues · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues?q=is%3Amerged+label%3A%22minor+change%22+)

It’s important context that the “standardized entry point” PR was originally _also_ marked as a `minor change`. So either the label is not accurate, or we’re not good at assigning those labels and should be better (though I do want to emphasize that @mbauman also was the one removing that label and adding `breaking` instead).

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [September 5, 2023, 8:14pm UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/32 "2023-09-05T20:14:47Z")

</div>

Looks like the discourse onebox munged my link. I’ve edited it. The “minor change” label is trying to identify exactly this — things that are technically breaking but have been deemed acceptable or a minor release.

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [September 5, 2023, 8:16pm UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/33 "2023-09-05T20:16:36Z")

</div>

> [@mbauman](#):
>
> The “minor change” label is trying to identify exactly this — things that are technically breaking but have been deemed acceptable or a minor release.

I think that should be highlighted in the label description - it currently only mentions behavioral changes, nothing about minor breakages:

![image](https://global.discourse-cdn.com/julialang/original/3X/3/b/3b4623101dfcfc81064e0acb10ef886fe7de4f89.png)

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [September 5, 2023, 8:17pm UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/34 "2023-09-05T20:17:07Z")

</div>

> [@Sukera](#):
>
> It’s important context that the “standardized entry point” PR was originally _also_ marked as a `minor change`. So either the label is not accurate, or we’re not good at assigning those labels and should be better (though I do want to emphasize that @mbauman also was the one removing that label and adding `breaking` instead).

In my view it _was_ accurate until it was reverted. It was retrospectively deemed too breaking to be a minor change.

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [September 5, 2023, 8:21pm UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/35 "2023-09-05T20:21:59Z")

</div>

> [@mbauman](#):
>
> In my view it _was_ accurate until it was reverted. It was retrospectively deemed too breaking to be a minor change.

Right, it definitely was a fitting label until we discovered that it wasn’t - which kind of gels with the theme of this thread about having to do better in anticipating the consequences a change really has 🙂 I.e., less cowboy attitude, more careful planning & defensive progress.

In my view, there is no one person at fault here - it’s the current (extremely informal) process that could have easily caught this particular instance, e.g. via a PkgEval. To me, that means there’s room for improvement in the process here.

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [September 5, 2023, 8:30pm UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/36 "2023-09-05T20:30:55Z")

</div>

This didn’t get released. It was briefly on a development branch. [PkgEval did flag it](https://github.com/JuliaLang/julia/pull/50974#issuecomment-1704630517), and there would’ve been many more hurdles for it to pass before even getting close to landing on a release.

For the good and the bad, open source means you see the floor of the sausage factory and can even participate in it.

---

<div class="post-metadata">

### Author: ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)
#### Post date: [October 9, 2023, 11:39am UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/37 "2023-10-09T11:39:18Z")

</div>

Any change, or at least addition to an _exported_ API (of Julia), is potentially (actually, technically, in fact) a breaking change.

Major languages, like C++ break compatibility all the time, also Python and Java. An exception might be Clojure, but it has full immutability, persistent data structures, i.e. features helping never needing breaking changes (and almost minimal syntax, and doesn’t need to add to it).

It’s an ideal to not break code, or do it so that very few users notice.

Python is in the process of dropping some outdated stdlibs, in 3.x, so it’s not just making breaking changes to its C API.

> <https://stackoverflow.com/questions/16506411/was-there-ever-a-breaking-change-in-the-java-language-specification>

> **[Breaking bad? Semantic versioning and impact of breaking changes in Maven...](https://link.springer.com/article/10.1007/s10664-021-10052-y)**
>
> Just like any software, libraries evolve to incorporate new features, bug fixes, security patches, and refactorings. However, when a library evolves, it may break the contract previously established with its clients by introducing Breaking Changes...

> in its API. These changes might trigger compile-time, link-time, or run-time errors in client code […]  
> We identify and address some limitations of the original protocol and expand the analysis to a new corpus spanning seven more years of the MCR. We also present a novel static analysis tool for Java bytecode, **Maracas** , […]  
> contrast with the original study and show that 83.4% of these upgrades do comply with semantic versioning. Furthermore, we observe that the tendency to comply with semantic versioning has significantly increased over time. Finally, we find that most BCs affect code that is not used by any client, and that only 7.9% of all clients are affected by BCs.

C++ and other _separately_ compiled languages, i.e. ahead of time, are in a special position. They can go with breaking API and it only affects developers. They are however famously afraid of, or against breaking the ABI, making C++ slower than it could be, thus not living up to its ideal “you don’t pay for what you don’t use”.

That said, I think Julia should strive for the SemVer ideal, to not break before 2.0.

> [@jakobnissen](#):
>
> The ecosystem will likely split according to Julia version, as large parts of the ecosystem stick to the LTS releases to avoid the hassle of upgrading

I’m not sure I understand this part. I don’t think a large fraction of users stick to [Julia] LTS releases, but since you mentioned “of the ecosystem” did you mean there are LTS packages? Some such as DataFrames.jl strive to still support Julia 1.6 LTS, but there’s no need I think. They can target (1.9 or) 1.10 now that will become the next LTS.

Julia has reproducability for any version, not just LTS, so people can e.g. program for 1.9 (or 1.3 for Cxx.jl…) and keep using it forever, with the Manifest for their project.

To me it’s a bonus if you can upgrade Julia, and yes ideally it would just work. I think it does except for some very few packages that pirate the internals of Julia. However, those foundational packages are used by many in the ecosystem, so in effect it affects most. It’s non-ideal, but I believe can always be handled by upgrading packages (in the past there was an exception Cxx.jl, that people no longer use).

Now about the potential breakage in Julia. If it adds an _exported_ function or macro say named `KsdhsSF2efD` then it’s relatively safe. But if it adds such a function or macro named e.g. `S`, then it has a large probability of conflicting. In either case PkgEval is run and it will likely be found to be conflicting, but only for registered packages using the same name, so since some packages are private, there’s just no way to be 100% sure for any addition to the _exported_ API. Julia recently added the `public` keyword, so now non-exported functions and macros can be added without them exported, but would people be ok with e.g. Base.new\_thing(), for any additions, as I suggested? I got downvoted on that suggestion at JuliaLang. People do not like fully-qualified for everything new from now on. I think that may be done in Clojure (and C++ and Python) for at least new stuff.

The same argument applies to packages, they can’t _export_ new things, technically speaking without updating the the major version according to SemVer.

> [@jakobnissen](#):
>
> Stop breaking people’s code, and be more explicit about what is guaranteed behaviour.

What should be guaranteed? Julia adds things all the time, with e.g. “available in Julia 1.11”, and I think all new additions should be marked Experimental, or at least implicitly. Then documented as such globally on new additions. Julia is getting a new stdlib StyledStrings. At first a new string type S"content" was proposed (then as _exported_; from Base). Its S\_str macro conflicted with a known registered package and would have been trouble. It was renamed styled\_str, and it’s NOT exported. You might think we’re ok, but even the name of the stdlib StyledStrings is in a global scope so that you can import it. Then we are kind of stuck with that name. Arguable if it’s not good, then instead of renaming a stdlib (or function or macro) we could rename as a synonym, and keep the old name just for compatibility. I would rather want to avoid accumulating too much such old cruft, why I recommend all additions are not committed to until next release, or later, for this 1.12 (or 1.13?). Who ever made the perfect API the first time around?

What Rick Hickey is talking about arguing against SemVer, is deletion (or changes) to API, as never really needed. He’s not arguing against additions, but I think he would agree with _exported_, i.e. _unqualified_ additions.

---

<div class="post-metadata">

### Author: ![vchuravy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vchuravy/32/8_2.png) [@vchuravy](https://discourse.julialang.org/u/vchuravy)
#### Post date: [October 9, 2023, 8:46pm UTC](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536/38 "2023-10-09T20:46:54Z")

</div>

> [@Palli](#):
>
> They can target (1.9 or) 1.10 now that will become the next LTS.

This has neither been confirmed nor denied. LTS decisions are made after the release, not before it.

[Previous page](https://discourse.julialang.org/t/rfc-give-up-on-semver/103536.md?page=1)
