summary refs log tree commit diff stats
path: root/tests/concepts
diff options
context:
space:
mode:
Diffstat (limited to 'tests/concepts')
-rw-r--r--tests/concepts/t18409.nim37
-rw-r--r--tests/concepts/t19730.nim20
-rw-r--r--tests/concepts/t20237.nim3
-rw-r--r--tests/concepts/t3330.nim2
-rw-r--r--tests/concepts/t8012.nim15
-rw-r--r--tests/concepts/t8558.nim26
-rw-r--r--tests/concepts/t976.nim57
-rw-r--r--tests/concepts/tconcepts.nim13
-rw-r--r--tests/concepts/tconcepts_issues.nim197
-rw-r--r--tests/concepts/tconcepts_overload_precedence.nim2
-rw-r--r--tests/concepts/texplain.nim92
-rw-r--r--tests/concepts/treversable.nim2
-rw-r--r--tests/concepts/tspec.nim105
-rw-r--r--tests/concepts/tusertypeclasses.nim3
-rw-r--r--tests/concepts/tusertypeclasses2.nim73
-rw-r--r--tests/concepts/twrapconcept.nim3
16 files changed, 525 insertions, 125 deletions
diff --git a/tests/concepts/t18409.nim b/tests/concepts/t18409.nim
new file mode 100644
index 000000000..0edba2d31
--- /dev/null
+++ b/tests/concepts/t18409.nim
@@ -0,0 +1,37 @@
+discard """
+  action: "compile"
+"""
+
+# A vector space over a field F concept.
+type VectorSpace*[F] = concept x, y, type V
+  vector_add(x, y) is V
+  scalar_mul(x, F) is V
+  dimension(V) is Natural
+
+# Real numbers (here floats) form a vector space.
+func vector_add*(v: float, w: float): float =  v + w
+func scalar_mul*(v: float, s: float): float =   v * s
+func dimension*(x: typedesc[float]): Natural = 1
+
+# 2-tuples of real numbers form a vector space.
+func vector_add*(v, w: (float, float)): (float, float) =
+  (vector_add(v[0], w[0]), vector_add(v[1], w[1]))
+
+func scalar_mul*(v: (float, float), s: float): (float, float) =
+  (scalar_mul(v[0], s), scalar_mul(v[1], s))
+
+func dimension*(x: typedesc[(float, float)]): Natural = 2
+
+# Check concept requirements.
+assert float is VectorSpace
+assert (float, float) is VectorSpace
+
+# Commutivity axiom for vector spaces over the same field.
+func axiom_commutivity*[F](u, v: VectorSpace[F]): bool =
+  vector_add(u, v) == vector_add(v, u)
+
+# This is okay.
+assert axiom_commutivity(2.2, 3.3)
+
+# This is not.
+assert axiom_commutivity((2.2, 3.3), (4.4, 5.5))
diff --git a/tests/concepts/t19730.nim b/tests/concepts/t19730.nim
new file mode 100644
index 000000000..575d45dda
--- /dev/null
+++ b/tests/concepts/t19730.nim
@@ -0,0 +1,20 @@
+discard """
+  output: '''1.01.01.01.0
+1.01.01.01.0
+'''
+"""
+
+type
+  Color = concept c
+    c.r is SomeFloat
+    c.g is SomeFloat
+    c.b is SomeFloat
+    c.a is SomeFloat
+
+proc useColor(color: Color) =
+  echo(color.r, color.g, color.b, color.a)
+
+let color = (r: 1.0, g: 1.0, b: 1.0, a: 1.0)
+useColor(color)
+
+useColor((r: 1.0, g: 1.0, b: 1.0, a: 1.0))
diff --git a/tests/concepts/t20237.nim b/tests/concepts/t20237.nim
new file mode 100644
index 000000000..175c7a9d1
--- /dev/null
+++ b/tests/concepts/t20237.nim
@@ -0,0 +1,3 @@
+type Foo* = concept
+  ## doc comment
+  proc foo(x: Self)
diff --git a/tests/concepts/t3330.nim b/tests/concepts/t3330.nim
index b92af5485..901f8d2f4 100644
--- a/tests/concepts/t3330.nim
+++ b/tests/concepts/t3330.nim
@@ -1,4 +1,5 @@
 discard """
+matrix: "--mm:refc"
 errormsg: "type mismatch: got <Bar[system.int]>"
 nimout: '''
 t3330.nim(70, 4) Error: type mismatch: got <Bar[system.int]>
@@ -48,7 +49,6 @@ expression: test(bar)'''
 
 
 
-
 ## line 60
 type
   Foo[T] = concept k
diff --git a/tests/concepts/t8012.nim b/tests/concepts/t8012.nim
new file mode 100644
index 000000000..ec2aa6e5c
--- /dev/null
+++ b/tests/concepts/t8012.nim
@@ -0,0 +1,15 @@
+type
+  MyTypeCon = concept c
+    c.counter is int
+  MyType = object
+    counter: int
+
+proc foo(conc: var MyTypeCon) =
+  conc.counter.inc
+  if conc.counter < 5:
+    foo(conc)
+
+var x: MyType
+
+x.foo
+discard x.repr
diff --git a/tests/concepts/t8558.nim b/tests/concepts/t8558.nim
new file mode 100644
index 000000000..acb2de30e
--- /dev/null
+++ b/tests/concepts/t8558.nim
@@ -0,0 +1,26 @@
+discard """
+  output: '''10
+9
+8
+7
+6
+5
+4
+3
+2
+1
+go!
+'''
+"""
+
+type Integral = concept x
+  x == 0 is bool
+  x - 1 is type(x)
+
+proc countToZero(n: Integral) =
+  if n == 0: echo "go!"
+  else:
+    echo n
+    countToZero(n-1)
+
+countToZero(10)
\ No newline at end of file
diff --git a/tests/concepts/t976.nim b/tests/concepts/t976.nim
new file mode 100644
index 000000000..776d53827
--- /dev/null
+++ b/tests/concepts/t976.nim
@@ -0,0 +1,57 @@
+discard """
+  output: '''
+Printable
+'''
+joinable: false
+"""
+
+#[
+  The converter is a proper example of a confounding variable
+  Moved to an isolated file
+]#
+
+type
+  Obj1[T] = object
+      v: T
+converter toObj1[T](t: T): Obj1[T] =
+  return Obj1[T](v: t)
+block t976:
+  type
+    int1 = distinct int
+    int2 = distinct int
+    int1g = concept x
+      x is int1
+    int2g = concept x
+      x is int2
+
+  proc take[T: int1g](value: int1) =
+    when T is int2:
+      static: error("killed in take(int1)")
+
+  proc take[T: int2g](vale: int2) =
+    when T is int1:
+      static: error("killed in take(int2)")
+
+  var i1: int1 = 1.int1
+  var i2: int2 = 2.int2
+
+  take[int1](i1)
+  take[int2](i2)
+
+  template reject(e) =
+    static: assert(not compiles(e))
+
+  reject take[string](i2)
+  reject take[int1](i2)
+
+  # bug #6249
+  type
+      Obj2 = ref object
+      PrintAble = concept x
+          $x is string
+
+  proc `$`[T](nt: Obj1[T]): string =
+      when T is PrintAble: result = "Printable"
+      else: result = "Non Printable"
+
+  echo Obj2()
\ No newline at end of file
diff --git a/tests/concepts/tconcepts.nim b/tests/concepts/tconcepts.nim
index d0bc76c20..ea3ddc401 100644
--- a/tests/concepts/tconcepts.nim
+++ b/tests/concepts/tconcepts.nim
@@ -31,6 +31,7 @@ e
 20
 10
 5
+9
 '''
 """
 
