Nim icon indicating copy to clipboard operation
Nim copied to clipboard

fixes #25116; default(T) breaks requiresInit requirements

Open ringabout opened this issue 3 months ago • 5 comments

fixes #25116

ringabout avatar Sep 09 '25 14:09 ringabout

It's really annoying for range types though, I would expect tons of misusages of ranges

let z: seq[range['a'..'z']] = @['c']

Otherwise stdlibs need a requireInit typetraits for using zeroDefault for types requiring explicit initialization

ringabout avatar Sep 09 '25 15:09 ringabout

The stdlib should use more zeroDefault then, why would it need yet another trait.

Araq avatar Sep 11 '25 07:09 Araq

proc arrayWithDefault*[T](size: static int): array[size, T] {.noinit, nodestroy, raises: [].} =
  ## Creates a new array filled with `default(T)`.
  for i in 0..size-1:
    result[i] = default(T)


proc setLen[T](s: var seq[T], newlen: Natural) {.nodestroy.} =
  ...
  for i in oldLen..<newlen:
    xu.p.data[i] = default(T)

arrayWithDefault and setLen need default to set default values for objects with default value fields or ranges types

ringabout avatar Sep 11 '25 12:09 ringabout

zeroDefault

the only valid use of zeroDefault is when the location is not observable from the public api of the type - ie a table could in theory use it for its storage, for memory slots that are not yet in use - but that begs the question: if it's not observable, why would you want to zero it in the first place? it's better to leave it uninitialized in that case since zeroing costs (a lot) of CPU.

It also brings into light the bytes-to-type edge where a zeroDefault-initialized instance is in fact not a valid instance of the type and therefore should not be treated as such - in particular, it should be treated as bytes meaning that its memory should also not see destructors run on it etc - consider:

type MyType = object
  v: range[2..3]

proc `=destroy`(v: var MyType) =
  assert v in 2..3

This is a general problem with building collections in Nim in a world with semi-deterministic destructors - the naive approach of trying to ignore the bytes-to-type edge that was introduced in ORC has downstream effects on the soundness of other features - this is also why a correct Table implementation likely would be better of using a seq[byte] for its underlying storage - a statement that holds for any custom collection really.

arnetheduck avatar Sep 12 '25 07:09 arnetheduck

It seems that It can make do by making the low bound value the default value of range types, e.g., simple range types only, like default(range[3..4])

The annoying cases are notnil and views types. Probably not touch them in this PR, e.g.

{.experimental: "views".}

proc split*(s: string, seps: set[char] = Whitespace,
                maxsplit: int = -1): seq[openArray[char]] =

ringabout avatar Sep 15 '25 13:09 ringabout