In #1131 and in the upcoming changelog for 0.1.17, passing a mutable argument of primitive type is no longer allowed.
Iterator invalidation (not related to custom/generic iterators) is a memory safety issue:
fn set_elem(mut arr []int, i int){
arr[i] = 5
*arr = [] // unexpected by caller
}
mut a := [1, 2] // original data
for i, _ in a {
set_elem(mut a, i)
}
Whilst a is being iterated with for, the original data will be freed (e.g. if using reference counting) when the *arr = [] call means the original data is apparently no longer referenced.
This can be fixed by adding a reference count increment while the for loop is active. But it doesn't solve the problem of the caller not realising that arr is reassigned to.
Instead, the compiler should allow:
fn set_int(mut e int) {
e = 5 // or whatever
}
mut a := [1, 2] // original data
for i, _ in a {
set_int(mut a[i])
}
This is much easier to reason about for the caller, and can prevent memory safety issues (in unsafe code at least).
This also highlights a problem I raised a while ago in the forum: does mut apply to the variable (the reference) or the value. Now it seems to sometimes apply to both, other times just the variable. In C/C++ we have int * and const int * and int const * and const int const * and they mean different things.
In the example above, why is arr mutable at all? It is only arr[x] we want mutable. The intent is that the elements of the array are mutable, perhaps fun set_elem(arr mut []int, i int)
Thanks @ntrel
This is work in progress. It will all work well in the end.
unsafe code will allow anything, by the way. Including modifying primitives.
@dcurrie your syntax (fun set_elem(arr mut []int, i int))) is the correct one. mut arr []int is invalid.
I remember your concern regarding mut. It will be taken care of.
It will all work well in the end.
Why not share the solution then? Sharing the solution has all the advantages:
If you don't have a solution yet, then you can't honestly say it will work well in the end. You can't know.
unsafe code will allow anything, by the way. Including modifying primitives
It should work in safe code, it's a basic use of mutability.
does mut apply to the variable (the reference) or the value
That is a separate issue, one I filed before the 0.1 release.
does mut apply to the variable (the reference) or the value
That is a separate issue, one I filed before the 0.1 release.
I believe @ntrel is referring to pointers and arrays can violate immutability #41