@@ -98,7 +99,7 @@ block tconceptinclosure:
 block overload_precedence:
   type ParameterizedType[T] = object
 
-  type CustomTypeClass = concept
+  type CustomTypeClass = concept c
     true
 
   # 3 competing procs
@@ -438,3 +439,13 @@ import mvarconcept
 block tvar:
   # bug #2346, bug #2404
   echo randomInt(5)
+
+block tcomment:
+  type
+    Foo = concept
+      ## Some comment
+      proc bar(x: Self)
+
+  proc bar(x: int) = echo x
+  proc foo(x: Foo) = x.bar
+  foo(9)
diff --git a/tests/concepts/tconcepts_issues.nim b/tests/concepts/tconcepts_issues.nim
index 65f6d4660..c6d0267c5 100644
--- a/tests/concepts/tconcepts_issues.nim
+++ b/tests/concepts/tconcepts_issues.nim
@@ -1,7 +1,6 @@
 discard """
   output: '''
 20.0 USD
-Printable
 true
 true
 true
@@ -27,6 +26,8 @@ false
 true
 -1
 Meow
+10 0.0
+1 2.0
 '''
 joinable: false
 """
@@ -76,55 +77,6 @@ block t3414:
   let s2 = s1.find(10)
 
 
-
-type
-  Obj1[T] = object
-      v: T
-converter toObj1[T](t: T): Obj1[T] =
-  return Obj1[T](v: t)
-block t976:
-  type
-    int1 = distinct int
-    int2 = distinct int
-    int1g = concept x
-      x is int1
-    int2g = concept x
-      x is int2
-
-  proc take[T: int1g](value: int1) =
-    when T is int2:
-      static: error("killed in take(int1)")
-
-  proc take[T: int2g](vale: int2) =
-    when T is int1:
-      static: error("killed in take(int2)")
-
-  var i1: int1 = 1.int1
-  var i2: int2 = 2.int2
-
-  take[int1](i1)
-  take[int2](i2)
-
-  template reject(e) =
-    static: assert(not compiles(e))
-
-  reject take[string](i2)
-  reject take[int1](i2)
-
-  # bug #6249
-  type
-      Obj2 = ref object
-      PrintAble = concept x
-          $x is string
-
-  proc `$`[T](nt: Obj1[T]): string =
-      when T is PrintAble: result = "Printable"
-      else: result = "Non Printable"
-
-  echo Obj2()
-
-
-
 block t1128:
   type
     TFooContainer[T] = object
