Skip to content
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

Enable non-lexigraphic equivalence checking for Compositions #6

Merged
merged 7 commits into from
Jan 13, 2024

Conversation

dfed
Copy link
Owner

@dfed dfed commented Jan 7, 2024

Today, SafeDI considers Foo & Bar and Bar & Foo to be discrete types. However, the compiler does not consider these types to be discrete, and therefore neither should we.

This change enables treating the above compositions as equivalent by utilizing an unordered Set to store the associated types of a TypeDescription.composition.

@dfed dfed force-pushed the dfed--unordered-composition-equivalence branch from 4cdd5e0 to 7d1d71e Compare January 7, 2024 15:40
@dfed dfed requested a review from kierajmumick January 7, 2024 15:41
@dfed dfed marked this pull request as ready for review January 7, 2024 15:41
Copy link

codecov bot commented Jan 7, 2024

Codecov Report

Attention: 3 lines in your changes are missing coverage. Please review.

Comparison is base (b3f0773) 97.73% compared to head (f377618) 97.74%.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main       #6      +/-   ##
==========================================
+ Coverage   97.73%   97.74%   +0.01%     
==========================================
  Files          37       37              
  Lines        7864     7909      +45     
==========================================
+ Hits         7686     7731      +45     
  Misses        178      178              
Files Coverage Δ
Tests/SafeDICoreTests/TypeDescriptionTests.swift 100.00% <100.00%> (ø)
Sources/SafeDICore/Models/TypeDescription.swift 93.60% <87.50%> (-0.47%) ⬇️

... and 1 file with indirect coverage changes

@@ -249,6 +257,8 @@ public enum TypeDescription: Codable, Hashable, Comparable, Sendable {
case typeDescription
/// The value for this key is the associated value of type [TypeDescription]
case typeDescriptions
/// The value for this key is the associated value of type Set<TypeDescription>
case unorderedTypeDescriptions
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not convinced this is a necessary addition. While the extra specificity is nice... the underlying json representations of a Set and Array are identical (aside from ordering).

So my options are:

  1. Introduce this new key
  2. Update the documentation on case typeDescriptions to state that the value here is either an array or set.

I'm currently leaning towards the second option.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah alright talked myself into it and pushed up 8afe45e. Open to feedback, and could be convinced to revert.

@dfed dfed requested a review from MrAdamBoyd January 8, 2024 21:43
@dfed dfed self-assigned this Jan 9, 2024
@dfed dfed added the enhancement New feature or request label Jan 9, 2024
@@ -27,7 +27,7 @@ public enum TypeDescription: Codable, Hashable, Comparable, Sendable {
/// A nested type with possible generics. e.g. Array.Element or Swift.Array<Element>
indirect case nested(name: String, parentType: TypeDescription, generics: [TypeDescription])
/// A composed type. e.g. Identifiable & Equatable
indirect case composition([TypeDescription])
indirect case composition(Set<TypeDescription>)
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A downside of using a Set here is that we no longer know the written order of the types of the composition in the source code. We could offset that by utilizing an array still, and then doing set comparisons in a manually written == implementation, but:

  1. Doing just-in-time Set comparisons can get expensive when doing a lot of comparisons
  2. Maintaining a manually written == implementation sounds... not fun

So I'm pretty bullish that this approach is good enough for our needs. Open to feedback and alternative thoughts of course.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's always OrderedSet from swift-collections, but then you'd be adding a dependency.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup! OrderedSet would solve the just-in-time Set comparison problem. But I'd still need the manually written == which is a bit painful. Might be worth it though?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no qualms with a dependency, especially one that already supports Linux 😄 https://swiftpackageindex.com/apple/swift-collections

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm gonna write a new type that houses both an array and a set, with its own == implementation, and use that.

return types
.map { $0.asSource }
// Sort the result to ensure stable code generation.
.sorted()
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we'll get rid of this line when we introduce the new type

@dfed dfed force-pushed the dfed--unordered-composition-equivalence branch from c9a9fa1 to 4280857 Compare January 13, 2024 01:09
private let set: Set<Element>

public static func == (lhs: UnorderedComparingArray, rhs: UnorderedComparingArray) -> Bool {
lhs.set == rhs.set
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duh, easier than I thought

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardest part was coming up with a name for the type. I'm not convinced I did a great job there.

@@ -425,6 +429,38 @@ extension ExprSyntax {
}
}

// MARK: - UnorderedComparingArray

public struct UnorderedComparingArray<Element: Codable & Hashable & Sendable>: Codable, Hashable, Sendable, Collection {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about changing the name? Having a subscript for an unordered array seems a bit confusing.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All sequences have subscripts, and sequences are not necessarily ordered logically (though their order is stable). It's a quirk of Foundation.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I am super open to other names

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going with UnorderedComparingCollection

Copy link
Collaborator

@MrAdamBoyd MrAdamBoyd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM other than one question

@dfed dfed merged commit 2697747 into main Jan 13, 2024
6 checks passed
@dfed dfed deleted the dfed--unordered-composition-equivalence branch January 13, 2024 02:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants