Skip to content

[SR-12442] cannot use withUnsafeMutablePointer to pass mutable pointer to base address of array #54881

@swift-ci

Description

@swift-ci
Previous ID SR-12442
Radar rdar://problem/62201022
Original Reporter dastrobu (JIRA User)
Type Bug
Additional Detail from JIRA
Votes 0
Component/s
Labels Bug
Assignee None
Priority Medium

md5: 73ad1fc070c40847e0a03524ea70c15b

Issue Description:

I cannot use withUnsafeMutablePointer as expected as illustrated by the following example:

Consider there is a C function taking a pointer equivalent to the following swift function

func some_c_function(_ a: UnsafeMutablePointer<UInt8>){
    print(a[0])
}

Then one can call this function in Swift in the following (unsafe) way

func f(){
    var a: [UInt8] = [42]
    let p = UnsafeMutablePointer(&a)
    some_c_function(p)
}

This yields the compiler warning

warning: initialization of 'UnsafeMutablePointer<UInt8>' results in a dangling pointer

Which is correct. So one would expect to be able to change this code to a safe call in the following way.

withUnsafeMutablePointer(to: &a) { p in
        some_c_function(p)
    }

However, this yields a compilation error:

Cannot convert value of type 'UnsafeMutablePointer<[UInt8]>' to expected argument type 'UnsafeMutablePointer<UInt8>'

Specifying the argument type explicitly gives a far less descriptive compilation error.

withUnsafeMutablePointer(to: &a) { (p: UnsafeMutablePointer<UInt8>) in
        some_c_function(p)
    }

Cannot convert value of type '()' to closure result type '_'

Specifying the return type as well gives a different but also not very helpful error

withUnsafeMutablePointer(to: &a) { (p: UnsafeMutablePointer<UInt8>) -> () in
        some_c_function(p)
    }

error: declared closure result '()' is incompatible with contextual type '_'

Xcode suggests a fix

Replace '()' with '_'

resulting in

withUnsafeMutablePointer(to: &a) { (p: UnsafeMutablePointer<UInt8>) -> _ in
        some_c_function(p)
    }

error: expected expression

In the end, the only safe and warning free code (I found) is

    a.withUnsafeMutableBufferPointer { p in
        some_c_function(p.baseAddress!)
    }

Since the automatic conversion from `&a` to `UnsafeMutablePointer<UInt8>` works with

let p = UnsafeMutablePointer(&a)

I would expect that it also works with

withUnsafeMutablePointer(to: &a) { p in ...

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions