/ doc / dev / semver_status.md
semver_status.md
 1  # Semver tracking
 2  
 3  We no longer use this file for semver tracking.  Instead, we use one
 4  `semver.md` file per crate.
 5  
 6  When you make a change to a crate that affects source compatibility,
 7  please append a paragraph to that crate's `semver.md`, creating it as
 8  necessary.
 9  
10  Every line should begin with one of the following:
11    * BREAKING
12    * MODIFIED
13  
14  A "BREAKING" change is one that may break other crates that depend on
15  this crate directly.
16  
17  A "MODIFIED" change is one the introduces a new API, such that crates
18  using the new API will not work with older versions of the crate.
19  
20  When we release a new version, we use these files to determine which
21  crates need major-version, minor-version, or patch-level version bumps.
22  We also use them to help write the "breaking changes" section of the
23  changelog. They aren't user-facing, so they don't go into much detail.
24  
25  Here is an example `semver.md` file:
26  
27  >```
28  >BREAKING: Removed the obsolete `detect_thylacine()` function.
29  >
30  >MODIFIED: New `Wombat::feed()` method.
31  >
32  >MODIFIED: `Numbat` now implements `Display`.
33  >
34  >BREAKING: The `Quokka` trait now inherits from Debug.
35  >```
36  
37  ## What is a breaking change?
38  
39  We will add guidance to this section as we come up with it. For now, see
40  [SemVer compatibility] in the Cargo book.
41  
42  [SemVer Compatibility]: https://doc.rust-lang.org/cargo/reference/semver.html
43  
44  ### When types from lower-level crates appear in the APIs of higher-level crates
45  
46  If a type (concrete type or trait) from a lower-level crate
47  is returned (or accepted)
48  by an API of a higher-level crate,
49  then a breaking change to that lower-level crate is a breaking change
50  for the higher-level crate, too.
51  
52  This includes any case where a higher-layer type
53  implements a public trait from a lower-layer;
54  even if the type is not itself re-exported by the higher-layer crate.
55  
56  #### Reasoning, and worked example:
57  
58  Suppose `tor_error::ErrorKind` gets a breaking change,
59  and we bump the major[1] for `tor_error` but not for `arti_client`.
60  Obviously our new `arti_client` uses the new `tor_error`.
61  
62  A downstream might use both `tor-error` and `arti-client`.
63  If they do this in the usual way,
64  a `cargo update` will get them the new `arti_client` but old `tor_error`.
65  Now their program has *two* instances of `tor_error`:
66  one whose `ErrorKind` is implemented by `arti_client::Error`,
67  and one that the downstream application code sees.
68  The effect is that the downstream application
69  can no longer call `.has_kind()` on an `arti_client::Error`
70  because they don't have the *right* `HasKind` method in scope.
71  
72  Note that this does not depend on the nature of the breaking change,
73  nor on the re-export of any names.
74  It only depends on the exposure of the type and its trait implementations.
75  
76  (The ["semver trick"](https://github.com/dtolnay/semver-trick)
77  can sometimes be used to help multiple different versions
78  of the same crate share global state, or perhaps, traits etc.)
79  
80  [1] "Major" here includes the 2nd component in a 0.x version.