Giter Site home page Giter Site logo

apple / swift-collections Goto Github PK

View Code? Open in Web Editor NEW
3.5K 157.0 268.0 12.81 MB

Commonly used data structures for Swift

License: Apache License 2.0

Swift 96.26% C++ 1.11% C 0.03% Shell 0.44% CMake 0.85% Python 1.31%
collection container deque dequeue hash ordered-dictionary ordered-set sequence queue

swift-collections's Introduction

Swift Collections

Swift Collections is an open-source package of data structure implementations for the Swift programming language.

Read more about the package, and the intent behind it, in the announcement on swift.org.

Contents

The package currently provides the following implementations:

  • BitSet and BitArray, dynamic bit collections.

  • Deque<Element>, a double-ended queue backed by a ring buffer. Deques are range-replaceable, mutable, random-access collections.

  • Heap, a min-max heap backed by an array, suitable for use as a priority queue.

  • OrderedSet<Element>, a variant of the standard Set where the order of items is well-defined and items can be arbitrarily reordered. Uses a ContiguousArray as its backing store, augmented by a separate hash table of bit packed offsets into it.

  • OrderedDictionary<Key, Value>, an ordered variant of the standard Dictionary, providing similar benefits.

  • TreeSet and TreeDictionary, persistent hashed collections implementing Compressed Hash-Array Mapped Prefix Trees (CHAMP). These work similar to the standard Set and Dictionary, but they excel at use cases that mutate shared copies, offering dramatic memory savings and radical time improvements.

The following additional data structures are currently under development but they aren't stable enough to preview yet.

Swift Collections uses the same modularization approach as Swift Numerics: it provides a standalone module for each thematic group of data structures it implements. For instance, if you only need a double-ended queue type, you can pull in only that by importing DequeModule. OrderedSet and OrderedDictionary share much of the same underlying implementation, so they are provided by a single module, called OrderedCollections. However, there is also a top-level Collections module that gives you every collection type with a single import statement:

import Collections

var deque: Deque<String> = ["Ted", "Rebecca"]
deque.prepend("Keeley")
deque.append("Nathan")
print(deque) // ["Keeley", "Ted", "Rebecca", "Nathan"]

Project Status

The Swift Collections package is source stable. The version numbers follow Semantic Versioning -- source breaking changes to public API can only land in a new major version.

The public API of version 1.1 of the swift-collections package consists of non-underscored declarations that are marked public in the Collections, BitCollections, DequeModule, HeapModule, OrderedCollections and HashTreeCollections modules.

Interfaces that aren't part of the public API may continue to change in any release, including patch releases. If you have a use case that requires using underscored APIs, please submit a Feature Request describing it! We'd like the public interface to be as useful as possible -- although preferably without compromising safety or limiting future evolution.

By "underscored declarations" we mean declarations that have a leading underscore anywhere in their fully qualified name. For instance, here are some names that wouldn't be considered part of the public API, even if they were technically marked public:

  • FooModule.Bar._someMember(value:) (underscored member)
  • FooModule._Bar.someMember (underscored type)
  • _FooModule.Bar (underscored module)
  • FooModule.Bar.init(_value:) (underscored initializer)

Note that contents of the Tests, Utils and Benchmarks subdirectories aren't public API. We don't make any source compatibility promises about them -- they may change at whim, and code may be removed in any new release. Do not rely on anything about them.

Future minor versions of the package may update these rules as needed.

We'd like this package to quickly embrace Swift language and toolchain improvements that are relevant to its mandate. Accordingly, from time to time, new versions of this package require clients to upgrade to a more recent Swift toolchain release. (This allows the package to make use of new language/stdlib features, build on compiler bug fixes, and adopt new package manager functionality as soon as they are available.) Patch (i.e., bugfix) releases will not increase the required toolchain version, but any minor (i.e., new feature) release may do so.

The following table maps existing package releases to their minimum required Swift toolchain release:

Package version Swift version Xcode release
swift-collections 1.0.x >= Swift 5.3.2 >= Xcode 12.4
swift-collections 1.1.x >= Swift 5.7.2 >= Xcode 14.2

(Note: the package has no minimum deployment target, so while it does require clients to use a recent Swift toolchain to build it, the code itself is able to run on any OS release that supports running Swift code.)

Using Swift Collections in your project

To use this package in a SwiftPM project, you need to set it up as a package dependency:

// swift-tools-version:5.9
import PackageDescription

let package = Package(
  name: "MyPackage",
  dependencies: [
    .package(
      url: "https://github.com/apple/swift-collections.git", 
      .upToNextMinor(from: "1.1.0") // or `.upToNextMajor
    )
  ],
  targets: [
    .target(
      name: "MyTarget",
      dependencies: [
        .product(name: "Collections", package: "swift-collections")
      ]
    )
  ]
)

Contributing to Swift Collections

We have a dedicated Swift Collections Forum where people can ask and answer questions on how to use or work on this package. It's also a great place to discuss its evolution.

If you find something that looks like a bug, please open a Bug Report! Fill out as many details as you can.

Branching Strategy

We maintain separate branches for each minor version of the package:

Package version Branch
swift-collections 1.0.x release/1.0
swift-collections 1.1.x release/1.1
swift-collections 1.2.x main

Changes must land on the branch corresponding to the earliest release that they will need to ship on. They are periodically propagated to subsequent branches, in the following direction:

release/1.0release/1.1main

For example, anything landing on release/1.0 will eventually appear on release/1.1 and then main too; there is no need to file standalone PRs for each release line. (Change propagation currently requires manual work -- it is performed by project maintainers.)

Working on the package

We have some basic documentation on package internals that will help you get started.

By submitting a pull request, you represent that you have the right to license your contribution to Apple and the community, and agree by submitting the patch that your contributions are licensed under the Swift License, a copy of which is provided in this repository.

Fixing a bug or making a small improvement

  1. Make sure to start by checking out the appropriate branch for the minor release you want the fix to ship in. (See above.)
  2. Submit a PR with your change. If there is an existing issue for the bug you're fixing, please include a reference to it.
  3. Make sure to add tests covering whatever changes you are making.

Proposing a small enhancement

  1. Raise a Feature Request. Discuss why it would be important to implement it.
  2. Submit a PR with your implementation, participate in the review discussion.
  3. When there is a consensus that the feature is desirable, and the implementation works well, it is fully tested and documented, then it will be merged.
  4. Rejoice!

Proposing the addition of a new data structure

We intend this package to collect generally useful data structures -- the ones that ought to be within easy reach of every Swift engineer's basic toolbox. The implementations we ship need to be of the highest technical quality, polished to the same shine as anything that gets included in the Swift Standard Library. (The only real differences are that this package isn't under the formal Swift Evolution process, and its code isn't ABI stable.)

Accordingly, adding a new data structure to this package is not an easy or quick process, and not all useful data structures are going to be a good fit.

If you have an idea for a data structure that might make a good addition to this package, please start a topic on the forum, explaining why you believe it would be important to implement it. This way we can figure out if it would be right for the package, discuss implementation strategies, and plan to allocate capacity to help.

Not all data structures will reach a high enough level of usefulness to ship in this package -- those that have a more limited audience might work better as a standalone package. Of course, reasonable people might disagree on the importance of including any particular data structure; but at the end of the day, the decision whether to take an implementation is up to the maintainers of this package.

If maintainers have agreed that your implementation would likely make a good addition, then it's time to start work on it. Submit a PR with your implementation as soon as you have something that's ready to show! We'd love to get involved as early as you like. Historically, the best additions resulted from close work between the contributor and a package maintainer.

Participate in the review discussion, and adapt code accordingly. Sometimes we may need to go through several revisions over multiple months! This is fine -- it makes the end result that much better. When there is a consensus that the feature is ready, and the implementation is fully tested and documented, the PR will be merged by a maintainer. This is good time for a small celebration -- merging is a good indicator that the addition will ship at some point.

Historically, PRs adding a new data structure have typically been merged to a new feature branch rather than directly to a release branch or main, and there was an extended amount of time between the initial merge and the tag that shipped the new feature. Nobody likes to wait, but getting a new data structure implementation from a state that was ready to merge to a state that's ready to ship is actually quite difficult work, and it takes maintainer time and effort that needs to be scheduled in advance. The closer an implementation is to the coding conventions and performance baseline of the Standard Library, the shorter this wait is likely to become, and the fewer changes there will be between merging and shipping.

Code of Conduct

Like all Swift.org projects, we would like the Swift Collections project to foster a diverse and friendly community. We expect contributors to adhere to the Swift.org Code of Conduct. A copy of this document is available in this repository.

Contact information

The current code owner of this package is Karoy Lorentey (@lorentey). You can contact him on the Swift forums, or by writing an email to klorentey at apple dot com. (Please keep it related to this project.)

In case of moderation issues, you can also directly contact a member of the Swift Core Team.

swift-collections's People

Contributors

amonshiz avatar aquageek avatar compnerd avatar ctmacuser avatar ejmarchant avatar ensan-hcl avatar felixherrmann avatar frizlab avatar glessard avatar hassila avatar hectormatos2011 avatar jpaolantonio avatar just-gull avatar kati-kms avatar kielgillard avatar ktoso avatar leonavel avatar lorentey avatar mahanazatiqullah avatar msteindorfer avatar neonichu avatar nickkohrn avatar numist avatar rex4539 avatar rkreutz avatar shahmishal avatar toddpress avatar vanvoorden avatar vihanb avatar warpling avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swift-collections's Issues

