Skip to content

Cherry-pick Assure trait-guarded dependencies are not included in resolution; precompute enabled traits before resolution (#8852) #8948

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 22, 2025

Conversation

bripeticca
Copy link
Contributor

Cherry pick of #8852

Trait-guarded dependencies were still being considered during dependency
resolution, when they should be excluded if they aren't being used in
any other scenario. Additionally, enabled traits should be pre-computed
before entering the resolution stage in order to avoid possible race
conditions when navigating through the dependency graph nodes.

Modifications:

Since we have the --experimental-prune-unused-dependencies feature
behind an experimental flag, we'll now consider an alternate path that
will prune trait-guarded package dependencies from the dependency graph
if and only if said dependency is not used in any other unguarded
context.

A dictionary wrapper titled EnabledTraitsMap is used to store the
enabled traits per package for the package graph and is stored as a
property within the Workspace, with some additional behaviour to
return a ["default"] set of traits if the package has not yet been
stored in the dictionary, rather than returning nil.

Following this behaviour, when passing a set of traits to methods that
require them (e.g. for dependency computation, enabled trait
computation, etc.) we now require that it is not Optional, since the
checks done on a nil set of traits were redundant.

SwiftCommandState now also stores a TraitConfiguration, since we'll
want access to this across multiple SwiftCommands, and it is
essentially a part of the state anyhow. TraitOptions is now included
in the GlobalOptions for SwiftCommands to supplement this, so that
when a SwiftCommandState is created we will have access to the
user-passed enabled traits. These options, as entitled, are available
globally across all the swift package commands, so previous properties
that declared TraitOptions in these commands has been removed in
favour of using it straight from the GlobalOptions.

Result:

Trait-guarded dependencies are excluded from dependency resolution, and
since traits are pre-computed there should no longer be an issue with
race conditions for traits in resolution as well.

…compute enabled traits before resolution (swiftlang#8852)

Trait-guarded dependencies were still being considered during dependency
resolution, when they should be excluded if they aren't being used in
any other scenario. Additionally, enabled traits should be pre-computed
before entering the resolution stage in order to avoid possible race
conditions when navigating through the dependency graph nodes.

Since we have the `--experimental-prune-unused-dependencies` feature
behind an experimental flag, we'll now consider an alternate path that
will prune trait-guarded package dependencies from the dependency graph
**_if and only if_** said dependency is not used in any other unguarded
context.

A dictionary wrapper titled `EnabledTraitsMap` is used to store the
enabled traits per package for the package graph and is stored as a
property within the `Workspace`, with some additional behaviour to
return a `["default"]` set of traits if the package has not yet been
stored in the dictionary, rather than returning `nil`.

Following this behaviour, when passing a set of traits to methods that
require them (e.g. for dependency computation, enabled trait
computation, etc.) we now require that it is not Optional, since the
checks done on a `nil` set of traits were redundant.

SwiftCommandState now also stores a `TraitConfiguration`, since we'll
want access to this across multiple `SwiftCommand`s, and it is
essentially a part of the state anyhow. `TraitOptions` is now included
in the `GlobalOptions` for `SwiftCommand`s to supplement this, so that
when a `SwiftCommandState` is created we will have access to the
user-passed enabled traits. These options, as entitled, are available
globally across all the swift package commands, so previous properties
that declared `TraitOptions` in these commands has been removed in
favour of using it straight from the `GlobalOptions`.

Trait-guarded dependencies are excluded from dependency resolution, and
since traits are pre-computed there should no longer be an issue with
race conditions for traits in resolution as well.
@bripeticca
Copy link
Contributor Author

@swift-ci please test

@bripeticca
Copy link
Contributor Author

@swift-ci please test

@bripeticca
Copy link
Contributor Author

@swift-ci please test windows

@bripeticca
Copy link
Contributor Author

@swift-ci please test

@bripeticca
Copy link
Contributor Author

@swift-ci please test windows

1 similar comment
@bripeticca
Copy link
Contributor Author

@swift-ci please test windows

@bripeticca bripeticca enabled auto-merge (squash) July 18, 2025 20:00
@dschaefer2
Copy link
Member

@swift-ci please test windows

1 similar comment
@dschaefer2
Copy link
Member

@swift-ci please test windows

@bripeticca bripeticca merged commit b931916 into swiftlang:release/6.2 Jul 22, 2025
6 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.

2 participants