summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semtypes.nim3
-rw-r--r--compiler/semtypinst.nim7
-rw-r--r--compiler/sigmatch.nim82
-rw-r--r--tests/concepts/tconcepts_issues.nim2
-rw-r--r--tests/errmsgs/t16654.nim2
-rw-r--r--tests/misc/t12869.nim2
-rw-r--r--tests/proc/tinferlambdareturn.nim36
-rw-r--r--tests/stdlib/tsugar.nim3
-rw-r--r--tests/types/t15836.nim2
-rw-r--r--tests/types/t15836_2.nim5
10 files changed, 91 insertions, 53 deletions
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index fe87c2973..1f671effa 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -1436,7 +1436,8 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
             "' is only valid for macros and templates")
       # 'auto' as a return type does not imply a generic:
       elif r.kind == tyAnything:
-        discard
+        r = copyType(r, c.idgen, r.owner)
+        r.flags.incl tfRetType
       elif r.kind == tyStatic:
         # type allowed should forbid this type
         discard
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 1510a3f9c..d1327a3ae 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -315,6 +315,9 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym, t: PType): PSym =
     result.ast = replaceTypeVarsN(cl, s.ast)
 
 proc lookupTypeVar(cl: var TReplTypeVars, t: PType): PType =
+  if tfRetType in t.flags and t.kind == tyAnything:
+    # don't bind `auto` return type to a previous binding of `auto`
+    return nil
   result = cl.typeMap.lookup(t)
   if result == nil:
     if cl.allowMetaTypes or tfRetType in t.flags: return
@@ -551,7 +554,9 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
   result = t
   if t == nil: return
 
-  if t.kind in {tyStatic, tyGenericParam, tyConcept} + tyTypeClasses:
+  const lookupMetas = {tyStatic, tyGenericParam, tyConcept} + tyTypeClasses - {tyAnything}
+  if t.kind in lookupMetas or
+      (t.kind == tyAnything and tfRetType notin t.flags):
     let lookup = cl.typeMap.lookup(t)
     if lookup != nil: return lookup
 
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 557d4c447..9e99353d1 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -2120,6 +2120,7 @@ template matchesVoidProc(t: PType): bool =
 
 proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
                         argSemantized, argOrig: PNode): PNode =
+  result = nil
   var
     fMaybeStatic = f.skipTypes({tyDistinct})
     arg = argSemantized
@@ -2182,28 +2183,33 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
     else:
       return argSemantized # argOrig
 
-  # If r == isBothMetaConvertible then we rerun typeRel.
-  # bothMetaCounter is for safety to avoid any infinite loop,
-  #  I don't have any example when it is needed.
-  # lastBindingsLenth is used to check whether m.bindings remains the same,
-  #  because in that case there is no point in continuing.
-  var bothMetaCounter = 0
-  var lastBindingsLength = -1
-  while r == isBothMetaConvertible and
-      lastBindingsLength != m.bindings.counter and
-      bothMetaCounter < 100:
-    lastBindingsLength = m.bindings.counter
-    inc(bothMetaCounter)
-    if arg.kind in {nkProcDef, nkFuncDef, nkIteratorDef} + nkLambdaKinds:
-      result = c.semInferredLambda(c, m.bindings, arg)
-    elif arg.kind != nkSym:
-      return nil
-    else:
-      let inferred = c.semGenerateInstance(c, arg.sym, m.bindings, arg.info)
-      result = newSymNode(inferred, arg.info)
-    inc(m.convMatches)
-    arg = result
-    r = typeRel(m, f, arg.typ)
+  block instantiateGenericRoutine:
+    # In the case where the matched value is a generic proc, we need to
+    # fully instantiate it and then rerun typeRel to make sure it matches.
+    # instantiationCounter is for safety to avoid any infinite loop,
+    #  I don't have any example when it is needed.
+    # lastBindingCount is used to check whether m.bindings remains the same,
+    #  because in that case there is no point in continuing.
+    var instantiationCounter = 0
+    var lastBindingCount = -1
+    while r in {isBothMetaConvertible, isInferred, isInferredConvertible} and
+        lastBindingCount != m.bindings.counter and
+        instantiationCounter < 100:
+      lastBindingCount = m.bindings.counter
+      inc(instantiationCounter)
+      if arg.kind in {nkProcDef, nkFuncDef, nkIteratorDef} + nkLambdaKinds:
+        result = c.semInferredLambda(c, m.bindings, arg)
+      elif arg.kind != nkSym:
+        return nil
+      elif arg.sym.kind in {skMacro, skTemplate}:
+        return nil
+      else:
+        if arg.sym.ast == nil:
+          return nil
+        let inferred = c.semGenerateInstance(c, arg.sym, m.bindings, arg.info)
+        result = newSymNode(inferred, arg.info)
+      arg = result
+      r = typeRel(m, f, arg.typ)
 
   case r
   of isConvertible:
@@ -2230,23 +2236,15 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
       result = arg
     else:
       result = implicitConv(nkHiddenStdConv, f, arg, m, c)
-  of isInferred, isInferredConvertible:
-    if arg.kind in {nkProcDef, nkFuncDef, nkIteratorDef} + nkLambdaKinds:
-      result = c.semInferredLambda(c, m.bindings, arg)
-    elif arg.kind != nkSym:
-      return nil
-    elif arg.sym.kind in {skMacro, skTemplate}:
-      return nil
-    else:
-      if arg.sym.ast == nil:
-        return nil
-      let inferred = c.semGenerateInstance(c, arg.sym, m.bindings, arg.info)
-      result = newSymNode(inferred, arg.info)
-    if r == isInferredConvertible:
-      inc(m.convMatches)
-      result = implicitConv(nkHiddenStdConv, f, result, m, c)
-    else:
-      inc(m.genericMatches)
+  of isInferred:
+    # result should be set in above while loop:
+    assert result != nil
+    inc(m.genericMatches)
+  of isInferredConvertible:
+    # result should be set in above while loop:
+    assert result != nil
+    inc(m.convMatches)
+    result = implicitConv(nkHiddenStdConv, f, result, m, c)
   of isGeneric:
     inc(m.genericMatches)
     if arg.typ == nil:
