Description
As highlighted in #95, #97 and #99, there are likely to be situations in which we need to fix or upgrade traits in breaking ways, and these are likely to have significant ramifications on the embedded ecosystem. This RFC proposes an approach to manage these breaking changes.
Goals:
- Mitigate the downstream breakage caused by embedded-hal breaking changes
- Communicate breaking changes to give library uses an opportunity to update
Approach:
We propose a staged approach for managing breaking changes, with some time between each stage to allow API consumers to update.
In the first release, replacement traits are introduced and feature-gated allowing users to opt in to their use. Feature names start with with use-
and a description of the change, for example use-fallible-digital-traits
for the new fallible digital trait update in #97. Existing traits are marked #[deprecated]
to alert users to the need to update, and this opt-in flag should be added to the CI build matrix. Documentation should also be updated to recommend the use of the opt-in traits and the related github issue for the change. This stage alerts HAL users of deprecation and allows immediate migration should they desire, without requiring any explicit action.
In the second release, the opt-in feature flag is replaced with an opt-out flag to allow regression to the previous trait if required, this should start with regress-
. Continuing the fallible digital trait example this would be regress-infallible-digital-traits
. This opt-out flag should be added to the build matrix, and the previous flag removed. Documentation should be updated to mention opt-out trait availability if required. This stage will break HAL consumers using the previous traits, requiring explicit action to update or defer the change.
In the third release, the old traits are removed, feature flags are removed from the package and the CI build matrix, and the documentation should be updated to remove mention of the opt-out trait. This stage will break any hal consumers that have not updated to the new traits.
In each release, these changes will be documented in the changelog (as is standard) and should be published through other useful means. The linking of the related issue in the documentation should allow for feedback from HAL consumers at each stage.
Each stage will correspond to a semver version increase (though it is worth noting that more than one breaking change may be included in a single release). At 0.x
this will be patch, minor, minor
, and >=1.x
: will be minor, major, major
.
I also wrote a small tool to analyse the dependency requirements, resolutions, and features of published crates (https://github.com/ryankurte/rust-dep-check), which would let us track migration through versions and feature flags. An example output showing the current use of embedded-hal
:
Found 100 crates using 'embedded-hal'
Version requirements:
^0.1 (0.1.3): 1 / 100 (1.00 %)
^0.1.0 (0.1.3): 6 / 100 (6.00 %)
^0.1.1 (0.1.3): 1 / 100 (1.00 %)
^0.1.2 (0.1.3): 7 / 100 (7.00 %)
^0.2 (0.2.1): 19 / 100 (19.00 %)
^0.2.0 (0.2.1): 12 / 100 (12.00 %)
^0.2.1 (0.2.1): 45 / 100 (45.00 %)
~0.2 (0.2.1): 9 / 100 (9.00 %)
Features:
unproven: 35 / 100 (35.00 %)
Resolved versions and features:
0.1.3: 15 / 100 (15.00 %)
unproven: 3 / 15 (20.00 %)
0.2.1: 85 / 100 (85.00 %)
unproven: 32 / 85 (37.65 %)
Questions
- Should this apply to traits marked
unproven
? My view is that given the propensity ofunproven
traits we may as well try to mitigate all breakages or no worry about it at all (see the alternative).
Alternative
Do nothing, semver already mitigates breaking changes and we’re in the 0.x series with no API stability guarantees. This is much simpler, though not particularly supportive of our API consumers or the possible impact of breaking changes on the ecosystem, and it doesn't give our consumers any notice of the change outside of the github discussions.