Skip to content

feat: add package traits for each dependency#431

Merged
stephencelis merged 3 commits into
pointfreeco:mainfrom
danthorpe:dependency-traits
Apr 1, 2026
Merged

feat: add package traits for each dependency#431
stephencelis merged 3 commits into
pointfreeco:mainfrom
danthorpe:dependency-traits

Conversation

@danthorpe
Copy link
Copy Markdown
Contributor

  • Adds package traits for each dependency.
  • by default all traits are enabled.

@pointfreeco pointfreeco deleted a comment from Younglilly4 Mar 25, 2026
@stephencelis
Copy link
Copy Markdown
Member

@danthorpe Can you elaborate a bit more with a PR description of what you're doing and why? (Ideally in your own words...LLMs have a habit of being verbose and not quite describing things accurately or at least succinctly.)

I know we've expressed interest in adding some traits that are on by default for dependency values that require a package dependency, but I believe that would be a much more minimal set of traits for DependenciesCombineSchedulers and DependenciesClocks. And maybe DependenciesFoundation for Linux, though with our key path usage today we can't build for embedded yet, so I'm not 100% sure it's worth it, but if a Linux user wants to push things forward we'd be down.

@danthorpe
Copy link
Copy Markdown
Contributor Author

Hi @stephencelis yeah, sure.

I'm trying to add this package to a large/non-trivial swift-on-server project. We don't really have a need for many of the built-in dependencies that ship out-of-the-box, (except maybe UUID). I especially want to avoid having those dependencies pull in exotic looking transitive dependencies, such as open-combine.

I started a discussion in your project here, where @mbrandonw suggested/hinted that a next step would be to use package traits to gate access to the dependencies. These would all be switched on by default initially, and package consumers would be able to use traits: [] to disable them all. In a breaking-change-future-version, this default behaviour could then be flipped, so that package consumers would use traits to opt-into the dependencies that are available in the package.

Haven't discussed the granularity of these traits yet, I figure that this is the limit - but if you wanted to scale things back to reduce the available traits - that seems reasonable too. For my use case, I want to pass traits: [].

Let me know what you think. I can try to connect with you on Slack if you want to discuss more.

@mbrandonw
Copy link
Copy Markdown
Member

Hi @danthorpe, yeah we can discuss what traits we think should be included. Off the top of my head:

  • Omitting \.assert, \.fireAndForget, and \.withRandomNumberGenerator via a trait is not buying you anything. Those dependencies only use what is already available to us via the standard library, and so there is no cost to including them.
  • I would recommend squashing all the Foundation-related traits into just a single trait because you aren't really saving much by being nitty gritty with each of those. Either you have Foundation linked or you don't.

I would further recommend taking a simplifying pass at this PR. Right now it introduces strange SWIFT_PACKAGE_… flags for some reason. I would expect you just use the traits instead of these flags.

@danthorpe
Copy link
Copy Markdown
Contributor Author

danthorpe commented Mar 31, 2026

Okay, updated following your recommendations @mbrandonw.

Didn't actually read the docs properly initially - didn't see that the SwiftPM automatically makes conditional directives for each trait. The reason why I defined them separately was that I was thinking we need to provide backwards compatibility so that these conditions are active on pre-Swift-6.1. Not immediately clear that it will work for that case, I'm hoping that your CI will expose any issues on older Swift versions...

@mbrandonw
Copy link
Copy Markdown
Member

Hi @danthorpe, thanks for doing that. It's getting closer. However I don't think we need separate traits for MainQueue and MainRunLoop. That can just be a CombineSchedulers trait. And further I don't feel OpenURL is carrying its weight because again that only depends on SwiftUI, which comes for free on Apple platforms. So it being always included is not a big deal.

@mbrandonw
Copy link
Copy Markdown
Member

Not immediately clear that it will work for that case, I'm hoping that your CI will expose any issues on older Swift versions...

Doing #if SOMETHING_THAT_DOESNT_EXIST is perfectly valid in Swift, but that does mean in Swift <6.2 we need to fake these traits by defining the flags in the other Package.swift's so that they are all enabled.

@danthorpe
Copy link
Copy Markdown
Contributor Author

Okay - I think fixed everything you raised.

@stephencelis
Copy link
Copy Markdown
Member

@danthorpe Looking good! We'll discuss tomorrow and hopefully merge!

Comment thread Package.swift Outdated
@stephencelis stephencelis merged commit 2d5bdd3 into pointfreeco:main Apr 1, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants