Search code examples
swiftsocketsdarwin

Cannot pass immutable value as inout argument: 'pointee' is a get-only property


This code from the Apple Docs gives me:

Cannot pass immutable value as inout argument: 'pointee' is a get-only property

import Foundation
import Darwin

extension sockaddr_storage {
    //...
    static func fromSockAddr<AddrType, ReturnType>(_ body: (_ sax: inout AddrType) throws -> ReturnType) rethrows -> (ReturnType, sockaddr_storage) {
        precondition(MemoryLayout<AddrType>.size <= MemoryLayout<sockaddr_storage>.size)
        // We need a mutable `sockaddr_storage` so that we can pass it to `withUnsafePointer(to:_:)`.
        var ss = sockaddr_storage()
        let result = try withUnsafePointer(to: &ss) {
            try $0.withMemoryRebound(to: AddrType.self, capacity: 1) {
                // Error: Cannot pass immutable value as inout argument: 'pointee' is a get-only property
                try body(&$0.pointee)
            }
        }
        return (result, ss)
    }
}

I can not find a way to make it compile.


Solution

  • You just need to change withUnsafePointer to withUnsafeMutablePointer.

    This works because withMemoryRebound now passes in an UnsafeMutablePointer<T> rather than UnsafePointer<T>, so you can mutate the pointee.

    Code:

    extension sockaddr_storage {
        //...
        static func fromSockAddr<AddrType, ReturnType>(_ body: (_ sax: inout AddrType) throws -> ReturnType) rethrows -> (ReturnType, sockaddr_storage) {
            precondition(MemoryLayout<AddrType>.size <= MemoryLayout<sockaddr_storage>.size)
            var ss = sockaddr_storage()
            let result = try withUnsafeMutablePointer(to: &ss) {
                try $0.withMemoryRebound(to: AddrType.self, capacity: 1) {
                    try body(&$0.pointee)
                }
            }
            return (result, ss)
        }
    }