Skip to content

Conversation

vanvoorden
Copy link
Contributor

@vanvoorden vanvoorden commented Jun 23, 2025

Background

SE-0494

We propose new isTriviallyIdentical(to:) instance methods to the following concrete types for determining in constant-time if two instances must be equal by-value:

  • String
  • Substring
  • Array
  • ArraySlice
  • ContiguousArray
  • Dictionary
  • Set

Instead of “one big diff”… we can try and keep the diffs grouped together by similar functionality:

  • String, Substring
  • Array, ArraySlice, ContiguousArray
  • Dictionary, Set

Changes

Our Dictionary does not directly perform a fast path for equality checking in our == operator.1 We can actually steal an idea from Dictionary.Keys.2 If both variants are native, we compare the storage buffer directly. If both variants are Cocoa, we compare the objects directly.

extension Dictionary { @_alwaysEmitIntoClient public func isIdentical(to other: Self) -> Bool { #if _runtime(_ObjC) if self._variant.isNative, other._variant.isNative, unsafe (self._variant.asNative._storage === other._variant.asNative._storage) { return true } if !self._variant.isNative, !other._variant.isNative, self._variant.asCocoa.object === other._variant.asCocoa.object { return true } #else if unsafe (self._variant.asNative._storage === other._variant.asNative._storage) { return true } #endif return false } }

Our Set performs a similar check over variants for our == operator.3 We can check identity similar to Dictionary:

extension Set { @_alwaysEmitIntoClient public func isIdentical(to other: Self) -> Bool { #if _runtime(_ObjC) if self._variant.isNative, other._variant.isNative, unsafe (self._variant.asNative._storage === other._variant.asNative._storage) { return true } if !self._variant.isNative, !other._variant.isNative, self._variant.asCocoa.object === other._variant.asCocoa.object { return true } #else if unsafe (self._variant.asNative._storage === other._variant.asNative._storage) { return true } #endif return false } }

Test Plan

New tests were added for Dictionary and Set.

Benchmarks

New benchmarks were added for Dictionary and Set.

Footnotes

  1. https://github.com/swiftlang/swift/blob/swift-6.1.2-RELEASE/stdlib/public/core/Dictionary.swift#L1583-L1598

  2. https://github.com/swiftlang/swift/blob/swift-6.1.2-RELEASE/stdlib/public/core/Dictionary.swift#L1365-L1384

  3. https://github.com/swiftlang/swift/blob/swift-6.1.2-RELEASE/stdlib/public/core/Set.swift#L408-L424

@glessard
Copy link
Contributor

@swift-ci please Apple silicon benchmark

@vanvoorden vanvoorden force-pushed the dictionary-identical branch 2 times, most recently from adbdeb8 to e73320c Compare August 26, 2025 01:03
@vanvoorden vanvoorden changed the title [StdLib][RFC][DNM] Add isIdentical Methods for Quick Comparisons to Dictionary and Set [SE-0494][StdLib] Add isTriviallyIdentical(to:) Methods for Quick Comparisons to Dictionary and Set Oct 16, 2025
@vanvoorden vanvoorden force-pushed the dictionary-identical branch from 390f0c7 to 20061b0 Compare October 16, 2025 23:29
/// considered identical.
///
/// - Performance: O(1)
@_alwaysEmitIntoClient
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lorentey Opaque here?

Copy link
Member

Choose a reason for hiding this comment

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

This type is generic, so sadly the answer is no -- we need this to be at least @inlinable. @_aeic is fine.

@vanvoorden
Copy link
Contributor Author

@swift-ci please Apple silicon benchmark

@vanvoorden
Copy link
Contributor Author

@swift-ci Please smoke test

@vanvoorden vanvoorden changed the title [SE-0494][StdLib] Add isTriviallyIdentical(to:) Methods for Quick Comparisons to Dictionary and Set [SE-0494][StdLib] Add isTriviallyIdentical(to:) Methods to Dictionary and Set Oct 20, 2025
@vanvoorden
Copy link
Contributor Author

@swift-ci Please smoke test Windows platform

@vanvoorden
Copy link
Contributor Author

@swift-ci Please smoke test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants