summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ast.nim2
-rw-r--r--compiler/extccomp.nim2
-rw-r--r--compiler/msgs.nim55
-rw-r--r--compiler/parser.nim15
-rw-r--r--compiler/sem.nim3
-rw-r--r--compiler/semdata.nim4
-rw-r--r--compiler/semexprs.nim30
-rw-r--r--compiler/semstmts.nim39
-rw-r--r--compiler/semtypes.nim3
-rw-r--r--compiler/sigmatch.nim68
10 files changed, 142 insertions, 79 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 2a7d8a551..5a5d87d06 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -712,7 +712,6 @@ type
                               # -1 means that the size is unkwown
     align*: int               # the type's alignment requirements
     loc*: TLoc
-    testeeName*: PIdent       # the test variable in user-defined type classes
 
   TPair*{.final.} = object 
     key*, val*: PObject
@@ -1088,7 +1087,6 @@ proc assignType(dest, src: PType) =
   dest.size = src.size
   dest.align = src.align
   dest.destructor = src.destructor
-  dest.testeeName = src.testeeName
   # this fixes 'type TLock = TSysLock':
   if src.sym != nil:
     if dest.sym != nil:
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index d7f3386e3..13eb972f6 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -583,7 +583,7 @@ proc CallCCompiler*(projectfile: string) =
       else:
         rawMessage(errGenerated, " execution of an external program failed; " &
                    "rerun with --parallelBuild:1 to see the error message")
-  if optNoLinking notin gGlobalOptions and cmds.len > 0:
+  if optNoLinking notin gGlobalOptions:
     # call the linker:
     var it = PStrEntry(toLink.head)
     var objfiles = ""
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 5363442b4..895ba71f3 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -436,7 +436,14 @@ type
                                # only 8 bytes.
     line*, col*: int16
     fileIndex*: int32
-    
+  
+  TErrorOutput* = enum
+    eStdOut
+    eStdErr
+    eInMemory
+
+  TErrorOutputs* = set[TErrorOutput]
+
   ERecoverableError* = object of EInvalidValue
   ESuggestDone* = object of EBase
 
@@ -534,13 +541,27 @@ var
   gHintCounter*: int = 0
   gWarnCounter*: int = 0
   gErrorMax*: int = 1         # stop after gErrorMax errors
-  gSilence*: int              # == 0 if we produce any output at all 
 
 when useCaas:
   var stdoutSocket*: TSocket
 
+proc UnknownLineInfo*(): TLineInfo =
+  result.line = int16(-1)
+  result.col = int16(-1)
+  result.fileIndex = -1
+
+var 
+  msgContext: seq[TLineInfo] = @[]
+  lastError = UnknownLineInfo()
+  bufferedMsgs*: seq[string]
+
+  errorOutputs* = {eStdOut, eStdErr}
+
+proc clearBufferedMsgs* =
+  bufferedMsgs = nil
+
 proc SuggestWriteln*(s: string) =
-  if gSilence == 0:
+  if eStdOut in errorOutputs:
     when useCaas:
       if isNil(stdoutSocket): Writeln(stdout, s)
       else:
@@ -548,6 +569,9 @@ proc SuggestWriteln*(s: string) =
         stdoutSocket.send(s & "\c\L")
     else:
       Writeln(stdout, s)
+  
+  if eInMemory in errorOutputs:
+    bufferedMsgs.safeAdd(s)
 
 proc SuggestQuit*() =
   if not isServing:
@@ -570,14 +594,6 @@ const
   RawWarningFormat* = "Warning: $1"
   RawHintFormat* = "Hint: $1"
 
-proc UnknownLineInfo*(): TLineInfo = 
-  result.line = int16(-1)
-  result.col = int16(-1)
-  result.fileIndex = -1
-
-var 
-  msgContext: seq[TLineInfo] = @[]
-
 proc getInfoContextLen*(): int = return msgContext.len
 proc setInfoContextLen*(L: int) = setLen(msgContext, L)
 
@@ -642,14 +658,18 @@ proc addCheckpoint*(filename: string, line: int) =
 
 proc OutWriteln*(s: string) = 
   ## Writes to stdout. Always.
-  if gSilence == 0: Writeln(stdout, s)
+  if eStdOut in errorOutputs: Writeln(stdout, s)
  
 proc MsgWriteln*(s: string) = 
   ## Writes to stdout. If --stdout option is given, writes to stderr instead.
-  if gSilence == 0:
-    if gCmd == cmdIdeTools and optCDebug notin gGlobalOptions: return
-    if optStdout in gGlobalOptions: Writeln(stderr, s)
-    else: Writeln(stdout, s)
+  if gCmd == cmdIdeTools and optCDebug notin gGlobalOptions: return
+
+  if optStdout in gGlobalOptions:
+    if eStdErr in errorOutputs: Writeln(stderr, s)
+  else:
+    if eStdOut in errorOutputs: Writeln(stdout, s)
+  
+  if eInMemory in errorOutputs: bufferedMsgs.safeAdd(s)
 
 proc coordToStr(coord: int): string = 
   if coord == -1: result = "???"
@@ -736,9 +756,6 @@ proc rawMessage*(msg: TMsgKind, args: openarray[string]) =
 proc rawMessage*(msg: TMsgKind, arg: string) = 
   rawMessage(msg, [arg])
 
-var
-  lastError = UnknownLineInfo()
-
 proc writeSurroundingSrc(info: TLineInfo) =
   const indent = "  "
   MsgWriteln(indent & info.sourceLine.ropeToStr)
diff --git a/compiler/parser.nim b/compiler/parser.nim
index e8439466a..fd51b04ec 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -1624,10 +1624,23 @@ proc parseObject(p: var TParser): PNode =
     return
   addSon(result, parseObjectPart(p))
 
+proc parseTypeClassParam(p: var TParser): PNode =
+  if p.tok.tokType == tkVar:
+    getTok(p)
+    result = newNode(nkVarTy)
+    result.addSon(p.parseSymbol)
+  else:
+    result = p.parseSymbol
+
 proc parseTypeClass(p: var TParser): PNode =
   result = newNodeP(nkTypeClassTy, p)
   getTok(p)
-  addSon(result, p.parseSymbol)
+  var args = newNode(nkArgList)
+  addSon(result, args)
+  addSon(args, p.parseTypeClassParam)
+  while p.tok.TokType == tkComma:
+    getTok(p)
+    addSon(args, p.parseTypeClassParam)
   if p.tok.tokType == tkCurlyDotLe and p.validInd:
     addSon(result, parsePragma(p))
   else:
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 71951dd3f..ea53afbeb 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -36,7 +36,8 @@ proc semParamList(c: PContext, n, genericParams: PNode, s: PSym)
 proc addParams(c: PContext, n: PNode, kind: TSymKind)
 proc maybeAddResult(c: PContext, s: PSym, n: PNode)
 proc instGenericContainer(c: PContext, n: PNode, header: PType): PType
-proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
+proc tryExpr(c: PContext, n: PNode,
+             flags: TExprFlags = {}, bufferErrors = false): PNode
 proc fixImmediateParams(n: PNode): PNode
 proc activate(c: PContext, n: PNode)
 proc semQuoteAst(c: PContext, n: PNode): PNode
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 121bf297d..d02359d4c 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -60,6 +60,7 @@ type
     threadEntries*: TSymSeq    # list of thread entries to check
     AmbiguousSymbols*: TIntSet # ids of all ambiguous symbols (cannot
                                # store this info in the syms themselves!)
+    InTypeClass*: int          # > 0 if we are in a user-defined type class
     InGenericContext*: int     # > 0 if we are in a generic type
     InUnrolledContext*: int    # > 0 if we are unrolling a loop
     InCompilesContext*: int    # > 0 if we are in a ``compiles`` magic
@@ -72,7 +73,8 @@ type
     libs*: TLinkedList         # all libs used by this module
     semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
     semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
-    semTryExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
+    semTryExpr*: proc (c: PContext, n: PNode,flags: TExprFlags = {},
+                       bufferErrors = false): PNode {.nimcall.}
     semOperand*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
     semConstBoolExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # XXX bite the bullet
     semOverloadedCall*: proc (c: PContext, n, nOrig: PNode,
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 47e07d402..337224aef 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -299,7 +299,7 @@ proc semOf(c: PContext, n: PNode): PNode =
   n.typ = getSysType(tyBool)
   result = n
 
-proc IsOpImpl(c: PContext, n: PNode): PNode =
+proc isOpImpl(c: PContext, n: PNode): PNode =
   InternalAssert n.sonsLen == 3 and
     n[1].kind == nkSym and n[1].sym.kind == skType and
     n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
@@ -321,10 +321,19 @@ proc IsOpImpl(c: PContext, n: PNode): PNode =
   else:
     var match: bool
     let t2 = n[2].typ
-    if t2.kind == tyTypeClass:
+    case t2.kind
+    of tyTypeClass:
       var m: TCandidate
       InitCandidate(m, t2)
       match = matchUserTypeClass(c, m, emptyNode, t2, t1) != nil
+    of tyOrdinal:
+      var m: TCandidate
+      InitCandidate(m, t2)
+      match = isOrdinalType(t1)
+    of tySequence, tyArray, tySet:
+      var m: TCandidate
+      InitCandidate(m, t2)
+      match = typeRel(m, t2, t1) != isNone
     else:
       match = sameType(t1, t2)
  
@@ -353,7 +362,7 @@ proc semIs(c: PContext, n: PNode): PNode =
 
   let t1 = n[1].typ.sons[0]
   # BUGFIX: don't evaluate this too early: ``T is void``
-  if not containsGenericType(t1): result = IsOpImpl(c, n)
+  if not containsGenericType(t1): result = isOpImpl(c, n)
 
 proc semOpAux(c: PContext, n: PNode) =
   const flags = {efDetermineType}
@@ -763,7 +772,8 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode =
     analyseIfAddressTakenInCall(c, result)
     if callee.magic != mNone:
       result = magicsAfterOverloadResolution(c, result, flags)
-  result = evalAtCompileTime(c, result)
+  if c.InTypeClass == 0:
+    result = evalAtCompileTime(c, result)
 
 proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = 
   # this seems to be a hotspot in the compiler!
@@ -814,7 +824,7 @@ proc buildEchoStmt(c: PContext, n: PNode): PNode =
 
 proc semExprNoType(c: PContext, n: PNode): PNode =
   result = semExpr(c, n, {efWantStmt})
-  discardCheck(result)
+  discardCheck(c, result)
   
 proc isTypeExpr(n: PNode): bool = 
   case n.kind
@@ -1208,7 +1218,7 @@ proc semProcBody(c: PContext, n: PNode): PNode =
       a.sons[1] = result
       result = semAsgn(c, a)
   else:
-    discardCheck(result)
+    discardCheck(c, result)
   closeScope(c)
 
 proc SemYieldVarResult(c: PContext, n: PNode, restype: PType) =
@@ -1429,12 +1439,12 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
     newNode(nkCall, n.info, quotes)])
   result = semExpandToAst(c, result)
 
-proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
+proc tryExpr(c: PContext, n: PNode,
+             flags: TExprFlags = {}, bufferErrors = false): PNode =
   # watch out, hacks ahead:
   let oldErrorCount = msgs.gErrorCounter
   let oldErrorMax = msgs.gErrorMax
   inc c.InCompilesContext
-  inc msgs.gSilence
   # do not halt after first error:
   msgs.gErrorMax = high(int)
   
@@ -1443,6 +1453,8 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   openScope(c)
   let oldOwnerLen = len(gOwners)
   let oldGenerics = c.generics
+  let oldErrorOutputs = errorOutputs
+  errorOutputs = if bufferErrors: {eInMemory} else: {}
   let oldContextLen = msgs.getInfoContextLen()
   
   let oldInGenericContext = c.InGenericContext
@@ -1465,7 +1477,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   setlen(gOwners, oldOwnerLen)
   c.currentScope = oldScope
   dec c.InCompilesContext
-  dec msgs.gSilence
+  errorOutputs = oldErrorOutputs
   msgs.gErrorCounter = oldErrorCount
   msgs.gErrorMax = oldErrorMax
 
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index ed6787a16..da8ba50a8 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -132,7 +132,7 @@ proc fixNilType(n: PNode) =
     for it in n: fixNilType(it)
   n.typ = nil
 
-proc discardCheck(result: PNode) =
+proc discardCheck(c: PContext, result: PNode) =
   if result.typ != nil and result.typ.kind notin {tyStmt, tyEmpty}:
     if result.kind == nkNilLit:
       result.typ = nil
@@ -142,6 +142,10 @@ proc discardCheck(result: PNode) =
       while n.kind in skipForDiscardable:
         n = n.lastSon
         n.typ = nil
