I have found a strange situation possible:
func foo(dict: inout [String: Any]) {
mergeDict(&dict, with: dict)
}
In general, this occurs when passing inout argument to another function with two arguments when one of them is also inout. This also includes all standard operators like +=, -=, *= ...
For now as I understand, compiler makes implicit copy. In Swift 5.9 borrowing / consuming modifiers can be used. Making borrowing and consuming conventions in func mergeDict explicit, seems that such situation should not be possible.
Should we improve compiler diagnostics to emit a warning in such cases and require an explicit copy of inout parameter?
1 Like
tera
2
What exactly do you find strange or wrong?
I believe that this fragment:
func mergeDict(_ dict: inout [String: Any], with other: [String: Any]) {
for (key, value) in other {
dict[key] = value
}
}
func foo(dict: inout [String: Any]) {
mergeDict(&dict, with: dict)
}
is 100% equivalent to this fragment:
func mergeDict(_ dict: inout [String: Any], with other: [String: Any]) {
var copy = dict
for (key, value) in other {
copy[key] = value
}
dict = copy
}
func foo(dict: inout [String: Any]) {
var copy = dict
mergeDict(©, with: dict)
dict = copy
}
1 Like
This is logically useless operation. I'm trying to understand can we add compiler diagnostics or will adding borrowing modifier prevent this, so:
func foo(dict: inout [String: Any]) {
mergeDict(&dict, with: dict) // warning or error
let explicitCopy = dict
mergeDict(&dict, with: explicitCopy) // ok
var explicitMutableCopy = dict
explicitMutableCopy[key] = value
mergeDict(&dict, with: explicitMutableCopy) // ok
mergeDict(&dict, with: [:])
}
tera
4
I see what you mean. So is this:
var x = 42
x |= x
Can you please what |= operator does in this situation?
tera
6
I mean it's a "no-op" operation compiler doesn't complaining about, same as here:
var x = 42
x = x | x
var y = true
y = y || y