The string definition is actually located in system.nim , just under a different name:
type TGenericSeq {.compilerproc, pure, inheritable.} = object len, reserved: int PGenericSeq {.exportc.} = ptr TGenericSeq UncheckedCharArray {.unchecked.} = array[0..ArrayDummySize, char]
Thus, the string is a raw pointer to an object with the fields len , reserved and data . Processes for strings are defined in sysstr.nim .
The semantics of the string assignments were chosen the same way as for all value types (not ref or ptr) in Nim by default, so you can assume that the assignments create a copy. When a copy is not needed, the compiler can leave it, but I'm not sure how much this happens. Passing strings to proc does not copy them. There is no optimization that prevents lines from being copied until they are mutated. Sequences behave identically.
You can change the default behavior for the default rows and sections by marking them as shallow, then copying is not performed on assignment:
var s = "foo" shallow s
def-
source share