@@ -324,15 +276,15 @@ block t6691:
 block t6782:
   type
     Reader = concept c
-      c.read(openarray[byte], int, int) is int
+      c.read(openArray[byte], int, int) is int
     Rdr = concept c
-      c.rd(openarray[byte], int, int) is int
+      c.rd(openArray[byte], int, int) is int
 
   type TestFile = object
 
-  proc read(r: TestFile, dest: openarray[byte], offset: int, limit: int): int =
+  proc read(r: TestFile, dest: openArray[byte], offset: int, limit: int): int =
       result = 0
-  proc rd(r: TestFile, dest: openarray[byte], offset: int, limit: int): int =
+  proc rd(r: TestFile, dest: openArray[byte], offset: int, limit: int): int =
       result = 0
 
   doAssert TestFile is Reader
@@ -397,7 +349,7 @@ block misc_issues:
   echo p2.x is float and p2.y is float # true
 
   # https://github.com/nim-lang/Nim/issues/2018
-  type ProtocolFollower = concept
+  type ProtocolFollower = concept c
     true # not a particularly involved protocol
 
   type ImplementorA = object
@@ -467,3 +419,138 @@ block misc_issues:
   # anyway and will be an error soon.
   var a: Cat = Cat()
   a.sayHello()
+
+
+# bug #16897
+
+type
+  Fp[N: static int, T] = object
+    big: array[N, T]
+
+type
+  QuadraticExt* = concept x
+    ## Quadratic Extension concept (like complex)
+    type BaseField = auto
+    x.c0 is BaseField
+    x.c1 is BaseField
+var address = pointer(nil)
+proc prod(r: var QuadraticExt, b: QuadraticExt) =
+  if address == nil:
+    address = addr b
+    prod(r, b)
+  else:
+    assert address == addr b
+
+type
+  Fp2[N: static int, T] {.byref.} = object
+    c0, c1: Fp[N, T]
+
+# This should be passed by reference,
+# but concepts do not respect the 24 bytes rule
+# or `byref` pragma.
+var r, b: Fp2[6, uint64]
+
+prod(r, b)
+
+
+block: # bug #21263
+  type
+    DateDayFraction = concept # no T, an atom
+      proc date(a: Self): int
+      proc fraction(b: Self): float
+    Date = distinct int
+    DateDayFractionImpl = object
+      date : int
+      fraction : float
+
+  proc date(a: Date): int = a.int
+  proc fraction(a:Date): float = 0.0
+
+  proc date(a: DateDayFractionImpl): int = a.date
+  proc fraction(b: DateDayFractionImpl): float = b.fraction
+
+
+  proc print(a: DateDayFraction) =
+    echo a.date, " ", a.fraction
+
+  print(10.Date) # ok
+  print(DateDayFractionImpl(date: 1, fraction: 2))  # error
+
+import sets
+import deques
+
+type AnyTree[V] = concept t, type T
+  for v in t.leaves(V):
+    v is V
+
+type BreadthOrder[V] = ref object
+  frontier: Deque[V]
+  visited: HashSet[V]
+
+proc expand[V, T](order: ref BreadthOrder[T], tree: AnyTree[V], node: V, transform: (V) -> (T)) =
+  for leaf in tree.leaves(node):
+    if not order.visited.containsOrIncl(transform(leaf)):
+      order.frontier.addLast(transform(leaf))
+
+proc hasNext[V](order: ref BreadthOrder[V]): bool =
+  order.frontier.len > 0
+
+proc init[V](_: typedesc[BreadthOrder]): ref BreadthOrder[V] =
+  result.new()
+  result[] = BreadthOrder[V](frontier: initDeque[V](), visited: initHashSet[V]())
+
+proc popNext[V](order: ref BreadthOrder[V]): V =
+  order.frontier.popFirst()
+
+type LevelNode[V] = tuple
+  depth: uint
+  node: V
+
+proc depthOf*[V](orderType: typedesc[BreadthOrder], tree: AnyTree[V], root, goal: V): uint =
+  if root == goal:
+    return 0
+  var order = init[LevelNode[V]](orderType)
+  order.expand(tree, root, (leaf) => (1.uint, leaf))
+  while order.hasNext():
+    let depthNode: LevelNode[V] = order.popNext()
+    if depthNode.node == goal:
+      return depthNode.depth
+    order.expand(tree, depthNode.node, (leaf) => (depthNode.depth + 1, leaf))
+
+type CappedStringTree = ref object
+  symbols: string
+  cap: Natural
+
+iterator leaves*(t: CappedStringTree, s: string): string =
+  if s.len < t.cap:
+    for c in t.symbols:
+      yield s & c
+
+block: # bug #12852
+  var tree = CappedStringTree(symbols: "^v><", cap: 5)
+
+  doAssert BreadthOrder.depthOf(tree, "", ">>>") == 3
+
+block: #bug #22723
+  type
+    Node  = concept n, type T 
+      for i in n.children:
+        i is T
+      n.parent is T
+
+    Nd = ref object
+      parent: Nd
+      children: seq[Nd]
+
+  proc addChild(parent, child: Node) =
+    parent.children.add(child)
+    child.parent = parent
+
+  proc foo =
+    var
+      a = Nd()
+      b = Nd()
+    a.addChild(b)
+    doAssert a.children.len == 1
+
+  foo()
diff --git a/tests/concepts/tconcepts_overload_precedence.nim b/tests/concepts/tconcepts_overload_precedence.nim
index 9eed6256a..c580d2688 100644
--- a/tests/concepts/tconcepts_overload_precedence.nim
+++ b/tests/concepts/tconcepts_overload_precedence.nim
@@ -9,7 +9,7 @@ x as CustomTypeClass'''
 
 type ParameterizedType[T] = object
 
-type CustomTypeClass = concept
+type CustomTypeClass = concept c
   true
 
 # 3 competing procs
diff --git a/tests/concepts/texplain.nim b/tests/concepts/texplain.nim
index de3d540cd..8cf04ae82 100644
--- a/tests/concepts/texplain.nim
+++ b/tests/concepts/texplain.nim
@@ -1,45 +1,33 @@
 discard """
   cmd: "nim c --verbosity:0 --colors:off $file"
   nimout: '''
