I'm semi-hiding the implementation element storage collection around another collection that has a non-MutableCollection interface.
public struct Heap<Base: Collection> {
public typealias Element = Base.Element
public /*private(set)*/ var raw: Raw
//...
}
extension Heap {
/// A wrapping collection that strips any mutable operations.
///
/// - Note: Also strips away laziness.
public struct Raw {
/// The wrapped collection.
@usableFromInline internal fileprivate(set) var base: Base
/// Creates a wrapper around the given collection.
@usableFromInline init(_ base: Base) { self.base = base }
}
}
extension Heap.Raw: Equatable where Base: Equatable {}
extension Heap.Raw: Hashable where Base: Hashable {}
// Extensions that implement pass-through conformance to Sequence and Collection.
// Extensions that implement pass-through conformance to BidirectionalCollection and RandomAccessCollection conditionally.
The problems came when trying to implement this method:
extension Heap where Base: MutableCollection, Base: RandomAccessCollection {
@discardableResult
public func replacePeak(with element: Element) -> Raw.Index? {
precondition(!isEmpty)
//raw.base[raw.base.startIndex] = element
var xxx = raw
xxx.base[raw.base.startIndex] = element
return nil // full implementation later....
}
}
I originally had two problems with the assignment. The first one was caused by the base property being set to internal private(set). I expected that to happen, and changing the mutation access to fileprivate fixed it.
The other one is more persistent. If you change the second "xxx" back to "raw," I get: "Cannot assign through subscript: subscript is get-only" highlighted on the "raw" inside the square brackets. As above, .raw is mutable from the Heap instance's perspective, so why can't I mutate a mutable sub-property? (Remember that raw itself deliberately doesn't conform to MutableCollection nor RangeReplaceableCollection.)
Did I find another bug?