Skip to content

New Style Concept Matches When It Should Not #21250

Open
@c-blake

Description

@c-blake

Description

Define a module lpt.nim (idea being a generic hash table with user types):

type
  LPs*[K,V] = concept
    proc key(c: Self, i: int): K        # Cell ops, i-th various
    proc val(c: Self, i: int): V        # Cell ops, i-th various
  Void* = distinct int
  Voids* = Void|distinct char

proc incl*[K,V: Voids](s: var LPs[K,V], key: K) =
  when V is not Voids: echo "whoa" # runs yet call matched!?
  echo "did incl"

iterator pairs*[K,V:not Voids](s: LPs[K,V]): (K, V) =
  var k: K; var v: V
  for i in 1..3: yield (k, v)

Now a client module, kv.nim that accesses the not Voids branch of the type constraint compiles when it should fail:

import lpt

var str = newStringOfCap(81920) # Unique data stacked bk2bk
const bOff = 26 # <64 MiB UNIQUE word data
const bLen =  6 # <64B long; Give 1 To Below?
const bCnt = 32 # <2 GiCount; Could be RT w/less convenience
type
  Count {.packed.} = object     # Dense-ish hash Count type
    off {.bitsize: bOff.}: uint32
    len {.bitsize: bLen.}: uint8
    cnt {.bitsize: bCnt.}: uint32
  Counts = object
    dat: seq[Count]
    len: int

proc key(c: Count): string = str[c.off ..< c.off + c.len]
proc `==`(a: string|Count, b: Count):bool = true
proc key(c: Counts, i: int): string = c.dat[i].key
proc val(c: Counts, i: int): uint32 = c.dat[i].cnt
proc incFailed(h: var Counts, ms: string): bool = false

proc main() =
  var h: Counts
  var nTot = 0
  block IO:
    for line in stdin.lines:
      inc nTot                        # Always bump `nTot`
      if h.incFailed(line): break IO
  echo h.len," unique ",nTot," total ",str.len," B"
  for (k, c) in h.pairs: echo c," ",k
  h.incl "heyho"                      # Should fail;DOESN'T
main()

However, a key-only variant ko.nim works & fails correctly (EDIT: and differs from kv.nim only in the lack of bCnt & cnt and the return type of val):

import lpt

var str = newStringOfCap(81920) # Unique data stacked bk2bk
const bOff = 26 # <64 MiB UNIQUE word data
const bLen =  6 # <64B long; Give 1 To Below?
type
  Count {.packed.} = object     # Dense-ish hash Count type
    off {.bitsize: bOff.}: uint32
    len {.bitsize: bLen.}: uint8
  Counts = object
    dat: seq[Count]
    len: int

proc key(c: Count): string = str[c.off ..< c.off + c.len]
proc `==`(a: string|Count, b: Count):bool = true
proc key(c: Counts, i: int): string = c.dat[i].key
proc val(c: Counts, i: int): Void {.used.} = discard
proc incFailed(h: var Counts, ms: string): bool = false

proc main() =
  var h: Counts
  var nTot = 0
  block IO:
    for line in stdin.lines:
      inc nTot                        # Always bump `nTot`
      if h.incFailed(line): break IO
  echo h.len," unique ",nTot," total ",str.len," B"
# for (k, c) in h.pairs: echo c," ",k # Should & DOES fail
  h.incl "heyho"
main()

Nim Version

Nim Compiler Version 1.9.1 [Linux: amd64]
Compiled at 2023-01-10
Copyright (c) 2006-2023 by Andreas Rumpf

active boot switches: -d:release -d:danger -d:nimUseLinenoise -d:nimHasLibFFI

commit hash: b68b28f

However, this has been failing for at least the last few weeks of nim-devel and also fails on nim-1.6.10

Current Output

{ EDIT: When given an empty file as stdin, } the incorrect kv.nim output is

0 unique 0 total 0 B
0
0
0
whoa
did incl

while the correct ko.nim output is

0 unique 0 total 0 B
did incl

Expected Output

ko.nim output is as expected. kv.nim is not expected to compile.. Additionally, it is not expected to both sigmatch the incl and emit "whoa\n" from the when.

Possible Solution

No response

Additional Information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions