Description
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.