Nim
Nim copied to clipboard
[Concept] predicate checking for proc return types `seq[X]` fail for `type X` concept parameter
Description
I wanted a concept that checks if there are several procs defined for the given type.
One of those procs returned a seq of that type, so I wanted to check for that.
When you do so and use a type <TypeAliasName> concept parameter, the predicate that checks for the proc will always fail.
Minimal Example:
type ExampleConcept = concept example, type Typ
list() is seq[Typ] # This always fails
type Example = object
proc list(): seq[Example] = @[Example()]
proc foo(x: ExampleConcept) = echo "bar"
let ex = Example()
ex.foo()
Nim Version
Nim Compiler Version 2.0.0 [Linux: amd64] Compiled at 2023-08-01 Copyright (c) 2006-2023 by Andreas Rumpf
git hash: a488067a4130f029000be4550a0fb1b39e0e9e7c active boot switches: -d:release
Current Output
Error: type mismatch
Expression: foo(ex)
[1] ex: Example
Expected one of (first mismatch at [position]):
[1] proc foo(x: ExampleConcept)
/home/philipp/dev/playground/src/playground.nim(4, 3) ExampleConcept: concept predicate failed
Expected Output
bar
Possible Solution
As a workaround you can infer the type from a concept's instance variable instead, which somehow works :
type ExampleConcept = concept example, type Typ
list() is seq[example.type]
type Example = object
proc list(): seq[Example] = @[Example()]
proc foo(x: ExampleConcept) = echo "bar"
let ex = Example()
ex.foo()
Therefore fundamentally the feature works, it just doesn't interpret seq[Typ] correctly for some reason.
Additional Information
I had assumed this may affect any generic type such as e.g. Table or Set, but when I tested this for Table it worked perfectly fine.
import std/tables
type ExampleConcept = concept example, type Typ
list() is Table[string, Typ]
type Example = object
proc list(): Table[string, Example] = discard
proc foo(x: ExampleConcept) = echo "bar"
let ex = Example()
ex.foo()
So I'm not sure why seqs are specifically singled out with this problem.
Note: I've seen a ton of other concept issues, some fairly similar to this, but all of them seemed a bit more "complex". This here seems to be a less "complex" scenario where the problem occurred, so I thought it might be a separate issue.
wow just encountered this
type
TreeNodeRec* = ref object ## used in frontend
# children*: TreeNodeRec ## works with single
children*: seq[TreeNodeRec] # XXX does not work with seq
Node = concept t, type T
# t.children is typeof t ## works with single
# t.children is T ## works with single
t.children is seq[typeof t] # works with seq
# t.children is seq[T] # XXX does not work with seq
func match*(n: Node): int = 1
when isMainModule:
echo match TreeNodeRec()
new discovery. this works:
type
TreeNodeRec* = ref object
children*: seq[TreeNodeRec]
# Node = concept t, type T #
Node = concept t
type T = typeof t
t.children is seq[T]
func match*(n: Node): int = 1
echo match TreeNodeRec()