+    elif c.InTypeClass > 0 and result.typ.kind == tyBool:
+      let verdict = semConstExpr(c, result)
+      if verdict.intVal == 0:
+        localError(result.info, "type class predicate failed.")
     elif result.typ.kind != tyError and gCmd != cmdInteractive:
       if result.typ.kind == tyNil:
         fixNilType(result)
@@ -169,7 +173,7 @@ proc semIf(c: PContext, n: PNode): PNode =
       typ = commonType(typ, it.sons[0].typ)
     else: illFormedAst(it)
   if isEmptyType(typ) or typ.kind == tyNil or not hasElse:
-    for it in n: discardCheck(it.lastSon)
+    for it in n: discardCheck(c, it.lastSon)
     result.kind = nkIfStmt
     # propagate any enforced VoidContext:
     if typ == EnforceVoidContext: result.typ = EnforceVoidContext
@@ -230,7 +234,7 @@ proc semCase(c: PContext, n: PNode): PNode =
       localError(n.info, errNotAllCasesCovered)
   closeScope(c)
   if isEmptyType(typ) or typ.kind == tyNil or not hasElse:
-    for i in 1..n.len-1: discardCheck(n.sons[i].lastSon)
+    for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon)
     # propagate any enforced VoidContext:
     if typ == EnforceVoidContext:
       result.typ = EnforceVoidContext
@@ -275,8 +279,8 @@ proc semTry(c: PContext, n: PNode): PNode =
     typ = commonType(typ, a.sons[length-1].typ)
   dec c.p.inTryStmt
   if isEmptyType(typ) or typ.kind == tyNil:
-    discardCheck(n.sons[0])
-    for i in 1..n.len-1: discardCheck(n.sons[i].lastSon)
+    discardCheck(c, n.sons[0])
+    for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon)
     if typ == EnforceVoidContext:
       result.typ = EnforceVoidContext
   else:
@@ -879,8 +883,9 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
   openScope(c)
   if n.sons[genericParamsPos].kind != nkEmpty:
     illFormedAst(n)           # process parameters:
-  if n.sons[paramsPos].kind != nkEmpty: 
-    semParamList(c, n.sons[ParamsPos], nil, s)
+  if n.sons[paramsPos].kind != nkEmpty:
+    var gp = newNodeI(nkGenericParams, n.info)
+    semParamList(c, n.sons[ParamsPos], gp, s)
     ParamsTypeCheck(c, s.typ)
   else:
     s.typ = newTypeS(tyProc, c)
@@ -1104,24 +1109,24 @@ proc finishMethod(c: PContext, s: PSym) =
     methodDef(s, false)
 
 proc semMethod(c: PContext, n: PNode): PNode = 
-  if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "method")
+  if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "method")
   result = semProcAux(c, n, skMethod, methodPragmas)
   
   var s = result.sons[namePos].sym
-  if not isGenericRoutine(s):
+  if not isGenericRoutine(s) and result.sons[bodyPos].kind != nkEmpty:
     if hasObjParam(s):
-      methodDef(s, false)
+      methodDef(s, fromCache=false)
     else:
-      LocalError(n.info, errXNeedsParamObjectType, "method")
+      localError(n.info, errXNeedsParamObjectType, "method")
 
 proc semConverterDef(c: PContext, n: PNode): PNode = 
-  if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "converter")
+  if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "converter")
   checkSonsLen(n, bodyPos + 1)
   result = semProcAux(c, n, skConverter, converterPragmas)
   var s = result.sons[namePos].sym
   var t = s.typ
-  if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "converter")
-  if sonsLen(t) != 2: LocalError(n.info, errXRequiresOneArgument, "converter")
+  if t.sons[0] == nil: localError(n.info, errXNeedsReturnType, "converter")
+  if sonsLen(t) != 2: localError(n.info, errXRequiresOneArgument, "converter")
   addConverter(c, s)
 
 proc semMacroDef(c: PContext, n: PNode): PNode = 
@@ -1129,9 +1134,9 @@ proc semMacroDef(c: PContext, n: PNode): PNode =
   result = semProcAux(c, n, skMacro, macroPragmas)
   var s = result.sons[namePos].sym
   var t = s.typ
-  if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "macro")
+  if t.sons[0] == nil: localError(n.info, errXNeedsReturnType, "macro")
   if n.sons[bodyPos].kind == nkEmpty:
