Skip to content

Commit fa909d1

Browse files
authored
solidify and clarify the API versioning strategy for macros (#3219)
Closes #1934
1 parent 2ac4f81 commit fa909d1

File tree

1 file changed

+108
-20
lines changed

1 file changed

+108
-20
lines changed

working/macros/feature-specification.md

Lines changed: 108 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,28 +1300,116 @@ given library. This will be allowed through the library introspection class,
13001300
which is available from the introspection APIs on all declarations via a
13011301
`library` getter.
13021302

1303-
**TODO**: Fully define the library introspection API for each phase.
1304-
13051303
### API versioning
13061304

1307-
**TODO**: Finalize the approach here (#1934).
1308-
1309-
It is possible that future language changes would require a breaking change to
1310-
an existing imperative macro API. For instance you could consider what would
1311-
happen if we added multiple return values from functions. That would
1312-
necessitate a change to many APIs so that they would support multiple return
1313-
types instead of a single one.
1314-
1315-
#### Proposal: Ship macro APIs as a Pub package
1316-
1317-
Likely, this package would only export directly an existing `dart:` uri, but
1318-
it would be able to be versioned like a public package, including tight sdk
1319-
constraints (likely on minor version ranges). This would work similar to the
1320-
`dart:_internal` library.
1321-
1322-
This approach would involve more work on our end (to release this package with
1323-
each dart release). But it would help keep users on the rails, and give us a
1324-
lot of flexibility with the API going forward.
1305+
It is expected that future language changes will require breaking changes to the
1306+
macro APIs. For instance you could consider what would happen if we added
1307+
multiple return values from functions. That would necessitate a change to many
1308+
APIs so that they would support multiple return types instead of a single one.
1309+
1310+
#### Design goals
1311+
1312+
* Enable us to make API changes when needed.
1313+
* Minimize churn for macro authors - most SDK versions will not be breaking and
1314+
it would be ideal to not ask packages to have super tight SDK constraints.
1315+
* Give early and actionable error messages to consumers of macros when a macro
1316+
they are using does not support a new language feature.
1317+
* Enable as much forwards/backwards compatibility as possible.
1318+
1319+
#### Solution: Ship macro APIs as a Pub package
1320+
1321+
The implementation of this package will always come from the SDK, through a
1322+
`dart:_macros` library, which will be exported by this package. The
1323+
`dart:_macros` library will be blocked from being imported or exported by any
1324+
library other than other `dart:` libraries and this package.
1325+
1326+
We use a `dart:` library here to ensure that the binaries shipped with the SDK
1327+
are compiled with exactly the same version of the API that macros are compiled
1328+
with. This ensures the communication protocol between macros and the SDK
1329+
binaries are compatible.
1330+
1331+
This package will have tight upper bound SDK constraints, constrained to the
1332+
minor release versions instead of major release versions.
1333+
1334+
The release/versioning strategy for the package is as follows:
1335+
1336+
- We will not allow any changes to the macro APIs in patch releases of the SDK,
1337+
even non-breaking changes. The package restricts itself to minor releases and
1338+
not patch releases of the SDK, so these changes would silently be visible to
1339+
users in a way that wasn't versioned through the package.
1340+
1341+
- When a new version of the Dart SDK is released which **does not have any**
1342+
changes to the macro API, then we will do a patch release of this package
1343+
which simply expands the SDK upper bound to include that version (specifically
1344+
it will be updated to less than the next minor version). For example,
1345+
if version `3.5.0` of the SDK was just released, and it has no changes to the
1346+
macro API, the new upper bound SDK constraint would be `<3.6.0` and the lower
1347+
bound would remain unchanged.
1348+
1349+
Since this is only a patch release of this package, all existing packages that
1350+
depend on this package (with a standard version constraint) will support it
1351+
already, so no work is required on macro authors' part to work with the new
1352+
Dart SDK.
1353+
1354+
- When a new version of the Dart SDK is released which has **non-breaking**
1355+
changes to the macro API, then we will do a minor release of this package,
1356+
which increases the lower bound SDK constraint to the newly released version,
1357+
and the upper bound to less than the next minor release version. For example,
1358+
if version `3.5.0` of the SDK was just released, and it has **non-breaking**
1359+
changes to the macro API, the new SDK constraint would be `>=3.5.0 <3.6.0`.
1360+
1361+
Note that only users on the newest SDK will get this new version, but that is
1362+
by design. The new features are being exposed only by the new SDK and are not
1363+
available to older SDKs.
1364+
1365+
Since this is only a minor release, all existing packages that depend on this
1366+
package (with a standard version constraint) will support it already, so no
1367+
work is required on macro authors' part to work with the new Dart SDK.
1368+
1369+
If a macro author wants to **use** the new features, they must update their
1370+
minimum constraint on this package to the latest version to ensure the new
1371+
features are available.
1372+
1373+
- When a new version of the Dart SDK includes a **breaking** change to the macro
1374+
API, then we will release a new major version of this package, and update the
1375+
SDK constraints in the same way as non-breaking changes (update both the
1376+
minimum and maximum SDK constraints, so only the current minor version is
1377+
allowed). By default, existing packages containing macros will not accept that
1378+
version of the macro package and thus will not work with the new Dart SDK.
1379+
1380+
Authors of packages containing macros will need to test to see if their macro
1381+
is compatible with the latest macro API. If so, they can ship a new patch
1382+
version of their package with a constraint on the macro package that includes
1383+
the new major version as well as the previous major version it's already known
1384+
to work with. If their package is broken by the macro API change, then, they
1385+
will fix their macro and ship a new version of their package with a dependency
1386+
on the macro package that only allows the latest major versions.
1387+
1388+
This approach has several advantages for macro authors and users, which are
1389+
closely aligned with the design goals:
1390+
1391+
* Fewer releases for macro authors (this package shouldn't have very many
1392+
breaking changes).
1393+
* Gives us flexibility with the API when needed.
1394+
* Gives early errors if a macro dependency doesn't support the users current
1395+
SDK. The failure will be in the form of a failed version solve.
1396+
* Macros can easily depend on wide ranges of this package (if they are
1397+
compatible).
1398+
1399+
There are some downsides to this approach as well:
1400+
1401+
* More work for us, we need to consistently prepare these releases for new SDKs.
1402+
* Version solve errors can sometimes be very cryptic to understand. This is a
1403+
general problem though, and we will benefit from any improvements in this
1404+
area.
1405+
* Dependency overrides on this package won't actually have any affect, which may
1406+
be confusing to users. The API is always dictated by the `dart:` library and
1407+
not the package itself. Note that this is different from `dart_internal`,
1408+
which wraps the `dart:` APIs it exposes. I don't think this would be
1409+
desireable for this use case, but we could see if it is feasible.
1410+
* It is possible we could forget to bump the min SDK when altering the internal
1411+
API for the `dart:_macros` package. We should put some sort of check in place
1412+
to help ensure we get this right.
13251413

13261414
## Resources
13271415

0 commit comments

Comments
 (0)