@@ -2260,8 +2258,10 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
     else:
       result = arg
   of isBothMetaConvertible:
-    # This is the result for the 101th time.
-    result = nil
+    # result should be set in above while loop:
+    assert result != nil
+    inc(m.convMatches)
+    result = arg
   of isFromIntLit:
     # too lazy to introduce another ``*matches`` field, so we conflate
     # ``isIntConv`` and ``isIntLit`` here:
diff --git a/tests/concepts/tconcepts_issues.nim b/tests/concepts/tconcepts_issues.nim
index 1d5e415dd..d6c8674fd 100644
--- a/tests/concepts/tconcepts_issues.nim
+++ b/tests/concepts/tconcepts_issues.nim
@@ -510,7 +510,7 @@ proc depthOf*[V](orderType: typedesc[BreadthOrder], tree: AnyTree[V], root, goal
   if root == goal:
     return 0
   var order = init[LevelNode[V]](orderType)
-  order.expand(tree, root, (leaf) => (1, leaf))
+  order.expand(tree, root, (leaf) => (1.uint, leaf))
   while order.hasNext():
     let depthNode: LevelNode[V] = order.popNext()
     if depthNode.node == goal:
diff --git a/tests/errmsgs/t16654.nim b/tests/errmsgs/t16654.nim
index 749707c06..b2b57619b 100644
--- a/tests/errmsgs/t16654.nim
+++ b/tests/errmsgs/t16654.nim
@@ -1,6 +1,6 @@
 discard """
   cmd: "nim check $options $file"
-  errormsg: "type mismatch: got <int> but expected 'float'"
+  errormsg: "type mismatch: got <int literal(1), proc (r: GenericParam): auto>"
 """
 
 when true: # bug #16654
diff --git a/tests/misc/t12869.nim b/tests/misc/t12869.nim
index 731a4e95e..054e28a03 100644
--- a/tests/misc/t12869.nim
+++ b/tests/misc/t12869.nim
@@ -1,5 +1,5 @@
 discard """
-  errormsg: "type mismatch: got <bool> but expected 'int'"
+  errormsg: "type mismatch: got <openArray[int], proc (x: GenericParam, y: GenericParam): auto, SortOrder>"
   line: 12
 """
 
diff --git a/tests/proc/tinferlambdareturn.nim b/tests/proc/tinferlambdareturn.nim
new file mode 100644
index 000000000..e9e592871
--- /dev/null
+++ b/tests/proc/tinferlambdareturn.nim
@@ -0,0 +1,36 @@
+import std/[sugar, sequtils]
+
+block: # issue #23200
+  proc dosomething(iter: int -> (iterator: int)) =
+    discard
+  proc dosomething(iter: int -> seq[int]) =
+    discard
+  proc makeSeq(x: int): seq[int] =
+    @[x]
+  # Works fine with 1.6.12 and 1.6.14
+  dosomething(makeSeq)
+  # Works with 1.6.12, fails with 1.6.14
+  dosomething((y) => makeSeq(y))
+  dosomething(proc (y: auto): auto = makeSeq(y))
+  proc foo(y: auto): auto = makeSeq(y)
+  dosomething(foo)
+
+block: # issue #18866
+  proc somefn[T](list: openarray[T], op: proc (v: T): float) =
+    discard op(list[0])
+
+  type TimeD = object
+    year:  Natural
+    month: 1..12
+    day:   1..31
+
+  doAssert not compiles(@[TimeD()].somefn(proc (v: auto): auto =
+    v
+  ))
+  @[TimeD()].somefn(proc (v: auto): auto =
+    v.year.float
+  )
+  proc foo(v: auto): auto = v
+  doAssert not compiles(@[TimeD()].somefn(foo))
+  proc bar(v: auto): auto = v.year.float
+  @[TimeD()].somefn(bar)
diff --git a/tests/stdlib/tsugar.nim b/tests/stdlib/tsugar.nim
index b9cbdd3e3..2ea96cfbb 100644
--- a/tests/stdlib/tsugar.nim
+++ b/tests/stdlib/tsugar.nim
@@ -295,7 +295,8 @@ template main() =
       for i in 0..5:
         xs.add(i)
 
-      xs.apply(d => ys.add(d))
+      xs.apply(proc (d: auto) = ys.add(d))
+      # ^ can be turned into d => ys.add(d) when we can infer void return type, #16906
       doAssert ys == @[0, 1, 2, 3, 4, 5]
 
     test()
diff --git a/tests/types/t15836.nim b/tests/types/t15836.nim
index 9c0c26dec..27d3ad0d0 100644
--- a/tests/types/t15836.nim
+++ b/tests/types/t15836.nim
@@ -1,5 +1,5 @@
 discard """
-  errormsg: "type mismatch: got <string> but expected 'int'"
+  errormsg: "type mismatch: got <int literal(1), proc (a: GenericParam): auto>"
   line: 11
 """ 
 
diff --git a/tests/types/t15836_2.nim b/tests/types/t15836_2.nim
index 9afef416a..6a16e2d22 100644
--- a/tests/types/t15836_2.nim
+++ b/tests/types/t15836_2.nim
@@ -1,8 +1,3 @@
-
-discard """
-  action: "compile"
-  disabled: true
-"""
 import std/sugar
 
 type Tensor[T] = object