-    LocalError(n.info, errImplOfXexpected, s.name.s)
+    localError(n.info, errImplOfXexpected, s.name.s)
   
 proc evalInclude(c: PContext, n: PNode): PNode =
   result = newNodeI(nkStmtList, n.info)
@@ -1221,7 +1226,7 @@ proc semStmtList(c: PContext, n: PNode): PNode =
         voidContext = true
         n.typ = EnforceVoidContext
       if i != last or voidContext:
-        discardCheck(n.sons[i])
+        discardCheck(c, n.sons[i])
       else:
         n.typ = n.sons[i].typ
         if not isEmptyType(n.typ):
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index b9893d037..92f47f585 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -876,8 +876,7 @@ proc freshType(res, prev: PType): PType {.inline.} =
 proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
   # if n.sonsLen == 0: return newConstraint(c, tyTypeClass)
   result = newOrPrevType(tyTypeClass, prev, c)
-  result.testeeName = considerAcc(n[0])
-  result.n = n[3]
+  result.n = n
 
   let
     pragmas = n[1]
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 318acc660..00f3b2b10 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -85,6 +85,7 @@ proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode,
   c.calleeSym = callee
   c.calleeScope = calleeScope
   initIdTable(c.bindings)
+  c.errors = nil
   if binding != nil and callee.kind in RoutineKinds:
     var typeParams = callee.ast[genericParamsPos]
     for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1):
@@ -202,7 +203,7 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1): string =
     add(result, argTypeToString(arg))
     if i != sonsLen(n) - 1: add(result, ", ")
 
-proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation
+proc typeRel*(c: var TCandidate, f, a: PType): TTypeRelation
 proc concreteType(c: TCandidate, t: PType): PType = 
   case t.kind
   of tyArrayConstr: 
@@ -750,40 +751,55 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
 
   # pushInfoContext(arg.info)
   openScope(c)
+  inc c.InTypeClass
 
-  var testee = newSym(skParam, f.testeeName, f.sym, f.sym.info)
-  testee.typ = a
-  addDecl(c, testee)
+  finally:
+    dec c.InTypeClass
+    closeScope(c)
 
-  for stmt in f.n:
-    var e = c.semTryExpr(c, copyTree(stmt))
-    if e == nil:
-      let expStr = renderTree(stmt, {renderNoComments})
-      m.errors.safeAdd("can't compile " & expStr & "  for " & a.typeToString)
-      return nil
-    case e.kind
-    of nkReturnStmt:
-      nil
-    of nkTypeSection: nil
-    of nkConstDef: nil
+  for param in f.n[0]:
+    var
+      dummyName: PNode
+      dummyType: PType
+    
+    if param.kind == nkVarTy:
+      dummyName = param[0]
+      dummyType = makeVarType(c, a)
     else:
-      if e.typ.kind == tyBool:
-        let verdict = c.semConstExpr(c, e)
-        if verdict.intVal == 0:
-          let expStr = renderTree(stmt, {renderNoComments})
-          m.errors.safeAdd(expStr & " doesn't hold for " & a.typeToString)
-          return nil
+      dummyName = param
+      dummyType = a
+
+    InternalAssert dummyName.kind == nkIdent
+    var dummyParam = newSym(skType, dummyName.ident, f.sym, f.sym.info)
+    dummyParam.typ = dummyType
+    addDecl(c, dummyParam)
 
-  closeScope(c)
+  for stmt in f.n[3]:
+    var e = c.semTryExpr(c, copyTree(stmt), bufferErrors = false)
+    m.errors = bufferedMsgs
+    clearBufferedMsgs()
+    if e == nil: return nil
 
+    case e.kind
+    of nkReturnStmt: nil
+    of nkTypeSection: nil
+    of nkConstDef: nil
+    else: nil
+  
   result = arg
   put(m.bindings, f, a)
 
-proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType, 
+proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, argType: PType,
                         argSemantized, argOrig: PNode): PNode =
-  var arg = argSemantized
-  var r: TTypeRelation
-  let fMaybeExpr = f.skipTypes({tyDistinct})
+  var
+    r: TTypeRelation
+    arg = argSemantized
+
+  let
+    a = if c.InTypeClass > 0: argType.skipTypes({tyTypeDesc})
+        else: argType
+    fMaybeExpr = f.skipTypes({tyDistinct})
+
   case fMaybeExpr.kind
   of tyExpr:
     if fMaybeExpr.sonsLen == 0: