Skip to content

SEGFAULT caused by type coercion of distinct types #14482

Open
@zah

Description

@zah

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions