Is this loss of transitive mutability another bug?

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?

Your example is missing mutating on the constrained extension method; was that just a typo?

That was it. Thank you.

Too bad the compiler couldn't suggest making the method mutating. This is yet another thing the compiler can pre-check with methods spelled with letters but miss with a subscript operator.

1 Like
Terms of Service

Privacy Policy

Cookie Policy