V: Don't disallow mut primitive arguments; invalidation

Created on 25 Jul 2019  路  6Comments  路  Source: vlang/v

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).

Discussion Type System

All 6 comments

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:

  1. Others can suggest improvements and find problems with it.
  2. Everyone will see that it will actually work well, instead of having to believe you.

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

Was this page helpful?
0 / 5 - 0 ratings