-texplain.nim(164, 10) Hint: Non-matching candidates for e(y)
+texplain.nim(162, 10) Hint: Non-matching candidates for e(y)
 proc e(i: int): int
   first type mismatch at position: 1
   required type for i: int
   but expression 'y' is of type: MatchingType
 
-texplain.nim(167, 7) Hint: Non-matching candidates for e(10)
+texplain.nim(165, 7) Hint: Non-matching candidates for e(10)
 proc e(o: ExplainedConcept): int
   first type mismatch at position: 1
   required type for o: ExplainedConcept
   but expression '10' is of type: int literal(10)
-texplain.nim(130, 6) ExplainedConcept: undeclared field: 'foo'
-texplain.nim(130, 6) ExplainedConcept: undeclared field: '.'
-texplain.nim(130, 6) ExplainedConcept: expression '.' cannot be called
-texplain.nim(130, 6) ExplainedConcept: expression '' has no type (or is ambiguous)
-texplain.nim(130, 5) ExplainedConcept: concept predicate failed
-texplain.nim(131, 6) ExplainedConcept: undeclared field: 'bar'
-texplain.nim(131, 6) ExplainedConcept: undeclared field: '.'
-texplain.nim(131, 6) ExplainedConcept: expression '.' cannot be called
-texplain.nim(131, 6) ExplainedConcept: expression '' has no type (or is ambiguous)
-texplain.nim(130, 5) ExplainedConcept: concept predicate failed
-
-texplain.nim(170, 10) Hint: Non-matching candidates for e(10)
+texplain.nim(128, 6) ExplainedConcept: undeclared field: 'foo'
+texplain.nim(128, 5) ExplainedConcept: concept predicate failed
+texplain.nim(129, 6) ExplainedConcept: undeclared field: 'bar'
+texplain.nim(128, 5) ExplainedConcept: concept predicate failed
+
+texplain.nim(168, 10) Hint: Non-matching candidates for e(10)
 proc e(o: ExplainedConcept): int
   first type mismatch at position: 1
   required type for o: ExplainedConcept
   but expression '10' is of type: int literal(10)
-texplain.nim(130, 6) ExplainedConcept: undeclared field: 'foo'
-texplain.nim(130, 6) ExplainedConcept: undeclared field: '.'
-texplain.nim(130, 6) ExplainedConcept: expression '.' cannot be called
-texplain.nim(130, 6) ExplainedConcept: expression '' has no type (or is ambiguous)
-texplain.nim(130, 5) ExplainedConcept: concept predicate failed
-texplain.nim(131, 6) ExplainedConcept: undeclared field: 'bar'
-texplain.nim(131, 6) ExplainedConcept: undeclared field: '.'
-texplain.nim(131, 6) ExplainedConcept: expression '.' cannot be called
-texplain.nim(131, 6) ExplainedConcept: expression '' has no type (or is ambiguous)
-texplain.nim(130, 5) ExplainedConcept: concept predicate failed
-
-texplain.nim(174, 20) Error: type mismatch: got <NonMatchingType>
+texplain.nim(128, 6) ExplainedConcept: undeclared field: 'foo'
+texplain.nim(128, 5) ExplainedConcept: concept predicate failed
+texplain.nim(129, 6) ExplainedConcept: undeclared field: 'bar'
+texplain.nim(128, 5) ExplainedConcept: concept predicate failed
+
+texplain.nim(172, 20) Error: type mismatch: got <NonMatchingType>
 but expected one of:
 proc e(i: int): int
   first type mismatch at position: 1
@@ -49,11 +37,11 @@ proc e(o: ExplainedConcept): int
   first type mismatch at position: 1
   required type for o: ExplainedConcept
   but expression 'n' is of type: NonMatchingType
-texplain.nim(174, 9) template/generic instantiation of `assert` from here
-texplain.nim(130, 5) ExplainedConcept: concept predicate failed
+texplain.nim(172, 9) template/generic instantiation of `assert` from here
+texplain.nim(128, 5) ExplainedConcept: concept predicate failed
 
 expression: e(n)
-texplain.nim(175, 20) Error: type mismatch: got <NonMatchingType>
+texplain.nim(173, 20) Error: type mismatch: got <NonMatchingType>
 but expected one of:
 proc r(i: string): int
   first type mismatch at position: 1
@@ -63,15 +51,15 @@ proc r(o: RegularConcept): int
   first type mismatch at position: 1
   required type for o: RegularConcept
   but expression 'n' is of type: NonMatchingType
-texplain.nim(175, 9) template/generic instantiation of `assert` from here
-texplain.nim(134, 5) RegularConcept: concept predicate failed
+texplain.nim(173, 9) template/generic instantiation of `assert` from here
+texplain.nim(132, 5) RegularConcept: concept predicate failed
 proc r[T](a: SomeNumber; b: T; c: auto)
   first type mismatch at position: 1
   required type for a: SomeNumber
   but expression 'n' is of type: NonMatchingType
 
 expression: r(n)
-texplain.nim(176, 20) Hint: Non-matching candidates for r(y)
+texplain.nim(174, 20) Hint: Non-matching candidates for r(y)
 proc r(i: string): int
   first type mismatch at position: 1
   required type for i: string
