-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Make Resolved*
in PackageGraph
value types
#7160
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Multiple places in our codebase pass around and store `[any PackageConditionProtocol]` arrays of existentials with `FIXME` notes that those should be sets and not arrays. Adding `Hashable` requirement to `PackageConditionProtocol` doesn't fix the issue, since existentials of this protocol still wouldn't conform to `Hashable`. A simple alternative is to create `enum PackageCondition` with cases for each condition type. We only have two of those types and they're always declared in the same package. There's no use case for externally defined types for this protocol. That allows us to convert uses of `[any PackageConditionProtocol]` to `Set<PackageCondition>`. Existing protocol kept around until clients of SwiftPM can migrate to the new `PackageCondition` enum.
This was referenced Dec 2, 2023
Depends on #7117, unblocks #7160. The `PackageModel` module has no business of defining supported platforms computation for resolved targets, products, and packages. This belongs to `PackageGraph`, but was previously leaking out into `PackageModel` by passing the `derivedXCTestPlatformProvider` closure around. That prevented us from converting marking `SupportedPlatforms` as `Hashable` and marking any of `Resolved*` types as value types and also `Hashable`. In the future, when we'll also need to make them `Sendable`, this could become problematic, passing so much state captured in a closure, mostly by accident.
9ba50be
to
27d4f68
Compare
MaxDesiatov
added a commit
that referenced
this pull request
Dec 5, 2023
Unblocks `PackageGraph` value types refactoring in #7160 and macros cross-compilation fix in #7118. Multiple places in our codebase pass around and store `[any PackageConditionProtocol]` arrays of existentials with `FIXME` notes that those should be sets and not arrays. We also can't convert types containing these arrays to value types with auto-generated `Hashable` conformance, since neither elements of these arrays nor arrays themselves are `Hashable`. Adding `Hashable` requirement to `PackageConditionProtocol` doesn't fix the issue, since existentials of this protocol still wouldn't conform to `Hashable`. A simple alternative is to create `enum PackageCondition` with cases for each condition type. We only have two of those types and they're always declared in the same module. There's no use case for externally defined types for this protocol. That allows us to convert uses of `[any PackageConditionProtocol]` to `[PackageCondition]`. Existing protocol is kept around until clients of SwiftPM can migrate to the new `PackageCondition` enum. This also allows us to remove a custom conformance to `Hashable` on `ResolvedTarget`, unblocking a conversion of `ResolvedTarget` to a value type and making it `Sendable` in the future.
tomerd
approved these changes
Dec 5, 2023
Sources/Build/BuildDescription/SwiftTargetBuildDescription.swift
Outdated
Show resolved
Hide resolved
Sources/Build/BuildDescription/ClangTargetBuildDescription.swift
Outdated
Show resolved
Hide resolved
@@ -102,6 +102,7 @@ public struct PackageGraphRoot { | |||
// at which time the current special casing can be deprecated. | |||
var adjustedDependencies = input.dependencies | |||
if let explicitProduct { | |||
// FIXME: `dependenciesRequired` modifies manifests and prevents conversion of `Manifest` to a value type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏼
tomerd
reviewed
Dec 5, 2023
…ft-package-manager into maxd/packagegraph-value-types # Conflicts: # Sources/Build/BuildDescription/TargetBuildDescription.swift # Sources/Build/BuildPlan/BuildPlan+Clang.swift # Sources/Build/BuildPlan/BuildPlan+Product.swift # Sources/Build/BuildPlan/BuildPlan+Swift.swift # Sources/PackageGraph/Resolution/ResolvedProduct.swift # Sources/PackageGraph/Resolution/ResolvedTarget.swift
neonichu
approved these changes
Dec 12, 2023
MaxDesiatov
added a commit
that referenced
this pull request
Dec 13, 2023
### Motivation: The `PackageModel` module has no business of defining supported platforms computation for resolved targets, products, and packages. This belongs to `PackageGraph`, but was previously leaking out into `PackageModel` by passing the `derivedXCTestPlatformProvider` closure around. That prevented us from marking `SupportedPlatforms` as `Hashable` and marking any of `Resolved*` types as value types also `Hashable`. In the future, when we need to make them `Sendable`, passing mutable state captured in a closure could become problematic. This also unblocks `PackageGraph` value types refactoring in #7160 and macros cross-compilation fix in #7118. ### Modifications: Add new `PlatformVersionProvider` type, which is a value type that can be easily made `Hashable` and `Sendable`. Instead of passing closures around, platform version computation code is now gathered in a single file (new `PlatformVersionProvider.swift`), with all possible context captured in its inner `enum Implementation`. This new type is adopted by `Resolved*` types in the `PackageGraph` module, which actively uses minimum platform version computations. Renamed `func getDerived` to `func getSupportedPlatform`, now that this function delegating to `PlatformVersionProvider` is declared on `Resolved*` types. ### Result: `SupportedPlatforms` type, which is nothing more than `[SupportedPlatform]` array with an additional closure, can be removed. Types that previously had properties of `SupportedPlatforms` can be easily converted to value types and made `Hashable` in a way that accounts for their content instead of class instance identity.
…xd/packagegraph-value-types # Conflicts: # Sources/PackageGraph/PackageGraph+Loading.swift # Sources/PackageGraph/Resolution/PlatformVersionProvider.swift # Sources/PackageGraph/Resolution/ResolvedPackage.swift # Sources/PackageGraph/Resolution/ResolvedProduct.swift # Sources/PackageGraph/Resolution/ResolvedTarget.swift # Sources/XCBuildSupport/PIFBuilder.swift # Tests/PackageGraphTests/TargetTests.swift
@swift-ci test |
@swift-ci test windows |
693b4ae
to
ad5792c
Compare
@swift-ci test |
@swift-ci test |
@swift-ci test windows |
@swift-ci test |
@swift-ci test windows |
1 similar comment
@swift-ci test windows |
MaxDesiatov
added a commit
that referenced
this pull request
Dec 20, 2023
Fix fixes a serious performance regression introduced for deep target dependency graphs in #7160. After converting `ResolvedTarget` to a value type, its synthesized `Hashable` conformance traversed the whole dependency tree multiple times when using `topologicalSort`. This made package resolution seemingly hang for packages that had a lot of nested target graphs. We already have an implementation of `topologicalSort` on `Identifiable`, thus we should use that instead. I've also added a performance test for this in `PackageGraphPerfTests` to prevent future regressions in this area.
MaxDesiatov
added a commit
that referenced
this pull request
Jan 2, 2024
### Motivation: A serious performance regression was introduced for deep target dependency graphs in #7160. After converting `ResolvedTarget` to a value type, its synthesized `Hashable` conformance traversed the whole dependency tree multiple times when using `topologicalSort`. This made package resolution seemingly hang for packages that had a lot of nested target graphs. ### Modifications: We already have an implementation of `topologicalSort` on `Identifiable`, so we're using that now instead. I've also added a performance test for this in `PackageGraphPerfTests` to prevent future regressions in this area. ### Result: Resolved rdar://119807385.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Depends on #7161. Unblocks macros cross-compilation fix in #7118.
Motivation:
Value types are easier to reason about as they prevent "spooky action at a distance" bugs, and can be easily made
Equatable
,Hashable
, and most important of allSendable
.Modifications:
Converted
ResolvedTarget
,ResolvedProduct
, andResolvedPackage
fromfinal class
es tostruct
s.Renamed
underlyingTarget
,underlyingProduct
, andunderlyingPackage
to justunderlying
to avoid tautological patterns liketarget.underlyingTarget
.Result:
It's easier to apply changes in
PackageGraph
. Also, in my benchmarks done locally this makes package graph resolution consistently ~5% faster when resolving the package graph of SwiftPM's ownPackage.swift
.main
branch:This PR's branch:
Future directions:
I'm unable to fully remove
Resolved*Builder
classes yet, as they rely onTarget
being a reference type and module aliasing relying on side effects of modifying instances ofTarget
. In turn,Target
is a class hierarchy, which we should convert to multiple value types that use composition in the future. In the meantime this also prevents us from making it, and all types that contain it,Sendable
.