The rules for conversion from arguments to pointers are somewhat inconsistent today. var
s may be directly passed as arguments to functions taking UnsafePointer<T>
or UnsafeMutablePointer<T>
arguments by taking the var
inout
. However, no such capacity is provided for let
s unless that let
is an array, in which case an array-to-pointer conversion takes place provided the argument is an UnsafePointer
.
The current solution to this is to make an intermediate copy for any let
variable:
func someFunction(arg: UInt32) {
var arg = arg
someOtherFunction(argByReference: &arg)
}
func someOtherFunction(argByReference: UnsafePointer<UInt32>) {
print(argByReference.pointee)
}
This can be fairly clunky, particular when dealing with C APIs that take arguments as const
pointers or that use pass-by-reference everywhere.
With the introduction of withUnsafePointer<T>(to: T)
, let
-bound variables can be converted to UnsafePointer
s without creation of temporaries. To avoid a copy (for larger values), the above could be written as:
func someFunction(arg: UInt32) {
withUnsafePointer(to: arg) { arg in
someOtherFunction(argByReference: arg)
}
}
I suggest extending the language to implicitly convert from let
variables to UnsafePointer
arguments, with behaviour equivalent to withUnsafePointer<T>(to: T)
in the same way that inout
-to-pointer maps to withUnsafeMutablePointer<T>(to: inout T)
. With this conversion in place, the above code could be written simply as:
func someFunction(arg: UInt32) {
someOtherFunction(argByReference: arg)
}
One alternative would be to still require the call to pass the argument with &
. However, I think that would potentially be more confusing, since in Swift &
means "take this variable inout
".
Reasons not to do this might be if it impacts type-checker performance in a meaningful way or if it makes code using it significantly more difficult to reason about. In general, though, I don't think it should matter to the caller whether the callee takes its arguments by value or by reference; what the caller cares about is only whether the argument may be modified at the end of the call.