@@ -81,28 +69,20 @@ proc r[T](a: SomeNumber; b: T; c: auto)
   required type for a: SomeNumber
   but expression 'y' is of type: MatchingType
 
-texplain.nim(184, 2) Error: type mismatch: got <MatchingType>
+texplain.nim(182, 2) Error: type mismatch: got <MatchingType>
 but expected one of:
 proc f(o: NestedConcept)
   first type mismatch at position: 1
   required type for o: NestedConcept
   but expression 'y' is of type: MatchingType
-texplain.nim(134, 6) RegularConcept: undeclared field: 'foo'
-texplain.nim(134, 6) RegularConcept: undeclared field: '.'
-texplain.nim(134, 6) RegularConcept: expression '.' cannot be called
-texplain.nim(134, 6) RegularConcept: expression '' has no type (or is ambiguous)
-texplain.nim(134, 5) RegularConcept: concept predicate failed
-texplain.nim(135, 6) RegularConcept: undeclared field: 'bar'
-texplain.nim(135, 6) RegularConcept: undeclared field: '.'
-texplain.nim(135, 6) RegularConcept: expression '.' cannot be called
-texplain.nim(135, 6) RegularConcept: expression '' has no type (or is ambiguous)
-texplain.nim(134, 5) RegularConcept: concept predicate failed
-texplain.nim(138, 5) NestedConcept: concept predicate failed
+texplain.nim(132, 6) RegularConcept: undeclared field: 'foo'
+texplain.nim(132, 5) RegularConcept: concept predicate failed
+texplain.nim(133, 6) RegularConcept: undeclared field: 'bar'
+texplain.nim(132, 5) RegularConcept: concept predicate failed
+texplain.nim(136, 5) NestedConcept: concept predicate failed
 
 expression: f(y)'''
   errormsg: "type mismatch: got <MatchingType>"
-  line: 184
-
 """
 
 
@@ -123,7 +103,25 @@ expression: f(y)'''
 
 
 
-# line 120 HERE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# line 124 HERE
 
 type
   ExplainedConcept {.explain.} = concept o
diff --git a/tests/concepts/treversable.nim b/tests/concepts/treversable.nim
index 6ebc077d9..d30ba0a3c 100644
--- a/tests/concepts/treversable.nim
+++ b/tests/concepts/treversable.nim
@@ -3,7 +3,7 @@ discard """
   output: '''
 z
 e
-  '''
+'''
 """
 
 type
diff --git a/tests/concepts/tspec.nim b/tests/concepts/tspec.nim
new file mode 100644
index 000000000..52f13a40a
--- /dev/null
+++ b/tests/concepts/tspec.nim
@@ -0,0 +1,105 @@
+discard """
+  output: '''4
+0
+4
+4
+1
+2
+3
+yes int
+string int'''
+  joinable: false
+"""
+
+import hashes
+
+type
+  Comparable = concept # no T, an atom
+    proc cmp(a, b: Self): int
+
+  ToStringable = concept
+    proc `$`(a: Self): string
+
+  Hashable = concept   ## the most basic of identity assumptions
+    proc hash(x: Self): int
+    proc `==`(x, y: Self): bool
+
+  Swapable = concept
+    proc swap(x, y: var Self)
+
+
+proc h(x: Hashable) =
+  echo x
+
+h(4)
+
+when true:
+  proc compare(a: Comparable) =
+    echo cmp(a, a)
+
+  compare(4)
+
+proc dollar(x: ToStringable) =
+  echo x
+
+when true:
+  dollar 4
+  dollar "4"
+
+#type D = distinct int
+
+#dollar D(4)
+
+when true:
+  type
+    Iterable[Ix] = concept
+      iterator items(c: Self): Ix
+
+  proc g[Tu](it: Iterable[Tu]) =
+    for x in it:
+      echo x
+
+  g(@[1, 2, 3])
+
+proc hs(x: Swapable) =
+  var y = x
+  swap y, y
+
+hs(4)
+
+type
+  Indexable[T] = concept # has a T, a collection
+    proc `[]`(a: Self; index: int): T # we need to describe how to infer 'T'
+    # and then we can use the 'T' and it must match:
+    proc `[]=`(a: var Self; index: int; value: T)
+    proc len(a: Self): int
+
+proc indexOf[T](a: Indexable[T]; value: T) =
+  echo "yes ", T
+
+block:
+  var x = @[1, 2, 3]
+  indexOf(x, 4)
+
+import tables, typetraits
+
+type
+  Dict[K, V] = concept
+    proc `[]`(s: Self; k: K): V
+    proc `[]=`(s: var Self; k: K; v: V)
+
+proc d[K2, V2](x: Dict[K2, V2]) =
+  echo K2, " ", V2
+
+var x = initTable[string, int]()
+d(x)
+
+
+type Monoid = concept
+  proc `+`(x, y: Self): Self
+  proc z(t: typedesc[Self]): Self
+
+proc z(x: typedesc[int]): int = 0
+
+doAssert int is Monoid
+
diff --git a/tests/concepts/tusertypeclasses.nim b/tests/concepts/tusertypeclasses.nim
index c7104f2a6..83e2b176e 100644
--- a/tests/concepts/tusertypeclasses.nim
+++ b/tests/concepts/tusertypeclasses.nim
@@ -1,4 +1,5 @@
 discard """
+  matrix: "--mm:refc"
   output: '''Sortable
 Sortable
 Container
@@ -9,6 +10,8 @@ int
 '''
 """
 