License.txt doesn't define the licensor / copyright holder, nor the years

A common thing for Apache licensed software is to provide the "short" version in the readme.
This can easily be copied for open source attribution pages.

The source code would potentially suggest this is that text:

Copyright (c) 2021 Apple Inc. and the Swift project authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

It's also possible that it should have a variation to mention the runtime exception, or link to the Swift.org mirrored license

Simranjit

Replace this paragraph with a short description of the incorrect behavior.
(If this is a regression, please note the last version of the package that exhibited the correct behavior in addition to your current version.)

Information

  • Package version: What tag or branch of swift-collections are you using?
  • Platform version: Please tell us the version number of your operating system.
  • Swift version: Paste the output of swift --version here.

Checklist

  • If possible, I've reproduced the issue using the main branch of this package.
  • I've searched for existing GitHub issues.

Steps to Reproduce

Replace this paragraph with an explanation of how to reproduce the incorrect behavior.
Include a simple code example, if possible.

Expected behavior

Describe what you expect to happen.

Actual behavior

Describe or copy/paste the behavior you observe.

Priority queue

Priority queues are commonly requested data structures, and are universally useful. A high-quality implementation would be a natural candidate for inclusion in this package. (Priority queues are used in sorting algorithms, various graph algorithms, networking protocol implementations, etc. etc. etc.)

I expect a straightforward array-backed binary heap might make most sense for the initial implementation, but I wouldn't be surprised if a fancier variant proved better overall.

struct Heap<Element: Comparable>

This would likely be mostly an implementation exercise rather than an API design challenge (although API design is never trivial). We'd probably need to experiment with several different data structure implementations, and perhaps even come up with our own variants that's better suited to Swift's unique combination of language features.

DequeModule compilation error on Ubuntu

I'm trying to build a CLI tool in GitHub Actions with a dependency on this package. It's building fine on macOS but it fails to build on Ubuntu 20.04.2 LTS fails. I'm using fwal/setup-swift@v1 to install Swift on the ubuntu environment.
I apologise if this is not an issue on the package itself.

Information

  • Package version: Tried both 0.0.3 and the most recent commit c0549b6
  • Platform version: Ubuntu 20.04.2 LTS
  • Swift version: Swift version 5.4 (swift-5.4-RELEASE) | Target: x86_64-unknown-linux-gnu

Checklist

  • If possible, I've reproduced the issue using the main branch of this package.
  • I've searched for existing GitHub issues.

Actual behavior

The compiler error is as follows:

gnu/debug/DequeModule.swiftmodule
2021-06-16T14:48:22.9117174Z <unknown>:0: error: fatal error encountered while reading from module 'DequeModule'; please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the project
2021-06-16T14:48:22.9119412Z <unknown>:0: note: module 'DequeModule' full misc version is '5.4(5.4)/Swift version 5.4 (swift-5.4-RELEASE)'
2021-06-16T14:48:22.9120239Z 
2021-06-16T14:48:22.9121042Z *** DESERIALIZATION FAILURE (please include this section in any bug report) ***
2021-06-16T14:48:22.9121888Z result not found
2021-06-16T14:48:22.9122743Z Cross-reference to module 'DequeModule'
2021-06-16T14:48:22.9123511Z ... Deque
2021-06-16T14:48:22.9124310Z ... in an extension in module 'DequeModule'
2021-06-16T14:48:22.9125028Z ... Element
2021-06-16T14:48:22.9125472Z 
2021-06-16T14:48:22.9126669Z Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the project and the crash backtrace.
2021-06-16T14:48:22.9127715Z Stack dump:
2021-06-16T14:48:22.9174473Z 1.	Swift version 5.4 (swift-5.4-RELEASE)
2021-06-16T14:48:22.9175397Z 2.	While evaluating request ASTLoweringRequest(Lowering AST to SIL for module DequeModule)
2021-06-16T14:48:22.9176720Z 3.	While deserializing SIL function "$s11DequeModule0A0VAASERzlE6encode2toys7Encoder_p_tKF"
2021-06-16T14:48:22.9178025Z 4.	While reading from 'DequeModule'
2021-06-16T14:48:22.9179066Z 5.	While finishing conformance for protocol conformance to 'Sequence' (in module 'Swift') for type 'Deque<Element>'

Full logs

swift-collections exports its benchmark runner

.executable(name: "swift-collections-benchmark", targets: ["swift-collections-benchmark"]),

The above line will export the benchmark-runner to all dependents (it'll even show up in Xcode's UI if you add Collections to add as a dependency of your own app/lib).

You can just remove the above line swift run swift-collections-benchmark will still function but it will not be exported to other packages.

`SortedSet` returns different results for equal indexes.

I encountered the issue when trying to get an absolute position of the element and got incorrect results.
I started a conversation on forum because I wasn't sure if it's a bug.

let index = set.index(of: X)
print(index == set.startIndex) // true
print(set[index] == set[set.startIndex]) // false

Information

Package version: Branch feature/SortedCollections
Platform version: macOS 12.2 Beta (21D5025f)
Swift version:

swift-driver version: 1.26.21 Apple Swift version 5.5.2 (swiftlang-1300.0.47.5 clang-1300.0.29.30)
Target: arm64-apple-macosx12.0

Checklist

  • If possible, I've reproduced the issue using the main branch of this package.
  • I've searched for existing GitHub issues.

Steps to Reproduce

Sample code:

var set = SortedSet<Int>()
        
for i in 0..<50 {
   set.insert(i)
}
        
set.forEach {
   let i = set.index(of: $0)!
   let v = set[i]
   let d = set.distance(from: set.startIndex, to: i)
   print("\(v) --> \(d)")

   if i == set.startIndex {
      print("Current `index` equals `startIndex`.")
      print("set[index] = \(set[i]). set[startIndex] = \(set[set.startIndex])")
   }
}

Output:

0 --> 0
Current index equals startIndex.
set[index] = 0. set[startIndex] = 0
1 --> 1
2 --> 0
Current index equals startIndex.
set[index] = 2. set[startIndex] = 0
3 --> 3
4 --> 4
5 --> 1
6 --> 6
7 --> 7
8 --> 0
...

Expected behavior

When indexes are equal, getting a value for those indexes should return the same value.

Actual behavior

Even though indexes are equal, getting a value for them returns different results.

Conform `OrderedDictionary` to `Collection` by wrapping integer indices in a non-`Hashable` index type

This is likely a bad idea. I'm pitching it here on the off-chance that it might lead to a better solution.

Currently OrderedDictionary is unable to conform to Collection because it's unable to implement subscript(position:), which is because it conflicts with subscript(key:) when the dictionary's keys are of its index type (Int).

Meanwhile, Dictionary avoids this and conforms to Collection by using an index type that almost certainly won't be used for keys.

What if we do something similar for OrderedDictionary , while still using Int for actual indixing? One possible solution in my opinion is wrapping Int in a new Index type for only Collection requirements (#58):

extension OrderedDictionary: Collection {

  public struct Index: Comparable {
    public static func < (lhs: Self, rhs: Self) -> Bool {
      lhs.value < rhs.value
    }
    
    public init(value: Int) {
      self.value = value
    }
    
    public let value: Int
  }

  public var startIndex: Index {
    Index(value: _keys.startIndex)
  }

  public var endIndex: Index {
    Index(value: _keys.endIndex)
  }

  public func index(after i: Index) -> Index {
    Index(value: _keys.index(after: i.value))
  }

  public subscript(position: Index) -> (key: Key, value: Value) {
    get { (_keys[position.value], _values[position.value]) }
  }

}

Because Index in the above snippet does not conform to Hashable, it's guaranteed that it cannot be used as Key.

The disadvantage, though, is that with something like this, there will be 2 index types visible to the user:

let orderedDictionary: OrderedDictionary = [1: "a", 2: "b"]
print(orderedDictionary.index(forKey: 1)) // prints "0"
print(orderedDictionary.startIndex)       // prints "Index(value: 0)"

Although it's straightforward to convert between Int and Index, it can be a surprise and source of confusion to new users.

Move Documentation into swift-docc format

Move the current Documentation folder content into the Sources/* folder's *.docc to fit swift-docc.

It can provide a better documentation when used in Xcode and later be hosted on a website.

The tutorial file can be added later.

Bug in CheckCollection from CollectionsTestSupport?

I am adopting CollectionsTestSupport code for my own testing purpose. I noticed that in checkCollection, distance(from:to:), the testing code seems to get all possible pairs of all indices, rather than making sure that the first index is less or equal to the second one:

// Check `distance(from:to:)`
withEvery("i", in: allIndices.indices) { i in
withEvery("j", in: allIndices.indices) { j in
let d = collection.distance(from: allIndices[i], to: allIndices[j])
expectEqual(d, j - i)
}
}

I believe the documentation for Collection says:

Unless the collection conforms to the BidirectionalCollection protocol, start must be less than or equal to end.

So this is probably a bug? It causes issues for my non-bidirectional collections.

OrderedSet.insert should be @discardableResult

Often I just need to insert an element into the OrderedSet. For now I need to prefix that with '_ = ' which in my option should be avoided. Please consider adding @discardableResult to

insert(_ item: Element, at index: Index) -> (inserted: Bool, index: Index)

Best, Felix

[Treap] Fast random insertions collection

At this moment, no collection can address random insertions. I have a data structure implemented through implicit Treap that behaves like a general array but can do random insertions/deletions/access with O(log n).

If such a container is needed, I can open a PR. What do you think?

[Heap] Improved consistency checking

The current Heap._checkInvariants method doesn't fully validate the min-max invariants -- it just checks to see if the property holds for the immediate children of any node.

Instead, we should compare the value stored in every node with a currently expected range of values.

E.g., in the tree below, when checking descendants of 11, each value needs to be within the range 11 ... 41. Each new level narrows this range a bit further (by refining the lower or upper bounds, depending on the polarity of the node).

 level 0:                 8
 level 1:         71              41
 level 2:     31      10      11      16
 level 3:   46  51  31  21  13

Implementing this would mean that we'd have to keep track of a stack of expected ranges in addition to their associated indices. (Or switch to a recursive implementation.)

OrderedSet append does not return the same type as insert

The API for insert in an OrderedSet is

public mutating func insert(_ item: Element, at index: Index) -> (inserted: Bool, index: Index)

and the one for append is

public mutating func append(_ item: Element) -> (inserted: Bool, index: Int)

I understand the return types are technically the same because Index is Int, always, but from a semantic point of view, shouldn’t the append method return a (inserted: Bool, index: Index) tuple?

Information

  • Package version: Swift Collection 0.0.2
  • Platform version: macOS 11.3
  • Swift version:
Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55)
Target: x86_64-apple-darwin20.4.0

Checklist

  • If possible, I've reproduced the issue using the main branch of this package.
  • I've searched for existing GitHub issues.

Steps to Reproduce

N/A

Expected behavior

OrderedSet’s append method to return (inserted: Bool, index: Index).

Actual behavior

It returns (inserted: Bool, index: Int).

Build fails if BUILD_LIBRARY_FOR_DISTRIBUTION is set to YES

Hello,
At Tuist we cache project's frameworks via xcframeworks and thus we add BUILD_LIBRARY_FOR_DISTRIBUTION=YES to xcodebuild command when building. This has worked fine but it's a problem when a project depends on swift-collections as build fails if we specify the BUILD_LIBRARY_FOR_DISTRIBUTION setting.

How hard would it be to make compilation work also with this flag?

Information

  • Package version: 0.0.7
  • Platform version: macOS 11.5.1
  • Swift version: Apple Swift version 5.4.2 (swiftlang-1205.0.28.2 clang-1205.0.19.57) Target: x86_64-apple-darwin20.6.0

Checklist

  • If possible, I've reproduced the issue using the main branch of this package.
  • I've searched for existing GitHub issues.

Steps to Reproduce

Run swift build -Xswiftc -enable-library-evolution

Expected behavior

Build should work fine

Actual behavior

Build fails with error:

swift build -Xswiftc -enable-library-evolution                                                                                                               15:09:48
/wrkdir/swift-collections/Sources/DequeModule/_DequeBuffer.swift:14:3: error: deinitializer can only be '@inlinable' if the class is '@_fixed_layout'
  @inlinable
  ^~~~~~~~~~

/wrkdir/swift-collections/Sources/DequeModule/_DequeBuffer.swift:14:3: error: deinitializer can only be '@inlinable' if the class is '@_fixed_layout'
  @inlinable
  ^~~~~~~~~~

/wrkdir/swift-collections/Sources/DequeModule/_UnsafeWrappedBuffer.swift:26:10: error: 'let' property 'first' may not be initialized directly; use "self.init(...)" or "self = ..." instead
    self.first = first
         ^
/wrkdir/swift-collections/Sources/DequeModule/_UnsafeWrappedBuffer.swift:15:16: note: 'first' declared here
  internal let first: UnsafeBufferPointer<Element>
               ^
/wrkdir/swift-collections/Sources/DequeModule/_UnsafeWrappedBuffer.swift:27:10: error: 'let' property 'second' may not be initialized directly; use "self.init(...)" or "self = ..." instead
    self.second = second
         ^
/wrkdir/swift-collections/Sources/DequeModule/_UnsafeWrappedBuffer.swift:18:16: note: 'second' declared here
  internal let second: UnsafeBufferPointer<Element>?
               ^
/wrkdir/swift-collections/Sources/DequeModule/_UnsafeWrappedBuffer.swift:68:10: error: 'let' property 'first' may not be initialized directly; use "self.init(...)" or "self = ..." instead
    self.first = first
         ^
/wrkdir/swift-collections/Sources/DequeModule/_UnsafeWrappedBuffer.swift:57:16: note: 'first' declared here
  internal let first: UnsafeMutableBufferPointer<Element>
               ^
/wrkdir/swift-collections/Sources/DequeModule/_UnsafeWrappedBuffer.swift:69:10: error: 'let' property 'second' may not be initialized directly; use "self.init(...)" or "self = ..." instead
    self.second = second?.count == 0 ? nil : second
         ^
/wrkdir/swift-collections/Sources/DequeModule/_UnsafeWrappedBuffer.swift:60:16: note: 'second' declared here
  internal let second: UnsafeMutableBufferPointer<Element>?
               ^
/wrkdir/swift-collections/Sources/DequeModule/_UnsafeWrappedBuffer.swift:26:10: error: 'let' property 'first' may not be initialized directly; use "self.init(...)" or "self = ..." instead
    self.first = first
         ^
/wrkdir/swift-collections/Sources/DequeModule/_UnsafeWrappedBuffer.swift:15:16: note: 'first' declared here
  internal let first: UnsafeBufferPointer<Element>
               ^
/wrkdir/swift-collections/Sources/DequeModule/_UnsafeWrappedBuffer.swift:27:10: error: 'let' property 'second' may not be initialized directly; use "self.init(...)" or "self = ..." instead
    self.second = second
         ^
/wrkdir/swift-collections/Sources/DequeModule/_UnsafeWrappedBuffer.swift:18:16: note: 'second' declared here
  internal let second: UnsafeBufferPointer<Element>?
               ^
/wrkdir/swift-collections/Sources/DequeModule/_UnsafeWrappedBuffer.swift:68:10: error: 'let' property 'first' may not be initialized directly; use "self.init(...)" or "self = ..." instead
    self.first = first
         ^
/wrkdir/swift-collections/Sources/DequeModule/_UnsafeWrappedBuffer.swift:57:16: note: 'first' declared here
  internal let first: UnsafeMutableBufferPointer<Element>
               ^
/wrkdir/swift-collections/Sources/DequeModule/_UnsafeWrappedBuffer.swift:69:10: error: 'let' property 'second' may not be initialized directly; use "self.init(...)" or "self = ..." instead
    self.second = second?.count == 0 ? nil : second
         ^
/wrkdir/swift-collections/Sources/DequeModule/_UnsafeWrappedBuffer.swift:60:16: note: 'second' declared here
  internal let second: UnsafeMutableBufferPointer<Element>?
               ^
/wrkdir/swift-collections/Sources/DequeModule/Deque._UnsafeHandle.swift:31:12: error: 'let' property '_header' may not be initialized directly; use "self.init(...)" or "self = ..." instead
      self._header = header
           ^
/wrkdir/swift-collections/Sources/DequeModule/Deque._UnsafeHandle.swift:16:9: note: '_header' declared here
    let _header: UnsafeMutablePointer<_DequeBufferHeader>
        ^
/wrkdir/swift-collections/Sources/DequeModule/Deque._UnsafeHandle.swift:32:12: error: 'let' property '_elements' may not be initialized directly; use "self.init(...)" or "self = ..." instead
      self._elements = elements
           ^
/wrkdir/swift-collections/Sources/DequeModule/Deque._UnsafeHandle.swift:18:9: note: '_elements' declared here
    let _elements: UnsafeMutablePointer<Element>
        ^
/wrkdir/swift-collections/Sources/DequeModule/Deque._UnsafeHandle.swift:34:12: error: 'let' property '_isMutable' may not be initialized directly; use "self.init(...)" or "self = ..." instead
      self._isMutable = isMutable
           ^
/wrkdir/swift-collections/Sources/DequeModule/Deque._UnsafeHandle.swift:21:9: note: '_isMutable' declared here
    let _isMutable: Bool
        ^
/wrkdir/swift-collections/Sources/DequeModule/Deque._UnsafeHandle.swift:31:12: error: 'let' property '_header' may not be initialized directly; use "self.init(...)" or "self = ..." instead
      self._header = header
           ^
/wrkdir/swift-collections/Sources/DequeModule/Deque._UnsafeHandle.swift:16:9: note: '_header' declared here
    let _header: UnsafeMutablePointer<_DequeBufferHeader>
        ^
/wrkdir/swift-collections/Sources/DequeModule/Deque._UnsafeHandle.swift:32:12: error: 'let' property '_elements' may not be initialized directly; use "self.init(...)" or "self = ..." instead
      self._elements = elements
           ^
/wrkdir/swift-collections/Sources/DequeModule/Deque._UnsafeHandle.swift:18:9: note: '_elements' declared here
    let _elements: UnsafeMutablePointer<Element>
        ^
/wrkdir/swift-collections/Sources/DequeModule/Deque._UnsafeHandle.swift:34:12: error: 'let' property '_isMutable' may not be initialized directly; use "self.init(...)" or "self = ..." instead
      self._isMutable = isMutable
           ^
/wrkdir/swift-collections/Sources/DequeModule/Deque._UnsafeHandle.swift:21:9: note: '_isMutable' declared here
    let _isMutable: Bool
        ^
/wrkdir/swift-collections/Sources/DequeModule/Deque+Collection.swift:31:21: error: 'self' used before 'self.init' call or assignment to 'self'
      self._storage = _storage
                    ^
/wrkdir/swift-collections/Sources/DequeModule/Deque+Collection.swift:32:22: error: 'self' used before 'self.init' call or assignment to 'self'
      self._nextSlot = start
                     ^
/wrkdir/swift-collections/Sources/DequeModule/Deque+Collection.swift:33:21: error: 'self' used before 'self.init' call or assignment to 'self'
      self._endSlot = end
                    ^
/wrkdir/swift-collections/Sources/DequeModule/Deque+Collection.swift:34:5: error: 'self.init' isn't called on all paths before returning from initializer
    }
    ^
/wrkdir/swift-collections/Sources/DequeModule/Deque+Collection.swift:31:21: error: 'self' used before 'self.init' call or assignment to 'self'
      self._storage = _storage
                    ^
/wrkdir/swift-collections/Sources/DequeModule/Deque+Collection.swift:32:22: error: 'self' used before 'self.init' call or assignment to 'self'
      self._nextSlot = start
                     ^
/wrkdir/swift-collections/Sources/DequeModule/Deque+Collection.swift:33:21: error: 'self' used before 'self.init' call or assignment to 'self'
      self._endSlot = end
                    ^
/wrkdir/swift-collections/Sources/DequeModule/Deque+Collection.swift:34:5: error: 'self.init' isn't called on all paths before returning from initializer
    }
    ^
/wrkdir/swift-collections/Sources/DequeModule/Deque+Collection.swift:31:21: error: 'self' used before 'self.init' call or assignment to 'self'
      self._storage = _storage
                    ^
/wrkdir/swift-collections/Sources/DequeModule/Deque+Collection.swift:32:22: error: 'self' used before 'self.init' call or assignment to 'self'
      self._nextSlot = start
                     ^
/wrkdir/swift-collections/Sources/DequeModule/Deque+Collection.swift:33:21: error: 'self' used before 'self.init' call or assignment to 'self'
      self._endSlot = end
                    ^
/wrkdir/swift-collections/Sources/DequeModule/Deque+Collection.swift:34:5: error: 'self.init' isn't called on all paths before returning from initializer
    }
    ^

[Heap] Convert CFBinaryHeap benchmarks to C

The CFBinaryHeap reference benchmarks are currently defined as an Objective-C class. These microbenchmarks could be sensitive to ObjC messaging overhead (however small it is) -- it would make sense to convert them to a pure C interface instead, like we did with the existing std::deque etc benchmarks.

Ordered collection with stable indices

Hello everyone,

I'd like to suggest adding an ordered collection similar to Swift's Array, but with stable indices.

What am I suggesting?

Like many collections, Array stores elements in contiguous storage, for well-known performance reasons. The issue with that strategy, however, is that the index of an element is not stable. By stable, I mean that inserting or removing elements will invalidate indices of existing elements.

var a: Array = ["a", "b", "c"]
let i = a.firstIndex(of: "c")!
a.remove(at: 1)
print(a[i]) // Fatal error: Index out of range

In contrast, a collection with stable indices would guarantee that the index of an element does not change if other elements are inserted or removed.

var a: StableArray = ["a", "b", "c"]
let i = a.firstIndex(of: "c")!
a.remove(at: 1)
print(a[i]) // Prints "c"

How is it useful?

Stable indices can be used to store the identity of a value in another data structure. For instance, one may wish to store some large elements in a dynamically resizable container and refer to them in an adjacency list, to represent a graph connecting these elements.

As a concrete example, I use such a container to represent basic blocks in an LLVM-like IR. Indices keep track of the position of an instruction in its basic block and are stored in various data structures, such as the def-use chain of an instruction. They need to be stable so that inserting a new instruction into a basic block does not change the index of any other instruction.

As a result, basic blocks can adopt (mutable) value semantics. An instruction is merely a tag with an immutable list of operands, uniquely identified by its index in a basic block.

Can we use existing data structures?

We can get close to an ordered collection with stable indices using hash maps.

Using Dictionary

A Dictionary has stable indices but does not preserve the order in which elements have been inserted. This problem could be solved by choosing keys such that they have a total order, but that approach would suffer from two issues:

First, it would require an ad-hoc key generator that is guaranteed to produce unique keys. This generator would also have to keep track of a total order between these keys, should insertion at random position be supported. One trick to solve that latter issue could be to choose keys from a dense range (e.g., rational numbers).

Second, there would be no obvious way to iterate over the dictionary in order, or determine the distance between two (stable) indices, or offset an index by a specific distance. Since the dictionary is unordered, distances would have to be computed using an ad-hoc data structure. The simplest approach would be to sort the dictionary's keys. A more efficient solution would be to have a cache maintained by the generator.

Using OrderedDictionary

OrderedDictionary solves part of the problem by preserving the order in which elements are inserted. In fact, its implementation already covers most of the aforementioned ad-hoc objects required to use Swift's Dictionary. Unfortunately, it still suffers from two issues:

First, as far as I am aware, OrderedDictionary does not support insertion at a random position. It also does not offer a method to retrieve the first/last key of a particular value (i.e., equivalences for firstIndex(of:) and lastIndex(of:) of Swift's ReversibleCollection). As a result, there is no way to compute distances with that data structure alone.

Second, even if the aforementioned feature was actually available, an ad-hoc object would still be required to generate unique keys, just like with the standard Dictionary.

Possible implementation

One possible implementation is to use a doubly linked list in which forward and backward pointers are encoded as offsets from the base address of a memory buffer. That way, the buffer can be copied or resized without invalidating the offsets, which is necessary to implement dynamically resizable containers and copy-on-write, respectively.

An index in that container is simply an offset from the base address of its internal buffer. It is stable, since insertion or removal merely changes the forward/backward pointers of the neighboring elements.

before removal:
  list: (nil, "a", +1) <-> (+0, "b", +2) <-> (+1, "c", nil)
  buffer: [(nil, "a", +1), (+0, "b", +2), (+1, "c", nil)]
remove(at: +1):
  list: (nil, "a", +2) <-> (+0, "c", nil)
  buffer: [(nil, "a", +1), nil, (+0, "c", nil)]

Note: empty "cells" can be used to store the index of the next empty cell, so that space freed after a removal can be reused for the next insertion.

This strategy sacrifies contiguous storage for stable indices and O(1) insertion/removal. An important drawback is that indices are not strideable (in the sense of Swift's Strideable protocol) without access to the container. Therefore, one cannot conform to Collection without having indices hold a pointer to the collection's buffer.

I have an (unprofiled, unoptimized, barely tested) implementation of that strategy here. I would be happy to work on a pull request, should there be any interest in merging an ordered collection with stable indices.

Other implementations

StableVec offers arrays with stable indices in Rust. The implementation is simpler than my proposal, relying on a standard array (or vector in Rust's parlance) instead of a doubly linked list. However, index stability is only preserved for removal, not for insertion.

[Heap] Switch to a custom _Index type that incrementally tracks depth

The Heap implementation currently uses naked integers as indices, and uses _binaryLogarithm to determine whether a particular index addresses a min or max node. This is a relatively expensive(*) operation that may have some measurable performance impact.

(*) Well, at least compared to a mov?

Instead, try switching to a custom _Index struct containing both a storage position and its associated depth.

Beyond a potential performance win, this would also allow for better code organization -- by allowing us to move the utility methods for retrieving the parents/children of an index to the Index type itself:

struct _Index: Comparable {
  let offset: Int
  let level: Int

  func parent() -> _Index?
  func grandParent() -> Index?
  func leftChild() -> _Index
  func rightChild() -> _Index
}

[Heap] Express heap operations on UnsafeMutableBufferPointer

Heap currently uses regular array subscripting to access the contents of its storage. Array access is pretty fast, but it includes index validation that is (hopefully) unnecessary in Heap's case. I expect the optimizer is able to get rid of these index validations in some (but not all) cases; but it probably makes sense to not have them in the first place.

Rework the low-level heap implementation to operate on UnsafeMutableBuffer storage instead, turning index checks into debug-mode assertions rather than unconditional preconditions.

To do this, it would make sense to introduce a Heap._UnsafeHandle or _UnsafeHeap struct that consists of an UnsafeMutableBufferPointer value, and move most heap operation to that. We'll need to have closure-based read and update helpers that expose a read-only (or read-write) view of the Array storage. (Similar to how Deque and OrderedSet's hash tables work.)

[Heap] Figure out what exactly makes `Array.swapAt` slow

The Heap implementation needed to switch from Array.swapAt to a hand-rolled swap implementation to get acceptable performance. (See associated discussion and bug report.)

Look at generated code to figure out what's going on and do whatever it takes to fix it, either within this package or (more likely) in the stdlib.

(Note that Array does not come with a custom swapAt implementation -- it just inherits the default implementation from MutableCollection. However, this alone does not explain the issue -- that default implementation is literally the same code as what this package is using.)

Weak-keyed/weak-valued hashed collections

A weak Set and a weak-keyed (or weak-valued) Dictionary are often-requested data structures that aren't easy to implement. It's especially difficult to do it correctly in terms of the existing Set and Dictionary -- most attempts end up accidentally changing the identity of keys already in a hash table, which violates invariants and leads to runtime errors.

This package would be a good place to host a set of weak collection implementations.

While the implementation isn't entirely trivial, I expect this will be mostly an API design challenge. Some notes:

  • These would work best if they came with their own hash table implementation whose lookup etc. operations are aware of the fact that keys/values could disappear at any moment, and are able to update the table accordingly.
  • Deallocated keys work like tombstones.
  • The Element, Key and/or Value types would be constrained to AnyObject. We can probably still allow custom Hashable implementations, as long as the hash table operations are aware of niled out entries. The tradeoff here is that requiring Hashable will make developers do more work by having to manually implement it, even if they only want to use object identity.
  • Ideally lookup operations would be able to incrementally update the table by getting rid of obsolete entries they encounter. A mutating lookup would probably preclude the use of these types in concurrent contexts. This is fine -- these are typically used for caches local to a particular actor.
  • These types probably won't be able to conform to Collection as their count can change at any point. This is fine -- they shouldn't even provide a count of live entries.
  • The types may or may not implement value semantics (depending on whichever choice makes most sense). This is fine.

Implement `move(fromOffsets:toOffset:)` and `remove(atOffsets:)`

SwiftUI defines MutableCollection.move(fromOffsets:toOffset:) and RangeReplaceableCollection.remove(atOffsets:) methods, which make it easy to interface with the onMove(perform:) and onDelete(perform:) view modifiers.

It'd be nice if the appropriate collections herein implemented the same functionality.

We've implemented both in our Identified Collections package, since the IdentifiedArray type is intended to be used in SwiftUI:

But it'd be nice to leverage more performant, upstream implementations on the OrderedDictionary it wraps instead.

`SortedSet` invariants can be broken if `Element` violates `Comparable` requirements

SortedSet incorrectly reports that the element is not contained in it.

Information

  • Package version: Branch feature/SortedCollections
  • Platform version: macOS 12.2 Beta (21D5025f)
  • Swift version:

swift-driver version: 1.26.21 Apple Swift version 5.5.2 (swiftlang-1300.0.47.5 clang-1300.0.29.30)
Target: arm64-apple-macosx12.0

Checklist

Steps to Reproduce

The issue happens when two elements are "NOT EQUAL" when compared via "==" operator, but "<" always returns false for them.

Here's a sample code:

struct Element: Comparable {      
     var id: UUID
     var value: Int
        
     static func < (lhs: Element, rhs: Element) -> Bool {
         lhs.value < rhs.value
     }
}
    
func test() {
     var set = SortedSet<Element>()
        
     let a = Element(id: UUID(), value: 0)
     let b = Element(id: UUID(), value: 0)
        
      // Inserts A
     set.insert(a)
     assert(set.contains(a))
        
     // Inserts B
     set.insert(b)
     print(set.count)                    // ---> "2"
     assert(set.contains(b))       // ---> CRASH
}

Expected behavior

set.contains returns true for the element that was inserted.

Actual behavior

set.contains returns false for the element that was already inserted.

Codable Support

I was trying to use the OrderedDictionary in a Codable struct.
I have some API requests that I receive a few dictionaries and I would like to preserve that order.
Previously I have a property like this.

let foos: [String: Foo]

And the parse works just fine, but the order of the items isn't guaranteed.

So I changed to this,

let foos: OrderedDictionary<String, Foo>

and I get this error.

"Expected to decode Array<Any> but found a dictionary instead."

It would be great if you give support Codable parsing.

[Heap] Add reference benchmarks for `std::priority_queue`

The C++ standard library comes with a std::priority_queue type (as well as standalone heap operations) that works as an adapter around a random-access container. We should add microbenchmarks for its operations so that we have an additional set of baselines against which we could compare Heap's performance.

Ambiguous initializers

Duplicate initializers for OrderedDictionary cause ambiguity in the compiler when it tries to resolve an initializer, however only under certain circumstances. I'm not 100% certain about what the scope of the issue is, but have included sample code for a data point on where the issue is reproduced.

The issue also reproduces in other scenarios which do not look like the included sample (in more complex projects).

Competing initializers:

Information

  • Package version: 1.0.1
  • Platform version: macOS 11.3.1 (20E241)
  • Swift version: 5.5.1 (swiftlang-1300.0.31.4 clang-1300.0.29.6)

Checklist

  • If possible, I've reproduced the issue using the main branch of this package.
  • I've searched for existing GitHub issues.

Steps to Reproduce

let names = ["dylan", "bob", "aaron", "carol"]
let dict1 = OrderedDictionary(uniqueKeysWithValues: names.map { ($0, 0) })
let dict2 = OrderedDictionary(uniqueKeysWithValues: ["dylan", "bob", "aaron", "carol"].map { ($0, 0) })

Expected behavior

Notice that dict1 initialization compiles fine. I expect dict2 initialization to compile fine as well.

Actual behavior

dict2 initialization fails, error:

/Users/lhunath/workspace/local/Sandbox/Sandbox/SandApp.swift:25:17: error: ambiguous use of 'init(uniqueKeysWithValues:)'
    let dict2 = OrderedDictionary(uniqueKeysWithValues: ["dylan", "bob", "aaron", "carol"].map { ($0, 0) })
                ^
/Users/lhunath/Library/Developer/Xcode/DerivedData/Sandbox-cngswxsbmagplshicoojnvdjrear/SourcePackages/checkouts/swift-collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Initializers.swift:79:10: note: found this candidate
  public init<S: Sequence>(
         ^
/Users/lhunath/Library/Developer/Xcode/DerivedData/Sandbox-cngswxsbmagplshicoojnvdjrear/SourcePackages/checkouts/swift-collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Initializers.swift:115:10: note: found this candidate
  public init<S: Sequence>(
         ^

`OrderedSet.index(of:)`

The standard Set types provides an index(of:) method. Like Set, OrderedSet also promises that its members are unique, so I believe it would make sense to add index(of:) to OrderedSet, too -- this will make for clearer code at the point of use than if we only had Collection's firstIndex(of:)/lastIndex(of:).

Fails to compile (Abort trap: 6)

Failed to compile using SPM.

TLDR (log file attached below)

Abort Trap: 6

<unknown>:0: error: fatal error encountered while reading from module 'OrderedCollections'; please file a bug report with your project and the crash log
<unknown>:0: note: module 'OrderedCollections' full misc version is '5.3.2(5.3.2)/Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)'

*** DESERIALIZATION FAILURE (please include this section in any bug report) ***
result not found
Cross-reference to module 'OrderedCollections'
... OrderedSet
... in an extension in module 'OrderedCollections'
... Element

Information

  • Package version: What tag or branch of swift-collections are you using?
    • 0.0.1
  • Platform version: Please tell us the version number of your operating system.
    • macOS: 11.2.1 (20D74)
    • Xcode: 12.4 (12D4e)
    • Simulator/device: Doesn't seem to matter
  • Swift version: Paste the output of swift --version here.
    • Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)
    • Target: x86_64-apple-darwin20.3.0

EDIT: Adding more details today

~ > sw_vers                                                                                                            system
ProductName:	macOS
ProductVersion:	11.2.3
BuildVersion:	20D91

~ > uname -a                                                                                                           system
Darwin ****.local 20.3.0 Darwin Kernel Version 20.3.0: Thu Jan 21 00:07:06 PST 2021; root:xnu-7195.81.3~1/RELEASE_X86_64 x86_64

~ > swift --version                                                                                                    system
Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)
Target: x86_64-apple-darwin20.3.0

~ > clang --version                                                                                                    system
Apple clang version 12.0.0 (clang-1200.0.32.29)
Target: x86_64-apple-darwin20.3.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin`

Checklist

  • If possible, I've reproduced the issue using the main branch of this package.
  • I've searched for existing GitHub issues.

Steps to Reproduce

  • Create new iOS app in Xcode (just default code)
  • Set up SPM to include this repo at v 0.0.1 (same for main)
  • Build
    • iOS app target fails (log file attached below)
    • Collections target fails
    • CollectionsBenchmark target fails
    • DequeModule succeeds
    • OrderedCollections target fails
    • swift-collections-benchmark fails
    • swift-collections-benchmark-Package succeeds
    • swift-collections-Package fails

Expected behavior

Expect SPM to compile the targets in this repo

Actual behavior

Build fails. see attached build log

`OrderedCollections` module fails to build with Bazel

Information

  • Package version: 1.0.0
  • Platform version: macOS 12.1 (21C52)
  • Swift version: Apple Swift version 5.5.2 (swiftlang-1300.0.47.5 clang-1300.0.29.30)

Checklist

  • If possible, I've reproduced the issue using the main branch of this package.
  • I've searched for existing GitHub issues.

Steps to Reproduce

I'm using Bazel build system and I met a build failure with the following stack trace whenever I tried to use xcconfig which had -assert-config Debug flag:

INFO: From Compiling Swift module OrderedCollections:
Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the project and the crash backtrace.
Stack dump:
0.	Program arguments: /Applications/Xcode-13.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend -frontend -c external/Collections/Sources/OrderedCollections/HashTable/_HashTable+Bucket.swift external/Collections/Sources/OrderedCollections/HashTable/_HashTable+BucketIterator.swift external/Collections/Sources/OrderedCollections/HashTable/_HashTable+Constants.swift external/Collections/Sources/OrderedCollections/HashTable/_HashTable+CustomStringConvertible.swift external/Collections/Sources/OrderedCollections/HashTable/_HashTable+Testing.swift external/Collections/Sources/OrderedCollections/HashTable/_HashTable+UnsafeHandle.swift external/Collections/Sources/OrderedCollections/HashTable/_HashTable.swift external/Collections/Sources/OrderedCollections/HashTable/_Hashtable+Header.swift external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Codable.swift external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+CustomDebugStringConvertible.swift external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+CustomReflectable.swift external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+CustomStringConvertible.swift external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Deprecations.swift external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Elements+SubSequence.swift external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Elements.swift external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Equatable.swift external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+ExpressibleByDictionaryLiteral.swift external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Hashable.swift external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Initializers.swift external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Invariants.swift "external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Partial MutableCollection.swift" "external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Partial RangeReplaceableCollection.swift" external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Sequence.swift external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Values.swift external/Collections/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+Codable.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+CustomDebugStringConvertible.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+CustomReflectable.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+CustomStringConvertible.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+Diffing.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+Equatable.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+ExpressibleByArrayLiteral.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+Hashable.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+Initializers.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+Insertions.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+Invariants.swift "external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+Partial MutableCollection.swift" "external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+Partial RangeReplaceableCollection.swift" "external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+Partial SetAlgebra+Basics.swift" "external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+Partial SetAlgebra+Operations.swift" "external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+Partial SetAlgebra+Predicates.swift" external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+RandomAccessCollection.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+ReserveCapacity.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+SubSequence.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+Testing.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+UnorderedView.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet+UnstableInternals.swift external/Collections/Sources/OrderedCollections/OrderedSet/OrderedSet.swift external/Collections/Sources/OrderedCollections/Utilities/RandomAccessCollection+Offsets.swift external/Collections/Sources/OrderedCollections/Utilities/_UnsafeBitset.swift -supplementary-output-file-map /var/folders/4n/33t8hhln04s0cvfg31h8kqpm0000gp/T/TemporaryDirectory.Lj9WJD/supplementaryOutputs-1 -target arm64-apple-ios13.0 -Xllvm -aarch64-use-tbi -enable-objc-interop -stack-check -sdk /Applications/Xcode-13.2.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.2.sdk -I /Applications/Xcode-13.2.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/lib -I /__build_bazel_rules_swift/swiftmodules -F /Applications/Xcode-13.2.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Frameworks -F /Applications/Xcode-13.2.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.2.sdk/Developer/Library/Frameworks -assert-config Debug -g -module-cache-path /var/folders/4n/33t8hhln04s0cvfg31h8kqpm0000gp/T/swift_module_cache.cLDFaN -swift-version 5 -Osize -D NDEBUG -D BAZEL -debug-prefix-map /private/var/tmp/_bazel_KJKIM/9dbf82519b813fdab4f1790d456d1805/execroot/line_ios=. -debug-prefix-map /Applications/Xcode-13.2.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.2.sdk/usr/include/objc/.=/Applications/Xcode-13.2.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.2.sdk/usr/include/objc -new-driver-path /Applications/Xcode-13.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-driver -no-clang-module-breadcrumbs -no-serialize-debugging-options -vfsoverlaybazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections.vfsoverlay.yaml -color-diagnostics -resource-dir /Applications/Xcode-13.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift -Xcc -iquote. -Xcc -iquotebazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin -Xcc -Ibazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_private_hmap.hmap -Xcc -Ibazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_public_hmap.hmap -Xcc -Ibazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_private_angled_hmap.hmap -Xcc -I. -Xcc -iquote -Xcc bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_private_hmap.hmap -Xcc -Oz -Xcc -fno-unroll-loops -Xcc -fno-jump-tables -Xcc -Os -Xcc -DNDEBUG=1 -Xcc -Wno-unused-variable -Xcc -Winit-self -Xcc -Wno-extra -module-name OrderedCollections -target-sdk-version 15.2.0 -parse-as-library -num-threads 12 -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/HashTable/_HashTable+Bucket.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/HashTable/_HashTable+BucketIterator.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/HashTable/_HashTable+Constants.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/HashTable/_HashTable+CustomStringConvertible.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/HashTable/_HashTable+Testing.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/HashTable/_HashTable+UnsafeHandle.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/HashTable/_HashTable.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/HashTable/_Hashtable+Header.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Codable.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+CustomDebugStringConvertible.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+CustomReflectable.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+CustomStringConvertible.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Deprecations.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Elements+SubSequence.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Elements.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Equatable.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+ExpressibleByDictionaryLiteral.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Hashable.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Initializers.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Invariants.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Partial__SPACE__MutableCollection.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Partial__SPACE__RangeReplaceableCollection.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Sequence.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary+Values.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedDictionary/OrderedDictionary.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+Codable.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+CustomDebugStringConvertible.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+CustomReflectable.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+CustomStringConvertible.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+Diffing.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+Equatable.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+ExpressibleByArrayLiteral.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+Hashable.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+Initializers.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+Insertions.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+Invariants.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+Partial__SPACE__MutableCollection.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+Partial__SPACE__RangeReplaceableCollection.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+Partial__SPACE__SetAlgebra+Basics.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+Partial__SPACE__SetAlgebra+Operations.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+Partial__SPACE__SetAlgebra+Predicates.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+RandomAccessCollection.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+ReserveCapacity.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+SubSequence.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+Testing.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+UnorderedView.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet+UnstableInternals.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/OrderedSet/OrderedSet.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/Utilities/RandomAccessCollection+Offsets.swift.o -o bazel-out/ios-arm64-min13.0-applebin_ios-ios_arm64-opt-ST-dddd6af9e792/bin/external/Collections/OrderedCollections_objs/Sources/OrderedCollections/Utilities/_UnsafeBitset.swift.o
1.	Apple Swift version 5.5.2 (swiftlang-1300.0.47.5 clang-1300.0.29.30)
2.	
3.	While evaluating request ExecuteSILPipelineRequest(Run pipelines { PrepareOptimizationPasses, EarlyModulePasses, HighLevel,Function+EarlyLoopOpt, HighLevel,Module+StackPromote, Serialize, MidLevel,Function, ClosureSpecialize, LowLevel,Function, LateLoopOpt, SIL Debug Info Generator } on SIL for OrderedCollections.OrderedCollections)
4.	While running pass #382999 SILFunctionTransform "LICM" on SILFunction "@$ss30_copySequenceToContiguousArrayys0dE0Vy7ElementQzGxSTRzlF18OrderedCollections13_UnsafeBitsetV_Tgq5".
 for <<debugloc at "<compiler-generated>":0:0>>Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  swift-frontend           0x0000000114effc27 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 39
1  swift-frontend           0x0000000114efebb8 llvm::sys::RunSignalHandlers() + 248
2  swift-frontend           0x0000000114f00236 SignalHandler(int) + 278
3  libsystem_platform.dylib 0x00007fff20591d7d _sigtramp + 29
4  libsystem_platform.dylib 000000000000000000 _sigtramp + 18446603339973452448
5  swift-frontend           0x0000000110970f7c (anonymous namespace)::LICM::run() + 1020
6  swift-frontend           0x0000000110a37179 swift::SILPassManager::runFunctionPasses(unsigned int, unsigned int) + 4409
7  swift-frontend           0x0000000110a332eb swift::SILPassManager::executePassPipelinePlan(swift::SILPassPipelinePlan const&) + 155
8  swift-frontend           0x0000000110a4dbcc swift::SimpleRequest<swift::ExecuteSILPipelineRequest, std::__1::tuple<> (swift::SILPipelineExecutionDescriptor), (swift::RequestFlags)1>::evaluateRequest(swift::ExecuteSILPipelineRequest const&, swift::Evaluator&) + 60
9  swift-frontend           0x0000000110a3b9c5 llvm::Expected<swift::ExecuteSILPipelineRequest::OutputType> swift::Evaluator::getResultUncached<swift::ExecuteSILPipelineRequest>(swift::ExecuteSILPipelineRequest const&) + 469
10 swift-frontend           0x0000000110a3e108 swift::runSILOptimizationPasses(swift::SILModule&) + 392
11 swift-frontend           0x0000000110185004 swift::CompilerInstance::performSILProcessing(swift::SILModule*) + 1108
12 swift-frontend           0x000000011001c143 performCompileStepsPostSILGen(swift::CompilerInstance&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> >, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, swift::PrimarySpecificPaths const&, int&, swift::FrontendObserver*) + 1187
13 swift-frontend           0x000000011000e6d7 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 14743
14 swift-frontend           0x000000010ff4eb08 main + 1032
15 libdyld.dylib            0x00007fff20567f5d start + 1
16 libdyld.dylib            0x00000000000000ea start + 18446603339973624206

Surprisingly, swiftc frontend does not complain if I don't use -assert-config Debug flag. It seems like there's something wrong with _UsafeBitset.Word.next() and I tweaked it a little so that I could make it built even with -assert-config Debug flag:

diff --git a/Sources/OrderedCollections/Utilities/_UnsafeBitset.swift b/Sources/OrderedCollections/Utilities/_UnsafeBitset.swift
index 9470c61..56d41a5 100644
--- a/Sources/OrderedCollections/Utilities/_UnsafeBitset.swift
+++ b/Sources/OrderedCollections/Utilities/_UnsafeBitset.swift
@@ -268,12 +268,18 @@ extension _UnsafeBitset {
   @frozen
   internal struct Word {
     @usableFromInline
-    internal var value: UInt
+    internal var value: UInt {
+      didSet { _value = value }
+    }
+
+    @usableFromInline
+    internal var _value: UInt
 
     @inlinable
     @inline(__always)
     internal init(_ value: UInt) {
       self.value = value
+      self._value = value
     }
   }
 }
@@ -378,7 +384,7 @@ extension _UnsafeBitset.Word: Sequence, IteratorProtocol {
   @inlinable
   internal mutating func next() -> Int? {
     guard value != 0 else { return nil }
-    let bit = value.trailingZeroBitCount
+    let bit = _value.trailingZeroBitCount
     value &= value &- 1       // Clear lowest nonzero bit.
     return bit
   }

I don't know why my tweak works though.. 🤔

Expected behavior

OrderedCollections module could be built.

Actual behavior

OrderedCollections module could not be built.

OrderedDictionary API naming update: `modifyValue` → `updateValue`

The two OrderedDictionary.modifyValue(...) methods are useful dictionary API extensions, but it seems pointless to call them modifyValue instead of the pre-existing updateValue.

Deprecate the modifyValue declarations and replace them with functionally equivalent members called updateValue.

[Heap] Add combinatorial tests

Use CollectionsTestSupport to run exhaustive tests on the Heap implementation, by e.g. generating all permutations of values up to size 8, and seeing if a Heap initialized from each works correctly.

We should also use (deterministic) random sampling to check operations on larger heaps, and heaps that contain duplicate elements.

CocoaPods release

Hi.

Thanks for the good library!
Can it be released on CocoaPods too?
We are working on the library which needs OrderedMaps but it has to be published on CocoaPods too.

Thanks,
Yehor

OrderedSet.intersection crashes due to out of bounds index

If have two OrderedSets of what are essentially UUIDs (wrapped in Tagged). Finding the intersection from setA works.

setA.intersection(setB)

But taking the two, same, sets and flipping the order causes an out of bounds crash in RandomAccessCollection+Offsets.swift#28.

setB.intersection(setA)

The items in the sets are 1389 vs. 1388 if that could somehow matter.

Here's a stack trace if it helps:

#0	0x000000018f8d9a3c in _swift_runtime_on_report ()
#1	0x000000018f949530 in _swift_stdlib_reportFatalErrorInFile ()
#2	0x000000018f64b5d8 in closure #1 in closure #1 in closure #1 in _assertionFailure(_:_:file:line:flags:) ()
#3	0x000000018f64b37c in closure #1 in closure #1 in _assertionFailure(_:_:file:line:flags:) ()
#4	0x000000018f64ad2c in _assertionFailure(_:_:file:line:flags:) ()
#5	0x000000018f64aff0 in _fatalErrorMessage(_:_:file:line:flags:) ()
#6	0x000000018f848f8c in UnsafeBufferPointer.subscript.read ()
#7	0x000000018f848dfc in protocol witness for Collection.subscript.read in conformance UnsafeBufferPointer<τ_0_0> ()
#8	0x00000001046bf4c0 in RandomAccessCollection.subscript.getter at swift-collections/Sources/OrderedCollections/Utilities/RandomAccessCollection+Offsets.swift:28
#9	0x000000010467d904 in _HashTable.UnsafeHandle._find<τ_0_0>(_:in:) at swift-collections/Sources/OrderedCollections/HashTable/_HashTable+UnsafeHandle.swift:299
#10	0x00000001046bd5e4 in closure #1 in closure #1 in OrderedSet._find_inlined(_:) at swift-collections/Sources/OrderedCollections/OrderedSet/OrderedSet.swift:396
#11	0x00000001046bd648 in thunk for @callee_guaranteed (@unowned _HashTable.UnsafeHandle) -> (@unowned Int?, @unowned _HashTable.Bucket, @error @owned Error) ()
#12	0x00000001046bf154 in partial apply for thunk for @callee_guaranteed (@unowned _HashTable.UnsafeHandle) -> (@unowned Int?, @unowned _HashTable.Bucket, @error @owned Error) ()
#13	0x00000001046837d8 in closure #1 in _HashTable.read<τ_0_0>(_:) at swift-collections/Sources/OrderedCollections/HashTable/_HashTable.swift:151
#14	0x0000000104683ec0 in partial apply for closure #1 in _HashTable.read<τ_0_0>(_:) ()
#15	0x000000018f730e18 in ManagedBuffer.withUnsafeMutablePointers<τ_0_0>(_:) ()
#16	0x00000001046836fc in _HashTable.read<τ_0_0>(_:) at swift-collections/Sources/OrderedCollections/HashTable/_HashTable.swift:149
#17	0x00000001046bd454 in closure #1 in OrderedSet._find_inlined(_:) at swift-collections/Sources/OrderedCollections/OrderedSet/OrderedSet.swift:395
#18	0x00000001046bd6e0 in thunk for @callee_guaranteed (@unowned UnsafeBufferPointer<τ_0_0>) -> (@unowned Int?, @unowned _HashTable.Bucket, @error @owned Error) ()
#19	0x00000001046bebe8 in partial apply for thunk for @callee_guaranteed (@unowned UnsafeBufferPointer<τ_0_0>) -> (@unowned Int?, @unowned _HashTable.Bucket, @error @owned Error) ()
#20	0x000000018f62ef9c in ContiguousArray.withUnsafeBufferPointer<τ_0_0>(_:) ()
#21	0x00000001046bd180 in OrderedSet._find_inlined(_:) atswift-collections/Sources/OrderedCollections/OrderedSet/OrderedSet.swift:391
#22	0x00000001046ab544 in OrderedSet.contains(_:) at swift-collections/Sources/OrderedCollections/OrderedSet/OrderedSet+Partial SetAlgebra+Basics.swift:47
#23	0x00000001046abdb8 in OrderedSet.intersection(_:) at swift-collections/Sources/OrderedCollections/OrderedSet/OrderedSet+Partial SetAlgebra+Operations.swift:164

Information

  • Package version: version 0.0.7?
  • Platform version: iOS 15, iPhone 12 Pro simulator.
  • Swift version: I assume Swift 5.5 (Xcode 13 beta 5)

Checklist

  • If possible, I've reproduced the issue using the main branch of this package.
  • I've searched for existing GitHub issues.

Did not attempt to reproduce on main as swift-collections is a sub-dependency on one of my dependencies. But could absolutely try if requested. Getting late where I am 😅

Steps to Reproduce

I have not been able to reproduce this issue unfortunately. I'm doing this a on a few different pairs of sets, and only one of them with this specific type (Tagged<Product, UUID> — product being a custom struct) causes the issue. The other sets are also Tagged<X, UUID>.

Happy to attempt to provide more attempts to reproduce. The inner workings of all this is a bit over my head though.

Expected behavior

I expect the "call order" to not matter.

Actual behavior

Out of bounds crash.

Sparse Set

A Sparse Set is a specialized data structure for storing elements from a large amount of possible values (e.g. natural numbers) that are used very sparingly, optimized for iteration, addition and removal to the set.

Use cases are for example are components attached to an entity in an Entity-Component System (ECS), if you are dealing with arrays of indices, but it can also be used comparably to a binary search tree or hash map, ideally outperforming both of them.

The main advantages of a Sparse Set are its performance which can be
O(1) for it's primary actions (source spareset/lib.rs) and its low memory footprint.

Example Implementations:

Further Reading:

[Heap] Improve top level documentation

The current API docs on Heap provide useful information about its implementation details, but the docs don't explain what a heap is and why one would want to use it. We should add an introduction that is useful for a wider audience, moving the current documentation into an 'Implementation Details' section.

Something like this would be a good start:

A collection of comparable items arranged in a way that allows efficient access to its minimal and maximal elements.

Heaps can be used to efficiently provide sorted access to items that arrive incrementally and out of order. For example, a server application may use a heap to store its queue of incoming client transactions, processing them in order of decreasing priority.

Heaps provide highly optimized implementations for the following operations:

  • insert(_:): Inserts a new element in O(log(count)) time.
  • min()/max(): Retrieve (but does not remove) the minimum/maximum item in O(1) time.
  • removeMin()/removeMax(): Remove and return the minimum/maximum item in O(log(count)) time.

<Some toy sample code illustrating these operations>

Reversed implementation of CollectionTestCase.tearDown

Looking at this class:

open class CollectionTestCase: XCTestCase {
  internal var _context: TestContext?

  public var context: TestContext { _context! }

  public override func setUp() {
    super.setUp()
    _context = TestContext.pushNew()
  }

  public override func tearDown() {
    super.setUp()
    TestContext.pop(context)
    _context = nil
  }
}

The tearDown method looks more like a copy/paste of setUp than a break-down. Shouldn't it be:

public override func tearDown() {
  TestContext.pop(context)
  _context = nil
  super.tearDown()
}

I'm using snapshot a2bcac4.

Implement `SortedSet`, `SortedDictionary`

OrderedSet and OrderedDictionary work great when we need to keep their elements in the order they were inserted, or if we only need to infrequently reorder/sort them. However, inserting (or removing) an element from the middle of the collection takes linear time in both cases, which makes these generic types less suitable for maintaining a sorted collection. It would be very much desirable for Swift developers to have access to efficient sorted collection types.

Self-balancing search trees naturally keep their elements sorted, and they implement efficient (O(log(n))) insertions and removals from anywhere in the collection -- so they seem an ideal choice for the implementation of a standard suite of sorted collections.

Binary search trees and similar low-fanout search tree variants (such as AVL trees or red-black trees) need to maintain a multitude of internal references, so they come with an inappropriately large memory overhead. High fanout search trees such as in-memory B-trees organize their elements into a tree of small contiguous buffers (up to a couple thousand items or so), and this makes them far more efficient in practice -- in terms of both space and time.

Unlike collections that store their elements in a single, contiguous buffer, tree-based collections also allow different versions of the same tree to share some of their storage, by simply referring to the same nodes within the tree. This makes them potentially more efficient than the existing standard collection types when implementing the copy-on-write optimization. (In B-tree's case, we can maintain a nice balance between lookup and CoW performance by having the inner nodes of the tree have a lower maximum fanout number than leaves.)

We'd like this package to implement a great set of sorted collection types based on an in-memory B-tree implementation.

struct SortedSet<Element: Comparable>: BidirectionalCollection, SetAlgebra {....}
struct SortedDictionary<Key: Comparable, Value> { ... }

struct SortedBag<Element: Comparable> { ... }
struct SortedMultimap<Key: Comparable, Value> { ... }

Deque initialisation using array similar repeating and count parameter

Implement initialiser of Deque to allow initialisation of Deque elements like available for Array(repeating: 0.0, count: 10).
The repeating parameter shall be setable to any Double for a number of elements as defined in count parameter.

A possible use case is:
private var myTryOfCircularQueue: Deque<Double> = Deque(repeating: 0.0, count: 10)

instead of:

private var myTryOfCircularQueue: Deque<Double> = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]

[Heap] We should be able to run tests in optimized builds

Currently the Heap tests in ./Tests/PriorityQueueTests/HeapTests.swift are relying on @testable import to access internal interfaces. Unfortantely this doesn't work in release mode, so we can only run heap tests in debug builds.

We ought to be able to run these correctness tests with optimizations enabled. The way to do this is to replace direct use of internal interfaces with an __unstable view and/or @_spi(Testing) -- see e.g. how OrderedSet does this.

Inference issue with `OrderedDictionary.init(grouping:by:)`

Unlike Dictionary, OrderedDictionary's grouping initializer works with any Value that conforms to RangeReplaceableCollection, not just Array. Unfortunately, this makes type inference trickier:

import OrderedCollections

struct StatEvent: Equatable {
   var name: String
   var date: String
   var hours: Int
}

var statEvents = [
   StatEvent(name: "lunch", date: "01-01-2015", hours: 1),
   StatEvent(name: "dinner", date: "01-01-2015", hours: 1),
   StatEvent(name: "dinner", date: "01-01-2015", hours: 1),
   StatEvent(name: "lunch", date: "01-01-2015", hours: 1),
   StatEvent(name: "dinner", date: "01-01-2015", hours: 1)
]

// This works:
let dict = Dictionary(grouping: statEvents, by: { $0.name })

// But this doesn't:
let orderedDict = OrderedDictionary(grouping: statEvents, by: { $0.name })
// error: Generic parameter 'Value' could not be inferred

The workaround is to add an explicit type annotation, such as:

let orderedDict = OrderedDictionary<String, [StatEvent]>(grouping: statEvents, by: { $0.name })
// OK

This works, but it makes this initializer harder to use than Dictionary's.

Bi-directional multimap?

Recently I encountered an issue where I needed a data structure that provided an efficient way of storing multiple values per key and being able to query for all keys that had a value.

A one way multi-value map can be implemented using Dictionary<Key, Set<Value>> but to get the keys that match values requires maintaining another Dictionary<Value, Set<Key>>. It would be nice if Swift had an efficient Bidirectional Multimap.

Fatal error: unsupported: file Swift/ArrayBuffer.swift, line 231

When initializing a Deque from an Array (coming from NSArray), it crashes at runtime with error:

Fatal error: unsupported: file Swift/ArrayBuffer.swift, line 231

Information

  • Package version: commit 65a3841
  • Platform version: macOS 11.2.1 (20D74)
  • Swift version: Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)
    Target: x86_64-apple-darwin20.3.0

Checklist

  • If possible, I've reproduced the issue using the main branch of this package.
  • I've searched for existing GitHub issues.

Steps to Reproduce

Crashes at runtime (Deque+RangeReplaceableCollection.swift:144):

let array = NSArray(arrayLiteral: NSString()) as! [NSObject]
let deque = Deque(array)

Runs without crashing:

let array = NSArray(arrayLiteral: NSString()) as! [NSObject]
let deque = Deque(Array(array))

Expected behavior

The first example above doesn’t crash.

Actual behavior

Only the second example doesn’t crash.

Invalid Windows Paths

Some files here and in swift‐collections‐benchmark contain paths that are invalid on Windows. As a result, SwiftPM cannot build swift‐collections from Windows. (It can cross‐compile to Windows just fine.)

[...]
Resolving https://github.com/apple/swift-collections at 0.0.2
[...]\.build\checkouts\swift-collections: error: Couldn’t check out revision ‘2d719d75a2065f213e58a5164384a3d2fcf9b59a’:
    error: invalid path 'Documentation/Announcement-benchmarks/Results/01 Deque: random access lookups.png'
[...]
Resolving https://github.com/apple/swift-collections-benchmark at 0.0.1
[...]\.build\checkouts\swift-collections-benchmark: error: Couldn’t check out revision ‘49297647d1c0855eb33ec18cd6ee1181727c159b’:
    error: invalid path 'Documentation/Assets/sample-results/01 Deque: random access lookups.png'
Error: Process completed with exit code 1.

Information

  • Package version: 0.0.2
  • Platform version: Windows 10
  • Swift version: Swift 5.4.0

Checklist

  • If possible, I've reproduced the issue using the main branch of this package.
  • I've searched for existing GitHub issues.

Steps to Reproduce

Simply attempt to check out each relevant repository on Windows. (An empty Windows GitHub action can be created to trigger a checkout attempt without a local Windows machine.)

OrderedDictionary API inconsistency

As noted in #81 (comment), OrderedDictionary currently provides the an index(forKey:) method, while also providing a subscript operation with an offset label:

let index = countryCodes.index(forKey: "JP")!
print(countryCodes[offset: index].value)

We should use consistent terminology -- it's not nice that we call this thing index in one API, while offset the other. One option is to rename the subscript label index, but I believe it'd be better to simply deprecate both of these entry points -- they are easily replaced with corresponding view methods:

let index = countryCodes.keys.index(of: "JP")!
print(countryCodes.elements[index].value)

Circular Queue

Circular Queue is an extension of the Queue data structure in which the last item is connected with the first item or the first index comes right after the last index. We can consider it like a Ring Buffer.

Circular Queue definition

The same can be written in Swift as well using a Ring Buffer Extension.

The following code deals with Circular Queue:

`struct RingBufferQueue: CustomStringConvertible {

private var elements: [T?]
private var front = -1
private var rear = -1

init(count: Int) {
    elements = Array(repeating: nil, count: count)
}

var isEmpty: Bool {
    front == -1 && rear == -1
}

var isFull: Bool {
    ((rear + 1) % elements.count) == front
}

var description: String {
    if isEmpty { return "Queue is empty..." }
    return "---- Queue start ----\n"
        + elements.map({String(describing: "\($0)")}).joined(separator: " -> ")
        + "\n---- Queue End ----\n"
}

var peek: T? {
    if isEmpty { return nil }
    return elements[front]
}

}

extension RingBufferQueue {

// to enqueue an element
mutating func enqueue(_ element: T) -> Bool {
    
    // if queue is empty
    if front == -1 && rear == -1 {
        front = 0
        rear = 0
        elements[rear] = element
        return true
    }
    
    if isFull {
        print("QUEUE IS FULL")
        return false
    }
    
    rear = (rear + 1) % elements.count
    elements[rear] = element
    return true
}

}

extension RingBufferQueue {

// to dequeue an element
mutating func dequeue() -> T? {
    
    if isEmpty {
        print("QUEUE IS EMPTY")
        return nil
    }
    
    // if queue has only single element
    if front == rear {
        defer {
            elements[front] = nil
            front = -1
            rear = -1
        }
        return elements[front]
    }
    
    defer {
        elements[front] = nil
        front = (front + 1) % elements.count
    }
    return elements[front]
}

}
`

Note : Modifications can be made to the above code as it is generic in nature.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.