mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Adds an explicit @escaping throughout the standard library, validation test suite, and tests. This will be necessary as soon as noescape is the default for closure parameters.
587 lines
19 KiB
Swift
587 lines
19 KiB
Swift
//===--- CheckCollectionInstance.swift.gyb --------------------*- swift -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
%{
|
|
from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
|
|
from gyb_stdlib_support import TRAVERSALS, collectionForTraversal
|
|
}%
|
|
|
|
import StdlibUnittest
|
|
|
|
public struct CollectionMisuseResiliencyChecks {
|
|
public enum FailureKind {
|
|
case none
|
|
case trap
|
|
}
|
|
|
|
public var creatingOutOfBoundsIndicesBehavior: FailureKind = .trap
|
|
public var subscriptOnOutOfBoundsIndicesBehavior: FailureKind = .trap
|
|
public var subscriptRangeOnOutOfBoundsRangesBehavior: FailureKind = .trap
|
|
|
|
public static var all: CollectionMisuseResiliencyChecks {
|
|
return CollectionMisuseResiliencyChecks()
|
|
}
|
|
|
|
public static var none: CollectionMisuseResiliencyChecks {
|
|
return CollectionMisuseResiliencyChecks(
|
|
creatingOutOfBoundsIndicesBehavior: .none,
|
|
subscriptOnOutOfBoundsIndicesBehavior: .none,
|
|
subscriptRangeOnOutOfBoundsRangesBehavior: .none)
|
|
}
|
|
}
|
|
|
|
% for inc, protocol, direction, end in (
|
|
% ('inc', 'Indexable', 'after', 'end'),
|
|
% ('dec', 'BidirectionalIndexable', 'before', 'start')):
|
|
|
|
/// Test that the elements of `instances` satisfy
|
|
/// ${'some of ' if inc == 'dec' else ''}the semantic
|
|
/// requirements of `${protocol}`, using `equalityOracle` to
|
|
/// generate equality expectations from pairs of positions in
|
|
/// `instances`.
|
|
///
|
|
/// - Precondition: ${'''`endIndex` is reachable from all
|
|
/// elements of `instances`.''' if inc == 'inc' else '''all
|
|
/// elements of `instances` are reachable from `startIndex`.'''}
|
|
public func check${inc.capitalize()}rementable<Instances, BaseCollection>(
|
|
_ instances: Instances,
|
|
of baseCollection: BaseCollection,
|
|
equalityOracle: (Instances.Index, Instances.Index) -> Bool,
|
|
${end}Index: Instances.Iterator.Element, ${TRACE}
|
|
) where
|
|
Instances : Collection,
|
|
BaseCollection : ${protocol},
|
|
Instances.Iterator.Element == BaseCollection.Index,
|
|
// FIXME(compiler limitation): these constraints should be applied to
|
|
// associated types of Collection.
|
|
Instances.Indices.Iterator.Element == Instances.Index {
|
|
|
|
checkEquatable(instances, oracle: equalityOracle, ${trace})
|
|
for i in instances {
|
|
if i != ${end}Index {
|
|
let next = baseCollection.index(${direction}: i)
|
|
// index(${direction}:) gets us a new index value
|
|
expectNotEqual(i, next, ${trace})
|
|
|
|
// Which is the same as if we apply formIndex(${direction}:)
|
|
var j = i
|
|
baseCollection.formIndex(${direction}: &j)
|
|
expectEqual(j, next, ${trace})
|
|
}
|
|
}
|
|
}
|
|
%end
|
|
|
|
internal func _checkIncrementalAdvance<Instances, BaseCollection>(
|
|
_ instances: Instances,
|
|
of baseCollection : BaseCollection,
|
|
equalityOracle: (Instances.Index, Instances.Index) -> Bool,
|
|
limit: Instances.Iterator.Element,
|
|
sign: BaseCollection.IndexDistance, // 1 or -1
|
|
next: (Instances.Iterator.Element) -> Instances.Iterator.Element,
|
|
${TRACE}
|
|
) where
|
|
Instances : Collection,
|
|
BaseCollection : Indexable,
|
|
Instances.Iterator.Element == BaseCollection.Index,
|
|
// FIXME(compiler limitation): these constraints should be applied to
|
|
// associated types of Collection.
|
|
Instances.Indices.Iterator.Element == Instances.Index {
|
|
for i in instances {
|
|
let d: BaseCollection.IndexDistance = sign > 0 ?
|
|
baseCollection.distance(from: i, to: limit) :
|
|
-baseCollection.distance(from: limit, to: i)
|
|
|
|
var offset: BaseCollection.IndexDistance = 0
|
|
for _ in 0...(d * sign).toIntMax() {
|
|
let j = baseCollection.index(i, offsetBy: offset)
|
|
let k = baseCollection.index(i, offsetBy: offset + sign, limitedBy: limit) ?? limit
|
|
let jAtLimit = offset == d
|
|
if jAtLimit {
|
|
expectEqual(limit, j, ${trace})
|
|
}
|
|
expectEqual(jAtLimit ? j : next(j), k, ${trace})
|
|
offset += sign
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Test that the elements of `instances` satisfy the semantic requirements of
|
|
/// index for `Collection`, using `equalityOracle` to generate equality
|
|
/// expectations from pairs of positions in `instances`.
|
|
///
|
|
/// - Precondition: `endIndex` is reachable from all elements of
|
|
/// `instances`
|
|
public func checkForwardIndex<Instances, BaseCollection>(
|
|
_ instances: Instances,
|
|
of baseCollection: BaseCollection,
|
|
equalityOracle: (Instances.Index, Instances.Index) -> Bool,
|
|
endIndex: Instances.Iterator.Element, ${TRACE}
|
|
) where
|
|
Instances : Collection,
|
|
BaseCollection : Indexable,
|
|
Instances.Iterator.Element == BaseCollection.Index,
|
|
// FIXME(compiler limitation): these constraints should be applied to
|
|
// associated types of Collection.
|
|
Instances.Indices.Iterator.Element == Instances.Index {
|
|
|
|
checkIncrementable(instances, of: baseCollection,
|
|
equalityOracle: equalityOracle, endIndex: endIndex, ${trace})
|
|
|
|
_checkIncrementalAdvance(instances, of: baseCollection,
|
|
equalityOracle: equalityOracle, limit: endIndex,
|
|
sign: 1, next: { baseCollection.index(after: $0) }, ${trace})
|
|
}
|
|
|
|
/// Test that the elements of `instances` satisfy the semantic requirements of
|
|
/// index for `BidirectionalCollection`, using `equalityOracle` to generate
|
|
/// equality expectations from pairs of positions in `instances`.
|
|
///
|
|
/// - Precondition:
|
|
/// - all elements of `instances` are reachable from `startIndex`.
|
|
/// - `endIndex` is reachable from all elements of `instances`.
|
|
public func checkBidirectionalIndex<Instances, BaseCollection>(
|
|
_ instances: Instances,
|
|
of baseCollection: BaseCollection,
|
|
equalityOracle: (Instances.Index, Instances.Index) -> Bool,
|
|
startIndex: Instances.Iterator.Element,
|
|
endIndex: Instances.Iterator.Element,
|
|
${TRACE}
|
|
) where
|
|
Instances: Collection,
|
|
BaseCollection : BidirectionalIndexable,
|
|
Instances.Iterator.Element == BaseCollection.Index,
|
|
// FIXME(compiler limitation): these constraints should be applied to
|
|
// associated types of Collection.
|
|
Instances.Indices.Iterator.Element == Instances.Index {
|
|
|
|
checkForwardIndex(instances, of: baseCollection,
|
|
equalityOracle: equalityOracle, endIndex: endIndex)
|
|
|
|
checkDecrementable(instances, of: baseCollection,
|
|
equalityOracle: equalityOracle, startIndex: startIndex, ${trace})
|
|
|
|
_checkIncrementalAdvance(instances, of: baseCollection,
|
|
equalityOracle: equalityOracle, limit: startIndex,
|
|
sign: -1, next: { baseCollection.index(before: $0) }, ${trace})
|
|
}
|
|
|
|
/// Test that the elements of `instances` satisfy the semantic requirements of
|
|
/// index for `RandomAccessCollection`, using `advanceOracle` and
|
|
/// 'distanceOracle' to generate expectations about the results of
|
|
/// `advanced(by:)` and `distance(to:)` from pairs of positions in `instances`
|
|
/// and `distances`.
|
|
///
|
|
/// - Precondition:
|
|
/// - all elements of `instances` are reachable from `startIndex`.
|
|
/// - `endIndex` is reachable from all elements of `instances`.
|
|
public func checkRandomAccessIndex<Instances, Distances, BaseCollection>(
|
|
_ instances: Instances, distances: Distances,
|
|
of baseCollection: BaseCollection,
|
|
distanceOracle:
|
|
(Instances.Index, Instances.Index) -> Distances.Iterator.Element,
|
|
advanceOracle:
|
|
(Instances.Index, Distances.Index) -> Instances.Iterator.Element,
|
|
startIndex: Instances.Iterator.Element,
|
|
endIndex: Instances.Iterator.Element,
|
|
${TRACE}
|
|
) where
|
|
Instances : Collection,
|
|
Distances : Collection,
|
|
BaseCollection : RandomAccessIndexable,
|
|
Instances.Iterator.Element == BaseCollection.Index,
|
|
Distances.Iterator.Element == BaseCollection.IndexDistance,
|
|
// FIXME(compiler limitation): these constraints should be applied to
|
|
// associated types of Collection.
|
|
Instances.Indices.Iterator.Element == Instances.Index,
|
|
Distances.Indices.Iterator.Element == Distances.Index {
|
|
|
|
checkBidirectionalIndex(instances, of: baseCollection,
|
|
equalityOracle: { distanceOracle($0, $1) == 0 },
|
|
startIndex: startIndex, endIndex: endIndex, ${trace})
|
|
|
|
checkAdvancesAndDistances(
|
|
instances, distances: distances,
|
|
of: baseCollection,
|
|
distanceOracle: distanceOracle,
|
|
advanceOracle: advanceOracle, ${trace})
|
|
}
|
|
|
|
// Copies what checkStrideable is doing, but instead of calling
|
|
// advanced(by:) and distance(to:) on an Strideable's,
|
|
// calls corresponding methods on a base collection.
|
|
public func checkAdvancesAndDistances<Instances, Distances, BaseCollection>(
|
|
_ instances: Instances, distances: Distances,
|
|
of baseCollection: BaseCollection,
|
|
distanceOracle:
|
|
(Instances.Index, Instances.Index) -> Distances.Iterator.Element,
|
|
advanceOracle:
|
|
(Instances.Index, Distances.Index) -> Instances.Iterator.Element,
|
|
${TRACE}
|
|
) where
|
|
Instances : Collection,
|
|
Distances : Collection,
|
|
BaseCollection : Indexable,
|
|
Instances.Iterator.Element == BaseCollection.Index,
|
|
Distances.Iterator.Element == BaseCollection.IndexDistance,
|
|
// FIXME(compiler limitation): these constraints should be applied to
|
|
// associated types of Collection.
|
|
Instances.Indices.Iterator.Element == Instances.Index,
|
|
Distances.Indices.Iterator.Element == Distances.Index {
|
|
|
|
checkComparable(
|
|
instances,
|
|
oracle: {
|
|
let d = distanceOracle($1, $0);
|
|
return d < 0 ? .lt : d == 0 ? .eq : .gt
|
|
},
|
|
${trace})
|
|
|
|
for i in instances.indices {
|
|
let x = instances[i]
|
|
expectEqual(x, baseCollection.index(x, offsetBy: 0))
|
|
|
|
for j in distances.indices {
|
|
let y = distances[j]
|
|
expectEqual(advanceOracle(i, j), baseCollection.index(x, offsetBy: y))
|
|
}
|
|
|
|
for j in instances.indices {
|
|
let y = instances[j]
|
|
expectEqual(distanceOracle(i, j), baseCollection.distance(from: x, to: y))
|
|
}
|
|
}
|
|
}
|
|
|
|
// Generate two overloads: one for Array (which will get
|
|
// picked up when the caller passes a literal), and another that
|
|
// accepts any appropriate Collection type.
|
|
% for genericParam, Element, Expected in [
|
|
% ('Expected: Collection', 'Expected.Iterator.Element', 'Expected'),
|
|
% ('Element' , 'Element' , 'Array<Element>')]:
|
|
|
|
% for Traversal in TRAVERSALS:
|
|
% TraversalCollection = collectionForTraversal(Traversal)
|
|
|
|
public func check${Traversal}Collection<
|
|
${genericParam}, C : ${TraversalCollection}
|
|
>(
|
|
_ expected: ${Expected}, _ collection: C,
|
|
${TRACE},
|
|
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
|
|
sameValue: (${Element}, ${Element}) -> Bool
|
|
) where
|
|
C.Iterator.Element == ${Element},
|
|
C.Indices.Iterator.Element == C.Index {
|
|
|
|
// A `Collection` is a multi-pass `Sequence`.
|
|
for _ in 0..<3 {
|
|
checkSequence(
|
|
expected, collection, ${trace},
|
|
resiliencyChecks: resiliencyChecks, sameValue: sameValue)
|
|
}
|
|
|
|
let succ = { collection.index(after: $0) }
|
|
% if Traversal != 'Forward':
|
|
let pred = { collection.index(before: $0) }
|
|
% end
|
|
// Advances up to 1 positions without passing endIndex. Don't use
|
|
// advanced(by: n) to do this because it's under test here.
|
|
let next = { $0 == collection.endIndex ? $0 : succ($0) }
|
|
|
|
// advances up to 5 positions without passing endIndex. Picking a
|
|
// small constant to avoid complexity explosion on large input
|
|
// collections.
|
|
let next5 = { next(next(next(next(next($0))))) }
|
|
|
|
let partWay0 = next5(collection.startIndex)
|
|
let partWay1 = next5(partWay0)
|
|
|
|
% if Traversal == 'Forward':
|
|
|
|
let instances = _allIndices(into: collection,
|
|
in: collection.startIndex..<partWay0)
|
|
checkForwardIndex(instances, of: collection,
|
|
equalityOracle: { $0 == $1 }, endIndex: partWay1, ${trace})
|
|
|
|
% elif Traversal == 'Bidirectional':
|
|
|
|
let instances = _allIndices(into: collection, in: partWay0..<partWay1)
|
|
checkBidirectionalIndex(instances, of: collection,
|
|
equalityOracle: { $0 == $1 },
|
|
startIndex: collection.startIndex,
|
|
endIndex: next5(partWay1), ${trace})
|
|
|
|
% else:
|
|
% assert(Traversal == 'RandomAccess')
|
|
typealias Distance = C.IndexDistance
|
|
|
|
let count: Distance = collection.count
|
|
let offset0 = min(5, count)
|
|
let offset1 = min(10, count)
|
|
let offset2 = min(15, count)
|
|
|
|
let distanceCandidates: [Distance] = [
|
|
-11, -7, -5, -3, -2, -1, 0, 1, 2, 3, 5, 7, 11]
|
|
|
|
let distances = distanceCandidates.filter { (x: Distance) -> Bool in
|
|
x + offset0 >= 0 && x + offset1 <= count
|
|
}
|
|
|
|
func nextN(_ n: Distance, _ i: C.Index) -> C.Index {
|
|
return collection.index(i, offsetBy: n)
|
|
}
|
|
|
|
let instances = _allIndices(into: collection, in: partWay0..<partWay1)
|
|
|
|
checkRandomAccessIndex(
|
|
instances,
|
|
distances: distances,
|
|
of: collection,
|
|
distanceOracle: { (x:Int, y:Int) in numericCast(y - x) },
|
|
advanceOracle: { x, y in nextN(distances[y], instances[x]) },
|
|
startIndex: collection.startIndex,
|
|
endIndex: next5(partWay1), ${trace})
|
|
|
|
% end
|
|
|
|
let expectedArray = Array(expected)
|
|
|
|
expectEqual(
|
|
expectedArray.count.toIntMax(), collection.count.toIntMax(), ${trace})
|
|
|
|
for _ in 0..<3 {
|
|
do {
|
|
let startIndex = collection.startIndex
|
|
let endIndex = collection.endIndex
|
|
|
|
for _ in collection.indices {
|
|
expectEqual(
|
|
startIndex, collection.startIndex,
|
|
"Iteration should not change startIndex",
|
|
stackTrace: ${stackTrace})
|
|
|
|
expectEqual(
|
|
endIndex, collection.endIndex,
|
|
"Iteration should not change endIndex",
|
|
stackTrace: ${stackTrace})
|
|
}
|
|
}
|
|
|
|
var allIndices = Array(collection.indices)
|
|
|
|
if expectedArray.count >= 2 {
|
|
for i in 0..<allIndices.count-1 {
|
|
let successor1 = succ(allIndices[i])
|
|
var successor2 = allIndices[i]
|
|
successor2 = succ(successor2)
|
|
var successor3 = allIndices[i]
|
|
successor3 = succ(successor3)
|
|
for s in [ successor1, successor2, successor3 ] {
|
|
expectEqual(allIndices[i + 1], s, ${trace})
|
|
expectEqualTest(
|
|
expectedArray[i + 1], collection[s], ${trace}, sameValue: sameValue)
|
|
}
|
|
}
|
|
|
|
% if Traversal == "Bidirectional":
|
|
|
|
for i in 1..<allIndices.count {
|
|
let predecessor1 = pred(allIndices[i])
|
|
var predecessor2 = allIndices[i]
|
|
predecessor2 = pred(predecessor2)
|
|
var predecessor3 = allIndices[i]
|
|
predecessor3 = pred(predecessor3)
|
|
for p in [ predecessor1, predecessor2, predecessor3 ] {
|
|
expectEqual(allIndices[i - 1], p, ${trace})
|
|
expectEqualTest(
|
|
expectedArray[i - 1], collection[p], ${trace}, sameValue: sameValue)
|
|
}
|
|
}
|
|
for i in 1..<allIndices.count {
|
|
let index = succ(pred(allIndices[i]))
|
|
expectEqual(allIndices[i], index, ${trace})
|
|
expectEqualTest(
|
|
expectedArray[i], collection[index], ${trace}, sameValue: sameValue)
|
|
}
|
|
|
|
% end
|
|
|
|
} // end of `if expectedArray.count >= 2`
|
|
|
|
do {
|
|
var allIndices2: [C.Index] = []
|
|
for i in collection.indices {
|
|
allIndices2.append(i)
|
|
}
|
|
|
|
expectEqualSequence(
|
|
allIndices, allIndices2, "iteration should not invalidate indices",
|
|
stackTrace: ${stackTrace})
|
|
|
|
expectEqualSequence(
|
|
expectedArray, allIndices.map { collection[$0] },
|
|
stackTrace: ${stackTrace}, sameValue: sameValue)
|
|
expectEqualSequence(
|
|
expectedArray, allIndices2.map { collection[$0] },
|
|
stackTrace: ${stackTrace}, sameValue: sameValue)
|
|
}
|
|
} // end of `for _ in 0..<3`
|
|
|
|
// FIXME: more checks for bidirectional and random access collections.
|
|
}
|
|
|
|
public func check${Traversal}Collection<
|
|
${genericParam}, C : ${TraversalCollection}
|
|
>(
|
|
_ expected: ${Expected}, _ collection: C,
|
|
${TRACE},
|
|
resiliencyChecks: CollectionMisuseResiliencyChecks = .all
|
|
) where
|
|
C.Iterator.Element == ${Element},
|
|
C.Indices.Iterator.Element == C.Index,
|
|
${Element} : Equatable {
|
|
|
|
check${Traversal}Collection(
|
|
expected, collection, ${trace},
|
|
resiliencyChecks: resiliencyChecks) { $0 == $1 }
|
|
}
|
|
|
|
% end
|
|
|
|
// FIXME: merge into checkCollection()
|
|
public func checkSliceableWithBidirectionalIndex<
|
|
${genericParam}, S : BidirectionalCollection
|
|
>(
|
|
_ expected: ${Expected}, _ sliceable: S, ${TRACE}
|
|
) where
|
|
S.Iterator.Element == ${Element},
|
|
S.Indices.Iterator.Element == S.Index,
|
|
S.SubSequence : BidirectionalCollection,
|
|
S.SubSequence.Iterator.Element == ${Element},
|
|
S.SubSequence.Indices.Iterator.Element == S.SubSequence.Index,
|
|
${Element} : Equatable {
|
|
|
|
// A `Sliceable` is a `Collection`.
|
|
checkBidirectionalCollection(expected, sliceable, ${trace})
|
|
|
|
let expectedArray = Array(expected)
|
|
|
|
let succ = { sliceable.index(after: $0) }
|
|
let pred = { sliceable.index(before: $0) }
|
|
|
|
var start = sliceable.startIndex
|
|
for startNumericIndex in 0...expectedArray.count {
|
|
if start != sliceable.endIndex {
|
|
start = succ(start)
|
|
start = pred(start)
|
|
start = succ(start)
|
|
start = pred(start)
|
|
}
|
|
var end = start
|
|
for endNumericIndex in startNumericIndex...expectedArray.count {
|
|
if end != sliceable.endIndex {
|
|
end = succ(end)
|
|
end = pred(end)
|
|
end = succ(end)
|
|
end = pred(end)
|
|
}
|
|
let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
|
|
let slice = sliceable[start..<end]
|
|
|
|
checkBidirectionalCollection(expectedSlice, slice, ${trace})
|
|
|
|
if end != sliceable.endIndex {
|
|
end = succ(end)
|
|
}
|
|
}
|
|
if start != sliceable.endIndex {
|
|
start = succ(start)
|
|
}
|
|
}
|
|
}
|
|
|
|
% end
|
|
|
|
|
|
public func checkRangeReplaceable<C, N>(
|
|
_ makeCollection: @escaping () -> C,
|
|
_ makeNewValues: (Int) -> N
|
|
) where
|
|
C : RangeReplaceableCollection,
|
|
N : Collection,
|
|
C.Iterator.Element : Equatable,
|
|
C.Iterator.Element == N.Iterator.Element,
|
|
C.Indices.Iterator.Element == C.Index {
|
|
|
|
typealias A = C
|
|
|
|
// First make an independent copy of the array that we can use for
|
|
// comparison later.
|
|
let source = Array<A.Iterator.Element>(makeCollection())
|
|
|
|
for (ix, i) in source.indices.enumerated() {
|
|
for (jx_, j) in (i..<source.endIndex).enumerated() {
|
|
let jx = jx_ + ix
|
|
|
|
let oldCount = jx - ix
|
|
for newCount in 0..<(2 * oldCount) {
|
|
let newValues = makeNewValues(newCount)
|
|
|
|
func reportFailure(_ a: inout A, _ message: String) {
|
|
print("\(message) when replacing indices \(ix)...\(jx)")
|
|
print(" in \(Array(source)) with \(Array(newValues))")
|
|
print(" yielding \(Array(a))")
|
|
print("====================================")
|
|
expectTrue(false)
|
|
}
|
|
|
|
var a = makeCollection()
|
|
|
|
a.replaceSubrange(nthIndex(a, ix)..<nthIndex(a, jx), with: newValues)
|
|
let growth = newCount - oldCount
|
|
|
|
let expectedCount = source.count + growth
|
|
let actualCount = numericCast(a.count) as Int
|
|
if actualCount != expectedCount {
|
|
reportFailure(
|
|
&a, "\(actualCount) != expected count \(expectedCount)")
|
|
}
|
|
|
|
for (kx, k) in a.indices.enumerated() {
|
|
let expectedValue = kx < ix ? nth(source, kx)
|
|
: kx < jx + growth ? nth(newValues, kx - ix)
|
|
: nth(source, kx - growth)
|
|
|
|
if a[k] != expectedValue {
|
|
reportFailure(
|
|
&a,
|
|
// FIXME: why do we need to break this string into two parts?
|
|
"a[\(kx)] = "
|
|
+ "\(a[k]) != expected value \(expectedValue)")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public func checkCollection<C : Collection, Expected : Collection>(
|
|
_ subject: C,
|
|
expected: Expected,
|
|
${TRACE},
|
|
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
|
|
sameValue: (Expected.Iterator.Element, Expected.Iterator.Element) -> Bool
|
|
) where C.Iterator.Element == Expected.Iterator.Element {
|
|
}
|
|
|