+# todo wait for https://github.com/nim-lang/Nim/pull/20380
+
 import typetraits
 
 template reject(expr) = assert(not compiles(x))
diff --git a/tests/concepts/tusertypeclasses2.nim b/tests/concepts/tusertypeclasses2.nim
index ae05540cd..6132bc2d8 100644
--- a/tests/concepts/tusertypeclasses2.nim
+++ b/tests/concepts/tusertypeclasses2.nim
@@ -1,24 +1,63 @@
-type
-  hasFieldX = concept z
-    z.x is int
+discard """
+  targets: "c js"
+"""
 
-  obj_x = object
-    x: int
+block:
+  type
+    hasFieldX = concept z
+      z.x is int
 
-  ref_obj_x = ref object
-    x: int
+    obj_x = object
+      x: int
 
-  ref_to_obj_x = ref obj_x
+    ref_obj_x = ref object
+      x: int
 
-  p_o_x = ptr obj_x
-  v_o_x = var obj_x
+    ref_to_obj_x = ref obj_x
 
-template check(x) =
-  static: assert(x)
+    p_o_x = ptr obj_x
+    v_o_x = var obj_x
 
-check obj_x is hasFieldX
-check ref_obj_x is hasFieldX
-check ref_to_obj_x is hasFieldX
-check p_o_x is hasFieldX
-check v_o_x is hasFieldX
+  template check(x) =
+    static: assert(x)
 
+  check obj_x is hasFieldX
+  check ref_obj_x is hasFieldX
+  check ref_to_obj_x is hasFieldX
+  check p_o_x is hasFieldX
+  check v_o_x is hasFieldX
+
+block:
+  type
+    Foo = concept x
+      x.isFoo
+    Bar = distinct float
+  template isFoo(x: Bar): untyped = true
+  proc foo(x: var Foo) =
+    float(x) = 1.0
+  proc foo2(x: var Bar) =
+    float(x) = 1.0
+  proc foo3(x: var (Bar|SomeNumber)) =
+    float(x) = 1.0
+  proc foo4(x: var any) =
+    float(x) = 1.0
+  var x: Bar
+  foo(x)
+  foo2(x)
+  foo3(x)
+  foo4(x)
+
+block: # bug #9550
+  block:
+    type Foo = concept c
+      for v in c: (v is char)
+
+    func foo(c: Foo) = (for v in c: discard)
+    foo @['a', 'b' ,'c']
+
+  block:
+    type Foo = concept c
+      for v in c: (v is char)
+
+    func foo(c: Foo) = (for v in c: discard)
+    foo ['a', 'b' ,'c']
diff --git a/tests/concepts/twrapconcept.nim b/tests/concepts/twrapconcept.nim
index 377b63afe..c3dea2ff9 100644
--- a/tests/concepts/twrapconcept.nim
+++ b/tests/concepts/twrapconcept.nim
@@ -1,7 +1,6 @@
 discard """
   errormsg: "type mismatch: got <string>"
-  line: 21
-  nimout: "twrapconcept.nim(11, 5) Foo: concept predicate failed"
+  nimout: "twrapconcept.nim(10, 5) Foo: concept predicate failed"
 """
 
 # https://github.com/nim-lang/Nim/issues/5127