nim-lang / Nim

Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula. Its design focuses on efficiency, expressiveness, and elegance (in that order of priority).
https://nim-lang.org
Other
16.55k stars 1.47k forks source link

3 bugs with set + range: codegen error, accepts invalid, internal error #17848

Closed timotheecour closed 1 month ago

timotheecour commented 3 years ago

Example

when true or defined(case1):
  # generate with:
  # var a = ""
  # for i in 0..<80: a.add "k" & $i & ", "
  # echo a
  type
    TMsgKind* = enum
      k0, k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k40, k41, k42, k43, k44, k45, k46, k47, k48, k49, k50, k51, k52, k53, k54, k55, k56, k57, k58, k59, k60, k61, k62, k63, k64, k65, k66, k67, k68, k69, k70, k71, k72, k73, k74, k75, k76, k77, k78, k79
  type
    TNoteKind* = range[k10..k79]
    Conf = ref object
      notes*: set[TNoteKind]
  proc bad(conf: Conf, noteSet: set[TMsgKind]) =
    conf.notes = noteSet
  var conf = Conf()
  bad(conf, {k10..k60})

when defined case2:
  type
    TMsgKind = enum k0, k1, k2, k3
    TNoteKind = range[k1..k2]
    TNoteKinds = set[TNoteKind]
  type Conf = ref object
    notes: TNoteKinds
  proc fn(conf: Conf, b: set[TMsgKind]) =
    conf.notes = b
  var conf = Conf()
  conf.fn({k0..k3}) # BUG: this should give error
  echo conf.notes # {k1, k2}

when defined case3:
  #[
  compiler/bitsets.nim(43, 9) `elem >= 0`  [AssertionDefect]
  ]#
  type
    TMsgKind = enum k0, k1, k2, k3
    TNoteKind* = range[k1..k2]
  var notes: set[TNoteKind]
  notes = {k0..k3}

Current Output with -d:case1

nim c -d:case1 main

/@mt12210.nim.c:347:53: error: used type 'tySet_tyEnum_TMsgKind__NjW55fVRoByWL2dh9aGzvHw' (aka 'NU8 [9]') where arithmetic or pointer
      type is required
        nimCopyMem((void*)(*conf).notes, (NIM_CONST void*)((tySet_tyEnum_TMsgKind__NjW55fVRoByWL2dh9aGzvHw) (noteSet)), 9);

this only occurs with large enough number of elements. I've reduced it (painfully) from a bug i found while working on compiler.

Current Output with -d:case2

nim r -d:case2 main prints {k1, k2} but conf.fn({k0..k3}) should give an error

Current Output with -d:case3

nim c -d:case3 main compiler gives an internal error: compiler/bitsets.nim(43, 9) elem >= 0 [AssertionDefect]

Additional Information

1.5.1 22e06ee95aeb32929a5b912096dfaa662165c162 these bugs are potentially related, hence grouped in 1 issue.

beef331 commented 3 years ago

Seems case 1 and case 2 are both now proper, probably should get regression tests, 3 still needs addressed.