Skip to content

Option causes a crash on distinct ref types #9566

Open
@PMunch

Description

@PMunch

Noticed a very strange bug with options and distinct types (not that I think the source of the issue is related to either). The supplied example throws an error unless -d:passTest is passed when compiling. The error comes from the C compiler which complains that a struct doesn't have the field has. The options module tries to optimise options of ref | ptr | pointer to just be a nil check instead of having a separate has field. Nim appears to not see the distinct JsonNode as a ref type, but it is able to see that Option[TestType] should be the same as a Option[JsonNode]. This means that if somelongname (named to be easy to search for in the C source) is defined before anotherlongname then the resulting Option struct doesn't have a has field as JsonNode is a ref type. But if the order is different, or if somelongname is not defined at all, then the resulting Option struct has the field as it doesn't see TestType as a ref.

Example

import json
import options

type TestType = distinct JsonNode

when not defined(passTest):
  var somelongname: Option[JsonNode]

var anotherlongname: Option[TestType]

if anotherlongname.isNone:
  echo "as expected"

Current Output

Without -d:passTest

Error: execution of an external compiler program 'gcc -c  -w  -I/home/peter/.choosenim/toolchains/nim-0.19.0/lib -o /home/peter/.cache/nim/jsopttest_d/jsopttest.c.o /home/peter/.cache/nim/jsopttest_d/jsopttest.c' failed with exit code: 1

/home/peter/.cache/nim/jsopttest_d/jsopttest.c: In function ‘isNone_bL5Zl5L69br9bckzAxrvAwMwjsopttest’:
/home/peter/.cache/nim/jsopttest_d/jsopttest.c:157:17: error: ‘tyObject_Option_Cgz4GLZ9bQIhJokNqwA3eBQ’ {aka ‘struct tyObject_Option_Cgz4GLZ9bQIhJokNqwA3eBQ’} has no member named ‘has’
  result = !(self.has);
                 ^

With -d:passTest

Hint: operation successful (26061 lines compiled; 1.025 sec total; 38.906MiB peakmem; Debug Build) [SuccessX]

Additional Information

I ran into this when trying to use my jsonschema library to create nimlsp, and managed to condense the error down to this.

EDIT: Found smaller example and probable root cause (updated example above).
EDIT2:
After some more testing I found out that this is the issue:

type
  MyRefType = ref object
    discard
  TestType = distinct MyRefType

when TestType is ref:
  echo "TestType is ref"

when MyRefType is ref:
  echo "MyRefType is ref"

This will output "MyRefType is ref", but not "TestType is ref". But Nim is still able to see that these are the same type, meaning that things like the option will be reused, but the two types will behave differently.

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