# Macro Adoption Concerns around SwiftSyntax

**URL:** <https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588>\
**Category:** Discussion\
**Tags:** swift-syntax, macros\
**Created:** [August 4, 2023, 6:02pm UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588 "2023-08-04T18:02:03Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![stephencelis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/stephencelis/32/2675_2.png) [@stephencelis](https://forums.swift.org/u/stephencelis)\
**Post date:** [August 4, 2023, 6:02pm UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/1 "2023-08-04T18:02:03Z")

</div>

Macros are one of the most celebrated new features of Swift, and many of us are excited to adopt them in our projects. Many members of the core team are also excited to suggest macros as a solution to many problems. We’d love to hit the ground running and adopt macros in our projects, but the decision to adopt them raises some questions, particularly around the dependence on the swift-syntax package.

1. Introducing SwiftSyntax to a project immediately incurs an additional 20 second debug build cost to a project, which may not seem like much, but that’s an extra minute for every 3 cleans. Things get much slower when building for release with whole module optimization: over 4 minutes just for SwiftSyntax. [This issue](https://github.com/apple/swift-syntax/issues/1194) from January highlights the problem, but there isn’t a lot of discussion around how it might be addressed. With Swift 5.9’s release on the horizon, can we expect these build times to improve in the near future, or will they be the cost of adopting macros for now?

2. Beyond build times, SwiftSyntax is a complex project to depend on, and it’s unclear how to version a project that depends on it. I started [this discussion](https://forums.swift.org/t/versioning-libraries-that-use-macros-and-swiftsyntax/66514) a few days ago and was hoping for guidance there, but I’ll restate the problem here. Because SwiftSyntax is a moving target and versioned alongside Swift releases, how can a library adopt macros and be compatible with multiple Swift versions at the same time? Is there a straightforward solution out there that isn’t documented? Beyond library maintenance there’s the question of library adoption. If an app depends on several packages that all ship macros, what happens when these libraries target different Swift versions? While this is a more general problem that comes with dependencies, SwiftSyntax would seem to exacerbate the issue.

3. And finally, SwiftSyntax’s API seems to be in constant flux. I’ve used the library sporadically over the years and whenever I return to a project that uses it, it rarely still builds. While it’s nice to see a new DocC tutorial on the 5.9 development release, there isn’t a ton of up-to-date documentation that’s easy to navigate in general, the examples in the repo are using old APIs that don’t seem to build any more, and many online resources one finds via a web search are also outdated. Is there a plan to stabilize these APIs? Should folks writing macros be concerned about maintaining SwiftSyntax code as its API continues to evolve?

Those are the three main issues that it would be nice to have clarity/guidance on. I believe there’s been discussion in the past about including SwiftSyntax alongside Swift, so maybe that would address all of the above concerns, but is it actually planned? Should folks be cautioned against adopting macros at this early stage?

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [August 4, 2023, 6:35pm UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/2 "2023-08-04T18:35:51Z")

</div>

i don't have much advice to give, i can only say that i have also experienced all three issues you highlighted.

---

<div class="post-metadata">

**Author:** ![dmt](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dmt/32/30830_2.png) [@dmt](https://forums.swift.org/u/dmt)\
**Post date:** [August 4, 2023, 6:58pm UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/3 "2023-08-04T18:58:23Z")

</div>

> [@stephencelis](#):
>
> Introducing SwiftSyntax to a project immediately incurs an additional 20 second debug build cost to a project, which may not seem like much, but that’s an extra minute for every 3 cleans.

I guess this is about the SPM distributed version? There is a bundled with the XCode's toolchain prebuilt version: `/Applications/Xcode15.0b5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/host/`

---

<div class="post-metadata">

**Author:** ![stephencelis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/stephencelis/32/2675_2.png) [@stephencelis](https://forums.swift.org/u/stephencelis)\
**Post date:** [August 4, 2023, 7:03pm UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/4 "2023-08-04T19:03:42Z")

</div>

The SPM-distributed version is what Xcode 15's macro template uses, and there's no way to simply `import SwiftSyntax` from Swift right now otherwise. One of my questions above less directly asks if this is to change by release.

---

<div class="post-metadata">

**Author:** ![dmt](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dmt/32/30830_2.png) [@dmt](https://forums.swift.org/u/dmt)\
**Post date:** [August 4, 2023, 7:34pm UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/5 "2023-08-04T19:34:46Z")

</div>

Check this out [GitHub - DmT021/ObservationBD: Proof of concept for Swift Observation back-deploy](https://github.com/DmT021/ObservationBD)  
This is my reimplementation of `Observable` macro. It doesn't depend on the SPM package

---

<div class="post-metadata">

**Author:** ![dmt](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dmt/32/30830_2.png) [@dmt](https://forums.swift.org/u/dmt)\
**Post date:** [August 4, 2023, 7:40pm UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/6 "2023-08-04T19:40:17Z")

</div>

Just add `$(TOOLCHAIN_DIR)/usr/lib/swift/host` to the `Import Paths` property of your macro target

---

<div class="post-metadata">

**Author:** ![stephencelis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/stephencelis/32/2675_2.png) [@stephencelis](https://forums.swift.org/u/stephencelis)\
**Post date:** [August 4, 2023, 7:43pm UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/7 "2023-08-04T19:43:31Z")

</div>

@dmt Unless I'm mistaken, you can't distribute an SPM package with custom import paths. I also don't think Apple is advising folks link to this bundled version, nor do they document this option.

---

<div class="post-metadata">

**Author:** ![stackotter](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/stackotter/32/20670_2.png) [@stackotter](https://forums.swift.org/u/stackotter)\
**Post date:** [August 4, 2023, 9:10pm UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/8 "2023-08-04T21:10:44Z")

</div>

> [@stephencelis](#):
>
> And finally, SwiftSyntax’s API seems to be in constant flux.

If number 3 continues to be an issue, it could be an option to update [SwiftMacroToolkit](https://github.com/stackotter/swift-macro-toolkit) to wrap the SwiftSyntax API more comprehensively to hide away the constantly changing API in a simpler, more stable, and more macro-specific wrapper for macro devs. That of course doesn’t help with the first two options at all though.

---

<div class="post-metadata">

**Author:** ![dmt](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dmt/32/30830_2.png) [@dmt](https://forums.swift.org/u/dmt)\
**Post date:** [August 4, 2023, 11:54pm UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/9 "2023-08-04T23:54:24Z")

</div>

> [@stephencelis](#):
>
> I also don't think Apple is advising folks link to this bundled version, nor do they document this option.

Huh, I guess you're right. I've found this in the example repo, but it seems like this approach has been abandoned, according to [this commit](https://github.com/DougGregor/swift-macro-examples/commit/75de546eddb2062943e15d131abb360b53ad7f57).  
Also I've found out that the toolchain for linux doesn't contain prebuilt SwiftSyntax for some reason.  
Sorry for misleading.

---

<div class="post-metadata">

**Author:** ![tgoyne](https://avatars.discourse-cdn.com/v4/letter/t/5e9695/32.png) [@tgoyne](https://forums.swift.org/u/tgoyne)\
**Post date:** [August 5, 2023, 12:31am UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/10 "2023-08-05T00:31:33Z")

</div>

I've been looking into package a macro for distribution recently and my current idea is:

1. Fork SwiftSyntax and rename it so that our version of SwiftSyntax can't conflict with another library.
2. Create binary builds of our fork and import that
3. `#if` soup in both Package.swift and the actual macro implementations to deal with 3.9+3.10

---

<div class="post-metadata">

**Author:** ![stephencelis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/stephencelis/32/2675_2.png) [@stephencelis](https://forums.swift.org/u/stephencelis)\
**Post date:** [August 7, 2023, 3:58pm UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/11 "2023-08-07T15:58:02Z")

</div>

I'm wondering if a member of the core team would weigh in on these concerns? I'd be happy to hear if they're unfounded.

---

<div class="post-metadata">

**Author:** ![esummers](https://avatars.discourse-cdn.com/v4/letter/e/f04885/32.png) [@esummers](https://forums.swift.org/u/esummers)\
**Post date:** [August 7, 2023, 11:14pm UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/12 "2023-08-07T23:14:28Z")

</div>

On #2) It would be great to see it standard practice to import the package corresponding to targeted Swift language version. If you are targeting Swift 5.9 then use the 5.9 branch of swift-syntax. There is nothing stopping that now, but SPM isn't great at detecting updates to a branch.

I think it would be great to include the recommended version for each Swift language mode as a shared library with Xcode to speed up compilation. Just don't include it as a dependency if you want to use the Swift built-in version. I think a shared library would only be available to macros or build plugins and not other uses of swift-syntax.

---

<div class="post-metadata">

**Author:** ![Jon\_Shier](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jon_shier/32/921_2.png) [@Jon\_Shier](https://forums.swift.org/u/Jon_Shier)\
**Post date:** [August 7, 2023, 11:23pm UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/13 "2023-08-07T23:23:47Z")

</div>

Seems like auto importing the version corresponding to the Swift version in the package would be a good first step. Then allow an override of that auto import with some sort of manual version so people can track development versions.

---

<div class="post-metadata">

**Author:** ![stephencelis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/stephencelis/32/2675_2.png) [@stephencelis](https://forums.swift.org/u/stephencelis)\
**Post date:** [August 8, 2023, 2:06am UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/14 "2023-08-08T02:06:11Z")

</div>

I encountered another example of the "constant flux" when I updated the `swift-syntax` dependency specified by Xcode's macro template (`509.0.0-swift-DEVELOPMENT-SNAPSHOT-2023-07-10-a` auto-updated to `2023-08-07-a`). I got a bunch of warnings when upgrading a relatively small project:

> ⚠ `init(file:source:)` is deprecated: Use `init(fileName:tree:)` instead
> 
> ⚠ `init(leadingTrivia:_:openDelimiter:_:openQuote:_:segments:_:closeQuote:_:closeDelimiter:_:trailingTrivia:)` is deprecated: renamed to `'StringLiteralExprSyntax(leadingTrivia:_:openingPounds:_:openingQuote:_:segments:_:closingQuote:_:closingPounds:_:trailingTrivia:)'`
> 
> ⚠ `rawStringDelimiter(_:leadingTrivia:trailingTrivia:presence:)` is deprecated: renamed to `rawStringPoundDelimiter`
> 
> ⚠ `rawStringDelimiter(_:leadingTrivia:trailingTrivia:presence:)` is deprecated: renamed to `rawStringPoundDelimiter`
> 
> ⚠ `argumentList` is deprecated: renamed to `arguments`
> 
> ⚠ `replacing(childAt:with:)` is deprecated: Use `.with(\.[index], newValue)` instead
> 
> ⚠ `argumentList` is deprecated: renamed to `arguments`
> 
> ⚠ `replacing(childAt:with:)` is deprecated: Use `.with(\.[index], newValue)` instead
> 
> ⚠ `appending` is deprecated: Create a new array of elements and construct a new collection type from those elements

While some of these are simple fixes, others are not.

---

<div class="post-metadata">

**Author:** ![ahoppen](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ahoppen/32/36046_2.png) [@ahoppen](https://forums.swift.org/u/ahoppen)\
**Post date:** [August 8, 2023, 2:41am UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/15 "2023-08-08T02:41:21Z")

</div>

Thanks for sharing your concerns @stephencelis

### Regarding (1) SwiftSyntax build times

Yes, that is cost of building a macro at the moment and unfortunately I don't have any suggestion of how to improve this situation at the moment. Installing swift-syntax into the toolchain will only work in cases where that installed version happens to match the one that SwiftPM resolved, which won't match if we need to create a patch release of swift-syntax or the Swift 5.10 compiler is used with swift-syntax 509.

### Regarding (2) SwiftSyntax Version Dependency

I have just composed an article that describes how macros should adjust their versions when updating to a new major swift-syntax version: [https://github.com/apple/swift-syntax/pull/2024](https://github.com/apple/swift-syntax/pull/2024). Let me know if that answers your questions. The TL;DR is: Update the minor version of a macro when updating its swift-syntax version dependency.

### Regarding (3a) SwiftSyntax API Breakage

swift-syntax has matured significantly over the last few months, the main driver being the drastic increase in our user base from macro authors. This has involved a significant number of rapid changes, with the goal of delivering a solid release alongside Swift 5.9. The latest changes you comment on are due to [Significant changes in the latest swift-syntax 509 prerelease](https://forums.swift.org/t/significant-changes-in-the-latest-swift-syntax-509-prerelease/66644), which we decided to land now to reduce the churn of the Swift 5.10-aligned release of swift-syntax.

We are anticipating that swift-syntax's API will become a lot more stable after its Swift 5.9-aligned release, though there will always be some API breakages in swift-syntax as the swift language itself evolves. We will do our best to mitigate these changes through API deprecations, which we have already been doing between the latest snapshot releases.

### Regarding (3b) Lack of Examples

The swift-syntax repository contains a [couple of examples](https://github.com/apple/swift-syntax/tree/main/Examples/Sources) that are guaranteed to always be up-to-date by a CI job. We'll also incorporate @Douglas_Gregor's list of [example macros](https://github.com/DougGregor/swift-macro-examples) into there as well ([#2026](https://github.com/apple/swift-syntax/issues/2026)). Similarly [swift-format](https://github.com/apple/swift-format) is a sizable client of swift-syntax that's always compatible with the latest swift-syntax release. Beyond these, are there any particular examples you think are missing?

### Regarding (3b) Lack of Documentation

With the two WWDC presentations on macros, [Expand on Swift macros](https://developer.apple.com/videos/play/wwdc2023-10167) and [Write Swift macros](https://developer.apple.com/videos/play/wwdc2023-10166) I think we have two good ways of getting started with macro development. [swiftpackageindex.com](https://swiftpackageindex.com/apple/swift-syntax/main/documentation/swiftsyntax) allows browsing the swift-syntax API and [swift-ast-explorer.com](https://swift-ast-explorer.com) allows interactive exploration of the syntax tree. I agree that it would always be good to have more documentation, but I think we aren't in a terribly bad spot at the moment. If there's anything you feel is missing, pull requests and/or issues are always welcome.

---

<div class="post-metadata">

**Author:** ![tgoyne](https://avatars.discourse-cdn.com/v4/letter/t/5e9695/32.png) [@tgoyne](https://forums.swift.org/u/tgoyne)\
**Post date:** [August 8, 2023, 4:12am UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/16 "2023-08-08T04:12:34Z")

</div>

> [@ahoppen](#):
>
> I have just composed an article that describes how macros should adjust their versions when updating to a new major swift-syntax version: [Add an article that describes how macros should be versioned when updating their swift-syntax dependency by ahoppen · Pull Request #2024 · apple/swift-syntax · GitHub](https://github.com/apple/swift-syntax/pull/2024). Let me know if that answers your questions. The TL;DR is: Update the minor version of a macro when updating its swift-syntax version dependency.

It sounds like the answer to "how do you support multiple versions of Swift at once?" is "you don't". Updating to 510 requires dropping support for 509, and failing to upgrade means you block updating other packages which have upgraded. This isn't a problem in the short run since of course only 5.9 will be the only version of Swift with macros for a while, but it really isn't a viable long-term answer.

---

<div class="post-metadata">

**Author:** ![esummers](https://avatars.discourse-cdn.com/v4/letter/e/f04885/32.png) [@esummers](https://forums.swift.org/u/esummers)\
**Post date:** [August 8, 2023, 5:06am UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/17 "2023-08-08T05:06:04Z")

</div>

> It sounds like the answer to "how do you support multiple versions of Swift at once?" is "you don't".

That is what language modes are for... but yeah I know the real world can be more complicated.

---

<div class="post-metadata">

**Author:** ![stephencelis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/stephencelis/32/2675_2.png) [@stephencelis](https://forums.swift.org/u/stephencelis)\
**Post date:** [August 8, 2023, 5:24am UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/18 "2023-08-08T05:24:11Z")

</div>

@ahoppen Thanks for replying! I appreciate the time and context.

1. While it's a bummer that there's no official way to address the build times, especially when it comes to release builds, I do hope awareness leads to a solution in the future.

2. Thanks for taking the time to work on the article! Having guidance is helpful, but I think it also highlights just how precarious versioning macros may be:

3. (b) The examples out there are indeed helpful when they're up to date! I think it might be a good idea to prune [this list](https://github.com/apple/swift-syntax/tree/main/Examples#some-example-usages) in the README, though. Many of these projects haven't been updated in years.

---

<div class="post-metadata">

**Author:** ![stephencelis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/stephencelis/32/2675_2.png) [@stephencelis](https://forums.swift.org/u/stephencelis)\
**Post date:** [August 8, 2023, 5:26am UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/19 "2023-08-08T05:26:40Z")

</div>

> [@esummers](#):
>
> That is what language modes are for... but yeah I know the real world can be more complicated.

This is precisely why an example library would be nice. While it won't be possible to show a macro that supports multiple versions of Swift concurrently till 5.10 is available, we could have a demo that shows how a more general library can use SwiftSyntax and ship versions that are compatible with several versions of Swift.

---

<div class="post-metadata">

**Author:** ![tgoyne](https://avatars.discourse-cdn.com/v4/letter/t/5e9695/32.png) [@tgoyne](https://forums.swift.org/u/tgoyne)\
**Post date:** [August 8, 2023, 5:27am UTC](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588/20 "2023-08-08T05:27:02Z")

</div>

I don't see how language modes are relevant to this.

[Next page](https://forums.swift.org/t/macro-adoption-concerns-around-swiftsyntax/66588.md?page=2)
