Open
Description
Consider the following program:
type
Bytes = seq[byte]
RedBytes = distinct Bytes
GreenBytes[T] = distinct Bytes
proc worksWithGreenBytes[T](data: var GreenBytes[T]) =
Bytes(data)[0] = byte(0)
proc worksWithRedBytes(data: var RedBytes) =
# Attempt one, let's tell Nim that our red bytes can
# be used as green bytes in this special case:
when false:
worksWithGreenBytes GreenBytes[int](data)
# Fails with:
# /home/zahary/nim/scratch/wrong_coercion.nim(12, 22) Error: type mismatch: got <GreenBytes[system.int]>
# but expected one of:
# proc worksWithGreenBytes[T](data: var GreenBytes[T])
# first type mismatch at position: 1
# required type for data: var GreenBytes[worksWithGreenBytes.T]
# but expression 'GreenBytes[int](data)' is immutable, not 'var'
# Aha! Let's fix that in a clever way:
type GreenBytesVar = var GreenBytes[int]
worksWithGreenBytes GreenBytesVar(data)
# The program now compiles, but segfaults:
# SIGSEGV: Illegal storage access. (Attempt to read from nil?)
var x = RedBytes @[1.byte, 2, 3]
worksWithRedBytes x
The when false
statement demonstrates a coercion error that happens only when the GreenBytes
distinct type is also a generic type.
The alternative way to force the coercion tricks the compiler into generating the following invalid code:
N_LIB_PRIVATE N_NIMCALL(void, worksWithGreenBytes__gm84k5EAEXjiXAGaLs4PxA)(tySequence__6H5Oh5UUvVCLiakt9aTwtUQ** data) {
if ((NU)(((NI) 0)) >= (NU)((*data) ? (*data)->Sup.len : 0)){ raiseIndexError2(((NI) 0),((*data) ? (*data)->Sup.len : 0)-1); }
(*data)->data[((NI) 0)] = ((NU8) 0);
}
N_LIB_PRIVATE N_NIMCALL(void, worksWithRedBytes__PvYV6DaJwxv9bcad9bhlyHYw)(tySequence__6H5Oh5UUvVCLiakt9aTwtUQ** data) {
worksWithGreenBytes__gm84k5EAEXjiXAGaLs4PxA((*data));
}
Notice how data
is dereferenced unnecessarily which leads to a segfault. It should be noted that the code works correctly in C++ mode, where the compiler uses reference types.
Nim Compiler Version 1.3.5 [Linux: amd64]
Compiled at 2020-05-28
Copyright (c) 2006-2020 by Andreas Rumpf
git hash: fe7a2d60f90ac48b296b637401da2724dd160954
active boot switches: -d:release