summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semexprs.nim4
-rw-r--r--compiler/semfold.nim2
-rw-r--r--compiler/semstmts.nim11
-rw-r--r--compiler/types.nim2
-rw-r--r--tests/concepts/treversable.nim31
5 files changed, 44 insertions, 6 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 9d7c493a7..d7b5667b9 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -271,7 +271,7 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
     localError(c.config, n.info, errXExpectsTypeOrValue % opToStr[m])
   else:
     n.sons[1] = semExprWithType(c, n.sons[1], {efDetermineType})
-    var typ = skipTypes(n.sons[1].typ, abstractVarRange + {tyTypeDesc})
+    var typ = skipTypes(n.sons[1].typ, abstractVarRange + {tyTypeDesc, tyUserTypeClassInst})
     case typ.kind
     of tySequence, tyString, tyCString, tyOpenArray, tyVarargs:
       n.typ = getSysType(c.graph, n.info, tyInt)
@@ -1261,7 +1261,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
   # make sure we don't evaluate generic macros/templates
   n.sons[0] = semExprWithType(c, n.sons[0],
                               {efNoEvaluateGeneric})
-  let arr = skipTypes(n.sons[0].typ, {tyGenericInst,
+  let arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyUserTypeClassInst,
                                       tyVar, tyLent, tyPtr, tyRef, tyAlias, tySink})
   case arr.kind
   of tyArray, tyOpenArray, tyVarargs, tySequence, tyString,
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index eceb10470..2f495bc7f 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -619,7 +619,7 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
       of mLow:
         result = newIntNodeT(firstOrd(g.config, n.sons[1].typ), n, g)
       of mHigh:
-        if skipTypes(n.sons[1].typ, abstractVar).kind notin
+        if skipTypes(n.sons[1].typ, abstractVar+{tyUserTypeClassInst}).kind notin
             {tySequence, tyString, tyCString, tyOpenArray, tyVarargs}:
           result = newIntNodeT(lastOrd(g.config, skipTypes(n[1].typ, abstractVar)), n, g)
         else:
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 292238dc9..f1ff38b01 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -519,7 +519,9 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
         localError(c.config, a.info, errWrongNumberOfVariables)
       b = newNodeI(nkVarTuple, a.info)
       newSons(b, length)
-      b.sons[length-2] = a.sons[length-2] # keep type desc for doc generator
+      # keep type desc for doc generator
+      # NOTE: at the moment this is always ast.emptyNode, see parser.nim
+      b.sons[length-2] = a.sons[length-2]
       b.sons[length-1] = def
       addToVarSection(c, result, n, b)
     elif tup.kind == tyTuple and def.kind in {nkPar, nkTupleConstr} and
@@ -558,7 +560,12 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
           # keep documentation information:
           b.comment = a.comment
         addSon(b, newSymNode(v))
-        addSon(b, a.sons[length-2])      # keep type desc for doc generator
+        # keep type desc for doc generator, but only if the user explicitly
+        # added it
+        if a.sons[length-2].kind != nkEmpty:
+          addSon(b, newNodeIT(nkType, a.info, typ))
+        else:
+          addSon(b, a.sons[length-2])
         addSon(b, copyTree(def))
         addToVarSection(c, result, n, b)
       else:
diff --git a/compiler/types.nim b/compiler/types.nim
index 98343c688..a1bdc7730 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -615,7 +615,7 @@ proc firstOrd*(conf: ConfigRef; t: PType): BiggestInt =
     else:
       assert(t.n.sons[0].kind == nkSym)
       result = t.n.sons[0].sym.position
-  of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tyStatic, tyInferred:
+  of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tyStatic, tyInferred, tyUserTypeClassInst:
     result = firstOrd(conf, lastSon(t))
   of tyOrdinal:
     if t.len > 0: result = firstOrd(conf, lastSon(t))
diff --git a/tests/concepts/treversable.nim b/tests/concepts/treversable.nim
new file mode 100644
index 000000000..6ebc077d9
--- /dev/null
+++ b/tests/concepts/treversable.nim
@@ -0,0 +1,31 @@
+# issue 7705, 7703, 7702
+discard """
+  output: '''
+z
+e
+  '''
+"""
+
+type
+  Reversable*[T] = concept a
+    a[int] is T
+    a.high is int
+    a.len is int
+    a.low is int
+
+proc get[T](s: Reversable[T], n: int): T =
+  s[n]
+
+proc hi[T](s: Reversable[T]): int =
+  s.high
+
+proc lo[T](s: Reversable[T]): int =
+  s.low
+
+iterator reverse*[T](s: Reversable[T]): T =
+  assert hi(s) - lo(s) == len(s) - 1
+  for z in hi(s).countdown(lo(s)):
+    yield s.get(z)
+
+for s in @["e", "z"].reverse:
+  echo s