1# Edition Evolution 2 3**Author:** [@mcy](https://github.com/mcy) 4 5**Approved:** 2022-07-06 6 7## Overview 8 9[Protobuf Editions](what-are-protobuf-editions.md) give us a mechanism for 10pulling protobuf files into the future by upgrading their *edition*. Features 11are flags associated with syntax items of a `.proto` file; they can be either 12set explicitly, or they can be implied by the edition. Features can either 13correspond to behavior in `protoc`'s frontend (e.g. `proto:closed_enums`), or to 14a specific backend (`cpp:string_view`). 15 16This document seeks to answer: 17 18* When do we create an edition? 19* How do backends inform protoc of their defaults? 20 21## Proposal 22 23### Total Ordering of Editions 24 25**NOTE:** This topic is largely superseded by [Edition Naming](edition-naming.md). 26 27The `FileDescriptorProto.edition` field is a string, so that we can avoid nasty 28surprises around needing to mint multiple editions per year: even if we mint 29`edition = "2022";`, we can mint `edition = "2022b";` in a pinch. 30 31However, we might not own some third-party backends, and they might be unaware 32of when we decide to mint editions, and might want to mint editions on their 33own. Suppose that I maintain the Haskell protobuf backend, and I decide to add 34the `haskell:more_monads` feature. How do I get this into an edition? 35 36We propose defining a *total order* on editions. This means that a backend can 37pick the default not by looking at the edition, but by asking "is this proto 38older than this edition, where I introduced this default?" 39 40The total order is thus: the edition string is split on `'.'`. Each component is 41then ordered by `a.len < b.len && a < b`. This ensures that `9 < 10`, 42for example. 43 44By convention, we will make the edition be either the year, like `2022`, or the 45year followed by a revision, like `2022.1`. Thus, we have the following total 46ordering on editions: 47 48``` 492022 < 2022.0 < 2022.1 < ... < 2022.9 < 2022.10 < ... < 2023 < ... < 2024 < ... 50``` 51 52This means that backends (even though we don't particularly recommend it) can 53change defaults as often as they like. Thus, if I decide that 54`haskell:more_monads` becomes true in 2023, I simply ask 55`file.EditionIsLaterThan("2023")`. If it becomes false in 2023.1, a future 56backend can ask `file.EditionIsBetween("2023", "2023.1")`. 57 58### Creating an Edition 59 60In a sense, every edition already exists; it's just a matter of defining 61features on it. 62 63If the feature is a `proto:` feature, `protoc` intrinsically knows it, and it is 64implemented in the frontend. 65 66If the feature is a backend feature, the backend must be able to produce some 67kind of proto like `message Edition { repeated Feature defaults = 1; }` that 68describes what a specific edition must look like, based on less-than/is-between 69predicates like those above. That information can be used by protoc to display 70the full set of features it knows about given its backends. (The backend must, 71of course, use this information to make relevant codegen decisions.) 72 73### What about Editions "From the Future"? 74 75Suppose that in version v5.0 of my Haskell backend I introduced 76`haskell:more_monads`, and this has a runtime component to it; that is, the 77feature must be present in the descriptor to be able to handle parsing the 78message correctly. 79 80However, suppose I have an older service running v4.2. It is compiled with a 81proto that was already edition 2023 at build time (alternatively, it dynamically 82loads a proto). My v5.0 client sends it an incompatible message from "the 83future". Because a parse failure would be an unacceptable service degradation, 84we have a couple of options: 85 86* Editions cannot introduce a feature that requires readers to accept new 87 encodings. 88 * Similarly, editions cannot add restrictions that constrain past parsers. 89* Editions may introduce such features, but they must somehow fit into some 90 kind of build horizon. 91 92The former is a reasonable-sounding but ultimately unacceptable position, since 93it means we cannot use editions if we wanted to, say, make it so that message 94fields are encoded as groups rather than length-prefixed chunks. The alternative 95is to define some kind of build horizon.