summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2019-07-17 16:01:44 +0200
committerGitHub <noreply@github.com>2019-07-17 16:01:44 +0200
commite11494f1cf46052d9b81d0f3d799b57b2ebe04f2 (patch)
treef8ca697e35af77375681171f1e288d88f3240c3c
parent326860e84c6abdafbf5b5aef49a9f4f59d66162b (diff)
parent063ae96a66502484d2d1ec841b84cb37953c4adb (diff)
downloadNim-e11494f1cf46052d9b81d0f3d799b57b2ebe04f2.tar.gz
Merge pull request #11680 from timotheecour/pr_fix_sigmatch_errmsg
fixes #8305; fixes #7808; fixes #10285; fixes #11061 + other bugs with type mismatch error msgs
-rw-r--r--compiler/semcall.nim62
-rw-r--r--compiler/sigmatch.nim57
-rw-r--r--tests/concepts/t3330.nim42
-rw-r--r--tests/concepts/texplain.nim126
-rw-r--r--tests/destructor/tdont_return_unowned_from_owned.nim28
-rw-r--r--tests/errmsgs/t8434.nim2
-rw-r--r--tests/errmsgs/tdetailed_position.nim2
-rw-r--r--tests/errmsgs/tgcsafety.nim2
-rw-r--r--tests/errmsgs/tsigmatch.nim172
-rw-r--r--tests/errmsgs/tunknown_named_parameter.nim4
-rw-r--r--tests/errmsgs/twrong_at_operator.nim10
-rw-r--r--tests/typerel/t7600_1.nim5
-rw-r--r--tests/typerel/t7600_2.nim5
-rw-r--r--tests/varres/tprevent_forloopvar_mutations.nim6
14 files changed, 396 insertions, 127 deletions
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 232a350b8..805a29303 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -107,7 +107,6 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
       elif errorsEnabled or z.diagnosticsEnabled:
         errors.add(CandidateError(
           sym: sym,
-          unmatchedVarParam: int z.mutabilityProblem,
           firstMismatch: z.firstMismatch,
           diagnostics: z.diagnostics))
     else:
@@ -173,14 +172,14 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
   var filterOnlyFirst = false
   if optShowAllMismatches notin c.config.globalOptions:
     for err in errors:
-      if err.firstMismatch > 1:
+      if err.firstMismatch.arg > 1:
         filterOnlyFirst = true
         break
 
   var candidates = ""
   var skipped = 0
   for err in errors:
-    if filterOnlyFirst and err.firstMismatch == 1:
+    if filterOnlyFirst and err.firstMismatch.arg == 1:
       inc skipped
       continue
     if err.sym.kind in routineKinds and err.sym.ast != nil:
@@ -189,34 +188,35 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
     else:
       add(candidates, getProcHeader(c.config, err.sym, prefer))
     add(candidates, "\n")
-    if err.firstMismatch != 0 and n.len > 1:
-      let cond = n.len > 2
-      if cond:
-        candidates.add("  first type mismatch at position: " & $abs(err.firstMismatch))
-        if err.firstMismatch >= 0: candidates.add("\n  required type: ")
-        else: candidates.add("\n  unknown named parameter: " & $n[-err.firstMismatch][0])
-      var wanted, got: PType = nil
-      if err.firstMismatch < 0:
-        discard
-      elif err.firstMismatch < err.sym.typ.len:
-        wanted = err.sym.typ.sons[err.firstMismatch]
-        if cond: candidates.add typeToString(wanted)
-      else:
-        if cond: candidates.add "none"
-      if err.firstMismatch > 0 and err.firstMismatch < n.len:
-        if cond:
-          candidates.add "\n  but expression '"
-          candidates.add renderTree(n[err.firstMismatch])
+    let nArg = if err.firstMismatch.arg < n.len: n[err.firstMismatch.arg] else: nil
+    let nameParam = if err.firstMismatch.formal != nil: err.firstMismatch.formal.name.s else: ""
+    if n.len > 1:
+      candidates.add("  first type mismatch at position: " & $err.firstMismatch.arg)
+      # candidates.add "\n  reason: " & $err.firstMismatch.kind # for debugging
+      case err.firstMismatch.kind
+      of kUnknownNamedParam: candidates.add("\n  unknown named parameter: " & $nArg[0])
+      of kAlreadyGiven: candidates.add("\n  named param already provided: " & $nArg[0])
+      of kExtraArg: candidates.add("\n  extra argument given")
+      of kMissingParam: candidates.add("\n  missing parameter: " & nameParam)
+      of kTypeMismatch, kVarNeeded:
+        doAssert nArg != nil
+        var wanted = err.firstMismatch.formal.typ
+        doAssert err.firstMismatch.formal != nil
+        candidates.add("\n  required type for " & nameParam &  ": ")
+        candidates.add typeToString(wanted)
+        candidates.add "\n  but expression '"
+        if err.firstMismatch.kind == kVarNeeded:
+          candidates.add renderNotLValue(nArg)
+          candidates.add "' is immutable, not 'var'"
+        else:
+          candidates.add renderTree(nArg)
           candidates.add "' is of type: "
-        got = n[err.firstMismatch].typ
-        if cond: candidates.add typeToString(got)
-      if wanted != nil and got != nil:
-        effectProblem(wanted, got, candidates)
-      if cond: candidates.add "\n"
-    if err.unmatchedVarParam != 0 and err.unmatchedVarParam < n.len:
-      candidates.add("  for a 'var' type a variable needs to be passed, but '" &
-                      renderNotLValue(n[err.unmatchedVarParam]) &
-                      "' is immutable\n")
+          var got = nArg.typ
+          candidates.add typeToString(got)
+          doAssert wanted != nil
+          if got != nil: effectProblem(wanted, got, candidates)
+      of kUnknown: internalAssert(c.config, false)
+      candidates.add "\n"
     for diag in err.diagnostics:
       candidates.add(diag & "\n")
   if skipped > 0:
@@ -260,7 +260,7 @@ proc bracketNotFoundError(c: PContext; n: PNode) =
   while symx != nil:
     if symx.kind in routineKinds:
       errors.add(CandidateError(sym: symx,
-                                unmatchedVarParam: 0, firstMismatch: 0,
+                                firstMismatch: MismatchInfo(),
                                 diagnostics: @[],
                                 enabled: false))
     symx = nextOverloadIter(o, c, headSymbol)
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 655ee83f0..4a6bf66e7 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -19,12 +19,22 @@ when (defined(booting) or defined(nimsuggest)) and not defined(leanCompiler):
   import docgen
 
 type
+  MismatchKind* = enum
+    kUnknown, kAlreadyGiven, kUnknownNamedParam, kTypeMismatch, kVarNeeded,
+    kMissingParam, kExtraArg
+
+  MismatchInfo* = object
+    kind*: MismatchKind # reason for mismatch
+    arg*: int           # position of provided arguments that mismatches
+    formal*: PSym       # parameter that mismatches against provided argument
+                        # its position can differ from `arg` because of varargs
+
   TCandidateState* = enum
     csEmpty, csMatch, csNoMatch
 
   CandidateError* = object
     sym*: PSym
-    unmatchedVarParam*, firstMismatch*: int
+    firstMismatch*: MismatchInfo
     diagnostics*: seq[string]
     enabled*: bool
 
@@ -56,7 +66,6 @@ type
                              # a distrinct type
     typedescMatched*: bool
     isNoCall*: bool          # misused for generic type instantiations C[T]
-    mutabilityProblem*: uint8 # tyVar mismatch
     inferredTypes: seq[PType] # inferred types during the current signature
                               # matching. they will be reset if the matching
                               # is not successful. may replace the bindings
@@ -70,8 +79,7 @@ type
                               # triggered with an idetools command in the
                               # future.
     inheritancePenalty: int   # to prefer closest father object type
-    firstMismatch*: int       # position of the first type mismatch for
-                              # better error messages
+    firstMismatch*: MismatchInfo # mismatch info for better error messages
     diagnosticsEnabled*: bool
 
   TTypeRelFlag* = enum
@@ -112,6 +120,7 @@ proc initCandidateAux(ctx: PContext,
   c.intConvMatches = 0
   c.genericMatches = 0
   c.state = csEmpty
+  c.firstMismatch = MismatchInfo()
   c.callee = callee
   c.call = nil
   c.baseTypeMatch = false
@@ -2280,6 +2289,17 @@ template isVarargsUntyped(x): untyped =
 
 proc matchesAux(c: PContext, n, nOrig: PNode,
                 m: var TCandidate, marker: var IntSet) =
+  var
+    a = 1 # iterates over the actual given arguments
+    f = if m.callee.kind != tyGenericBody: 1
+        else: 0 # iterates over formal parameters
+    arg: PNode # current prepared argument
+    formal: PSym # current routine parameter
+
+  defer:
+    m.firstMismatch.arg = a
+    m.firstMismatch.formal = formal
+
   template checkConstraint(n: untyped) {.dirty.} =
     if not formal.constraint.isNil:
       if matchNodeKinds(formal.constraint, n):
@@ -2294,28 +2314,21 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
       if argConverter.kind == nkHiddenCallConv:
         if argConverter.typ.kind != tyVar:
           m.state = csNoMatch
-          m.mutabilityProblem = uint8(f-1)
+          m.firstMismatch.kind = kVarNeeded
           return
       elif not n.isLValue:
         m.state = csNoMatch
-        m.mutabilityProblem = uint8(f-1)
+        m.firstMismatch.kind = kVarNeeded
         return
 
-  var
-    # iterates over formal parameters
-    f = if m.callee.kind != tyGenericBody: 1
-        else: 0
-    # iterates over the actual given arguments
-    a = 1
-    arg: PNode # current prepared argument
-
   m.state = csMatch # until proven otherwise
+  m.firstMismatch = MismatchInfo()
   m.call = newNodeI(n.kind, n.info)
   m.call.typ = base(m.callee) # may be nil
   var formalLen = m.callee.n.len
   addSon(m.call, copyTree(n.sons[0]))
   var container: PNode = nil # constructed container
-  var formal: PSym = if formalLen > 1: m.callee.n.sons[1].sym else: nil
+  formal = if formalLen > 1: m.callee.n.sons[1].sym else: nil
 
   while a < n.len:
     if a >= formalLen-1 and f < formalLen and m.callee.n[f].typ.isVarargsUntyped:
@@ -2336,20 +2349,20 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
         addSon(container, n.sons[a])
     elif n.sons[a].kind == nkExprEqExpr:
       # named param
+      m.firstMismatch.kind = kUnknownNamedParam
       # check if m.callee has such a param:
       prepareNamedParam(n.sons[a], c)
       if n.sons[a].sons[0].kind != nkIdent:
         localError(c.config, n.sons[a].info, "named parameter has to be an identifier")
         m.state = csNoMatch
-        m.firstMismatch = -a
         return
       formal = getSymFromList(m.callee.n, n.sons[a].sons[0].ident, 1)
       if formal == nil:
         # no error message!
         m.state = csNoMatch
-        m.firstMismatch = -a
         return
       if containsOrIncl(marker, formal.position):
+        m.firstMismatch.kind = kAlreadyGiven
         # already in namedParams, so no match
         # we used to produce 'errCannotBindXTwice' here but see
         # bug #3836 of why that is not sound (other overload with
@@ -2363,9 +2376,9 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
       n.sons[a].typ = n.sons[a].sons[1].typ
       arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
                                 n.sons[a].sons[1], n.sons[a].sons[1])
+      m.firstMismatch.kind = kTypeMismatch
       if arg == nil:
         m.state = csNoMatch
-        m.firstMismatch = a
         return
       checkConstraint(n.sons[a].sons[1])
       if m.baseTypeMatch:
@@ -2392,6 +2405,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           else:
             addSon(m.call, copyTree(n.sons[a]))
         elif formal != nil and formal.typ.kind == tyVarargs:
+          m.firstMismatch.kind = kTypeMismatch
           # beware of the side-effects in 'prepareOperand'! So only do it for
           # varargs matching. See tests/metatype/tstatic_overloading.
           m.baseTypeMatch = false
@@ -2408,6 +2422,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
             m.state = csNoMatch
             return
         else:
+          m.firstMismatch.kind = kExtraArg
           m.state = csNoMatch
           return
       else:
@@ -2415,7 +2430,9 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           internalError(c.config, n.sons[a].info, "matches")
           return
         formal = m.callee.n.sons[f].sym
+        m.firstMismatch.kind = kTypeMismatch
         if containsOrIncl(marker, formal.position) and container.isNil:
+          m.firstMismatch.kind = kAlreadyGiven
           # already in namedParams: (see above remark)
           when false: localError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
           m.state = csNoMatch
@@ -2436,7 +2453,6 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
                                     n.sons[a], nOrig.sons[a])
           if arg == nil:
             m.state = csNoMatch
-            m.firstMismatch = f
             return
           if m.baseTypeMatch:
             assert formal.typ.kind == tyVarargs
@@ -2510,7 +2526,8 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
         else:
           # no default value
           m.state = csNoMatch
-          m.firstMismatch = f
+          m.firstMismatch.kind = kMissingParam
+          m.firstMismatch.formal = formal
           break
       else:
         if formal.ast.kind == nkEmpty:
diff --git a/tests/concepts/t3330.nim b/tests/concepts/t3330.nim
index a1ad96f2b..6bf52f3aa 100644
--- a/tests/concepts/t3330.nim
+++ b/tests/concepts/t3330.nim
@@ -1,49 +1,63 @@
 discard """
 errormsg: "type mismatch: got <Bar[system.int]>"
-disabled: "true"
+disabled: "32bit"
 nimout: '''
-t3330.nim(63, 4) Error: type mismatch: got <Bar[system.int]>
+t3330.nim(78, 4) Error: type mismatch: got <Bar[system.int]>
 but expected one of:
 proc test(foo: Foo[int])
-t3330.nim(48, 8) Hint: Non-matching candidates for add(k, string, T)
+  first type mismatch at position: 1
+  required type for foo: Foo[int]
+  but expression 'bar' is of type: Bar[system.int]
+t3330.nim(63, 8) Hint: Non-matching candidates for add(k, string, T)
 proc add[T](x: var seq[T]; y: openArray[T])
   first type mismatch at position: 1
-  required type: var seq[T]
+  required type for x: var seq[T]
   but expression 'k' is of type: Alias
 proc add(result: var string; x: float)
   first type mismatch at position: 1
-  required type: var string
+  required type for result: var string
   but expression 'k' is of type: Alias
 proc add(x: var string; y: string)
   first type mismatch at position: 1
-  required type: var string
+  required type for x: var string
   but expression 'k' is of type: Alias
 proc add(x: var string; y: cstring)
   first type mismatch at position: 1
-  required type: var string
+  required type for x: var string
   but expression 'k' is of type: Alias
 proc add[T](x: var seq[T]; y: T)
   first type mismatch at position: 1
-  required type: var seq[T]
+  required type for x: var seq[T]
   but expression 'k' is of type: Alias
 proc add(result: var string; x: int64)
   first type mismatch at position: 1
-  required type: var string
+  required type for result: var string
   but expression 'k' is of type: Alias
 proc add(x: var string; y: char)
   first type mismatch at position: 1
-  required type: var string
+  required type for x: var string
   but expression 'k' is of type: Alias
 
-t3330.nim(48, 8) template/generic instantiation of `add` from here
-t3330.nim(55, 6) Foo: 'bar.value' cannot be assigned to
-t3330.nim(48, 8) template/generic instantiation of `add` from here
-t3330.nim(56, 6) Foo: 'bar.x' cannot be assigned to
+t3330.nim(63, 8) template/generic instantiation of `add` from here
+t3330.nim(70, 6) Foo: 'bar.value' cannot be assigned to
+t3330.nim(63, 8) template/generic instantiation of `add` from here
+t3330.nim(71, 6) Foo: 'bar.x' cannot be assigned to
 
 expression: test(bar)'''
 """
 
+# Note: currently disabled on 32bit because the candidates are presented in
+# different order on travis with `NIM_COMPILE_TO_CPP=false CPU=i386`;
+# a possible fix would be to sort the candidates by proc signature or
+# declaration location
+
+
+
+
+
+
 
+## line 60
 type
   Foo[T] = concept k
     add(k, string, T)
diff --git a/tests/concepts/texplain.nim b/tests/concepts/texplain.nim
index 4ec848732..f3d70320f 100644
--- a/tests/concepts/texplain.nim
+++ b/tests/concepts/texplain.nim
@@ -2,69 +2,101 @@ discard """
   cmd: "nim c --verbosity:0 --colors:off $file"
   nimout: '''
 Hint: texplain [Processing]
-texplain.nim(118, 10) Hint: Non-matching candidates for e(y)
+texplain.nim(158, 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(121, 7) Hint: Non-matching candidates for e(10)
+texplain.nim(161, 7) Hint: Non-matching candidates for e(10)
 proc e(o: ExplainedConcept): int
-texplain.nim(84, 6) ExplainedConcept: undeclared field: 'foo'
-texplain.nim(84, 6) ExplainedConcept: undeclared field: '.'
-texplain.nim(84, 6) ExplainedConcept: expression '.' cannot be called
-texplain.nim(84, 5) ExplainedConcept: concept predicate failed
-texplain.nim(85, 6) ExplainedConcept: undeclared field: 'bar'
-texplain.nim(85, 6) ExplainedConcept: undeclared field: '.'
-texplain.nim(85, 6) ExplainedConcept: expression '.' cannot be called
-texplain.nim(84, 5) ExplainedConcept: concept predicate failed
-
-texplain.nim(124, 10) Hint: Non-matching candidates for e(10)
+  first type mismatch at position: 1
+  required type for o: ExplainedConcept
+  but expression '10' is of type: int literal(10)
+texplain.nim(124, 6) ExplainedConcept: undeclared field: 'foo'
+texplain.nim(124, 6) ExplainedConcept: undeclared field: '.'
+texplain.nim(124, 6) ExplainedConcept: expression '.' cannot be called
+texplain.nim(124, 5) ExplainedConcept: concept predicate failed
+texplain.nim(125, 6) ExplainedConcept: undeclared field: 'bar'
+texplain.nim(125, 6) ExplainedConcept: undeclared field: '.'
+texplain.nim(125, 6) ExplainedConcept: expression '.' cannot be called
+texplain.nim(124, 5) ExplainedConcept: concept predicate failed
+
+texplain.nim(164, 10) Hint: Non-matching candidates for e(10)
 proc e(o: ExplainedConcept): int
-texplain.nim(84, 6) ExplainedConcept: undeclared field: 'foo'
-texplain.nim(84, 6) ExplainedConcept: undeclared field: '.'
-texplain.nim(84, 6) ExplainedConcept: expression '.' cannot be called
-texplain.nim(84, 5) ExplainedConcept: concept predicate failed
-texplain.nim(85, 6) ExplainedConcept: undeclared field: 'bar'
-texplain.nim(85, 6) ExplainedConcept: undeclared field: '.'
-texplain.nim(85, 6) ExplainedConcept: expression '.' cannot be called
-texplain.nim(84, 5) ExplainedConcept: concept predicate failed
-
-texplain.nim(128, 20) Error: type mismatch: got <NonMatchingType>
+  first type mismatch at position: 1
+  required type for o: ExplainedConcept
+  but expression '10' is of type: int literal(10)
+texplain.nim(124, 6) ExplainedConcept: undeclared field: 'foo'
+texplain.nim(124, 6) ExplainedConcept: undeclared field: '.'
+texplain.nim(124, 6) ExplainedConcept: expression '.' cannot be called
+texplain.nim(124, 5) ExplainedConcept: concept predicate failed
+texplain.nim(125, 6) ExplainedConcept: undeclared field: 'bar'
+texplain.nim(125, 6) ExplainedConcept: undeclared field: '.'
+texplain.nim(125, 6) ExplainedConcept: expression '.' cannot be called
+texplain.nim(124, 5) ExplainedConcept: concept predicate failed
+
+texplain.nim(168, 20) Error: type mismatch: got <NonMatchingType>
 but expected one of:
 proc e(o: ExplainedConcept): int
-texplain.nim(128, 9) template/generic instantiation of `assert` from here
-texplain.nim(84, 5) ExplainedConcept: concept predicate failed
+  first type mismatch at position: 1
+  required type for o: ExplainedConcept
+  but expression 'n' is of type: NonMatchingType
+texplain.nim(168, 9) template/generic instantiation of `assert` from here
+texplain.nim(124, 5) ExplainedConcept: concept predicate failed
 proc e(i: int): int
+  first type mismatch at position: 1
+  required type for i: int
+  but expression 'n' is of type: NonMatchingType
 
 expression: e(n)
-texplain.nim(129, 20) Error: type mismatch: got <NonMatchingType>
+texplain.nim(169, 20) Error: type mismatch: got <NonMatchingType>
 but expected one of:
 proc r(o: RegularConcept): int
-texplain.nim(129, 9) template/generic instantiation of `assert` from here
-texplain.nim(88, 5) RegularConcept: concept predicate failed
+  first type mismatch at position: 1
+  required type for o: RegularConcept
+  but expression 'n' is of type: NonMatchingType
+texplain.nim(169, 9) template/generic instantiation of `assert` from here
+texplain.nim(128, 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
 proc r(i: string): int
+  first type mismatch at position: 1
+  required type for i: string
+  but expression 'n' is of type: NonMatchingType
 
 expression: r(n)
-texplain.nim(130, 20) Hint: Non-matching candidates for r(y)
+texplain.nim(170, 20) Hint: Non-matching candidates for r(y)
 proc r[T](a: SomeNumber; b: T; c: auto)
+  first type mismatch at position: 1
+  required type for a: SomeNumber
+  but expression 'y' is of type: MatchingType
 proc r(i: string): int
+  first type mismatch at position: 1
+  required type for i: string
+  but expression 'y' is of type: MatchingType
 
-texplain.nim(138, 2) Error: type mismatch: got <MatchingType>
+texplain.nim(178, 2) Error: type mismatch: got <MatchingType>
 but expected one of:
 proc f(o: NestedConcept)
-texplain.nim(88, 6) RegularConcept: undeclared field: 'foo'
-texplain.nim(88, 6) RegularConcept: undeclared field: '.'
-texplain.nim(88, 6) RegularConcept: expression '.' cannot be called
-texplain.nim(88, 5) RegularConcept: concept predicate failed
-texplain.nim(89, 6) RegularConcept: undeclared field: 'bar'
-texplain.nim(89, 6) RegularConcept: undeclared field: '.'
-texplain.nim(89, 6) RegularConcept: expression '.' cannot be called
-texplain.nim(88, 5) RegularConcept: concept predicate failed
-texplain.nim(92, 5) NestedConcept: concept predicate failed
-
-expression: f(y)
-'''
+  first type mismatch at position: 1
+  required type for o: NestedConcept
+  but expression 'y' is of type: MatchingType
+texplain.nim(128, 6) RegularConcept: undeclared field: 'foo'
+texplain.nim(128, 6) RegularConcept: undeclared field: '.'
+texplain.nim(128, 6) RegularConcept: expression '.' cannot be called
+texplain.nim(128, 5) RegularConcept: concept predicate failed
+texplain.nim(129, 6) RegularConcept: undeclared field: 'bar'
+texplain.nim(129, 6) RegularConcept: undeclared field: '.'
+texplain.nim(129, 6) RegularConcept: expression '.' cannot be called
+texplain.nim(128, 5) RegularConcept: concept predicate failed
+texplain.nim(132, 5) NestedConcept: concept predicate failed
+
+expression: f(y)'''
   errormsg: "type mismatch: got <MatchingType>"
-  line: 138
+  line: 178
 
   disabled: 32bit
 """
@@ -77,7 +109,15 @@ expression: f(y)
 
 
 
-# line 80 HERE
+
+
+
+
+
+
+
+
+# line 120 HERE
 
 type
   ExplainedConcept {.explain.} = concept o
diff --git a/tests/destructor/tdont_return_unowned_from_owned.nim b/tests/destructor/tdont_return_unowned_from_owned.nim
index 5794dec1d..a726960c6 100644
--- a/tests/destructor/tdont_return_unowned_from_owned.nim
+++ b/tests/destructor/tdont_return_unowned_from_owned.nim
@@ -1,21 +1,33 @@
 discard """
   cmd: "nim check --newruntime --hints:off $file"
-  nimout: '''tdont_return_unowned_from_owned.nim(24, 10) Error: cannot return an owned pointer as an unowned pointer; use 'owned(Obj)' as the return type
-tdont_return_unowned_from_owned.nim(27, 10) Error: cannot return an owned pointer as an unowned pointer; use 'owned(Obj)' as the return type
-tdont_return_unowned_from_owned.nim(30, 6) Error: type mismatch: got <Obj>
+  nimout: '''tdont_return_unowned_from_owned.nim(36, 10) Error: cannot return an owned pointer as an unowned pointer; use 'owned(Obj)' as the return type
+tdont_return_unowned_from_owned.nim(39, 10) Error: cannot return an owned pointer as an unowned pointer; use 'owned(Obj)' as the return type
+tdont_return_unowned_from_owned.nim(42, 6) Error: type mismatch: got <Obj>
 but expected one of:
 proc new[T](a: var ref T; finalizer: proc (x: ref T) {.nimcall.})
+  first type mismatch at position: 2
+  missing parameter: finalizer
 2 other mismatching symbols have been suppressed; compile with --showAllMismatches:on to see them
 
 expression: new(result)
-tdont_return_unowned_from_owned.nim(30, 6) Error: illformed AST:
-tdont_return_unowned_from_owned.nim(38, 13) Error: assignment produces a dangling ref: the unowned ref lives longer than the owned ref
-tdont_return_unowned_from_owned.nim(39, 13) Error: assignment produces a dangling ref: the unowned ref lives longer than the owned ref
-tdont_return_unowned_from_owned.nim(43, 10) Error: cannot return an owned pointer as an unowned pointer; use 'owned(RootRef)' as the return type
+tdont_return_unowned_from_owned.nim(42, 6) Error: illformed AST:
+tdont_return_unowned_from_owned.nim(50, 13) Error: assignment produces a dangling ref: the unowned ref lives longer than the owned ref
+tdont_return_unowned_from_owned.nim(51, 13) Error: assignment produces a dangling ref: the unowned ref lives longer than the owned ref
+tdont_return_unowned_from_owned.nim(55, 10) Error: cannot return an owned pointer as an unowned pointer; use 'owned(RootRef)' as the return type
 '''
   errormsg: "cannot return an owned pointer as an unowned pointer; use 'owned(RootRef)' as the return type"
-  line: 43
+  line: 55
 """
+
+
+
+
+
+
+
+
+
+## line 30
 # bug #11073
 type
   Obj = ref object
diff --git a/tests/errmsgs/t8434.nim b/tests/errmsgs/t8434.nim
index b37468111..ada38e9c0 100644
--- a/tests/errmsgs/t8434.nim
+++ b/tests/errmsgs/t8434.nim
@@ -4,7 +4,7 @@ discard """
 proc fun0[T1: int | float |
     object | array | seq](a1: T1; a2: int)
   first type mismatch at position: 1
-  required type: T1: int or float or object or array or seq[T]
+  required type for a1: T1: int or float or object or array or seq[T]
   but expression 'byte(1)' is of type: byte
 
 expression: fun0(byte(1), 0)
diff --git a/tests/errmsgs/tdetailed_position.nim b/tests/errmsgs/tdetailed_position.nim
index ce5b18bbd..ecece7972 100644
--- a/tests/errmsgs/tdetailed_position.nim
+++ b/tests/errmsgs/tdetailed_position.nim
@@ -6,7 +6,7 @@ nimout: '''
 but expected one of:
 proc main(a, b, c: string)
   first type mismatch at position: 1
-  required type: string
+  required type for a: string
   but expression '1' is of type: int literal(1)
 
 expression: main(1, 2, 3)
diff --git a/tests/errmsgs/tgcsafety.nim b/tests/errmsgs/tgcsafety.nim
index 0ae60f200..e6a62204e 100644
--- a/tests/errmsgs/tgcsafety.nim
+++ b/tests/errmsgs/tgcsafety.nim
@@ -8,7 +8,7 @@ proc serve(server: AsyncHttpServer; port: Port;
           callback: proc (request: Request): Future[void] {.closure, gcsafe.};
           address = ""): owned(Future[void])
   first type mismatch at position: 3
-  required type: proc (request: Request): Future[system.void]{.closure, gcsafe.}
+  required type for callback: proc (request: Request): Future[system.void]{.closure, gcsafe.}
   but expression 'cb' is of type: proc (req: Request): Future[system.void]{.locks: <unknown>.}
   This expression is not GC-safe. Annotate the proc with {.gcsafe.} to get extended error information.
 
diff --git a/tests/errmsgs/tsigmatch.nim b/tests/errmsgs/tsigmatch.nim
new file mode 100644
index 000000000..42a98a891
--- /dev/null
+++ b/tests/errmsgs/tsigmatch.nim
@@ -0,0 +1,172 @@
+discard """
+  cmd: "nim check --showAllMismatches:on --hints:off $file"
+  nimout: '''
+tsigmatch.nim(111, 4) Error: type mismatch: got <A, string>
+but expected one of:
+proc f(b: B)
+  first type mismatch at position: 1
+  required type for b: B
+  but expression 'A()' is of type: A
+proc f(a: A)
+  first type mismatch at position: 2
+  extra argument given
+
+expression: f(A(), "extra")
+tsigmatch.nim(125, 6) Error: type mismatch: got <tuple of (string, proc (){.gcsafe, locks: 0.})>
+but expected one of:
+proc foo(x: (string, proc ()))
+  first type mismatch at position: 1
+  required type for x: tuple of (string, proc (){.closure.})
+  but expression '("foobar", proc () = echo(["Hello!"]))' is of type: tuple of (string, proc (){.gcsafe, locks: 0.})
+
+expression: foo(("foobar", proc () = echo(["Hello!"])))
+tsigmatch.nim(132, 11) Error: type mismatch: got <proc (s: string): string{.noSideEffect, gcsafe, locks: 0.}>
+but expected one of:
+proc foo[T, S](op: proc (x: T): S {.cdecl.}): auto
+  first type mismatch at position: 1
+  required type for op: proc (x: T): S{.cdecl.}
+  but expression 'fun' is of type: proc (s: string): string{.noSideEffect, gcsafe, locks: 0.}
+proc foo[T, S](op: proc (x: T): S {.safecall.}): auto
+  first type mismatch at position: 1
+  required type for op: proc (x: T): S{.safecall.}
+  but expression 'fun' is of type: proc (s: string): string{.noSideEffect, gcsafe, locks: 0.}
+
+expression: foo(fun)
+tsigmatch.nim(143, 13) Error: type mismatch: got <array[0..0, proc (x: int){.gcsafe, locks: 0.}]>
+but expected one of:
+proc takesFuncs(fs: openArray[proc (x: int) {.gcsafe, locks: 0.}])
+  first type mismatch at position: 1
+  required type for fs: openarray[proc (x: int){.closure, gcsafe, locks: 0.}]
+  but expression '[proc (x: int) {.gcsafe, locks: 0.} = echo [x]]' is of type: array[0..0, proc (x: int){.gcsafe, locks: 0.}]
+
+expression: takesFuncs([proc (x: int) {.gcsafe, locks: 0.} = echo [x]])
+tsigmatch.nim(149, 4) Error: type mismatch: got <int literal(10), a0: int literal(5), string>
+but expected one of:
+proc f(a0: uint8; b: string)
+  first type mismatch at position: 2
+  named param already provided: a0
+
+expression: f(10, a0 = 5, "")
+tsigmatch.nim(156, 4) Error: type mismatch: got <string, string, string, string, string, float64, string>
+but expected one of:
+proc f(a1: int)
+  first type mismatch at position: 1
+  required type for a1: int
+  but expression '"asdf"' is of type: string
+proc f(a1: string; a2: varargs[string]; a3: float; a4: var string)
+  first type mismatch at position: 7
+  required type for a4: var string
+  but expression '"bad"' is immutable, not 'var'
+
+expression: f("asdf", "1", "2", "3", "4", 2.3, "bad")
+tsigmatch.nim(164, 4) Error: type mismatch: got <string, a0: int literal(12)>
+but expected one of:
+proc f(x: string; a0: var int)
+  first type mismatch at position: 2
+  required type for a0: var int
+  but expression 'a0 = 12' is immutable, not 'var'
+proc f(x: string; a0: string)
+  first type mismatch at position: 2
+  required type for a0: string
+  but expression 'a0 = 12' is of type: int literal(12)
+
+expression: f(foo, a0 = 12)
+tsigmatch.nim(171, 7) Error: type mismatch: got <Mystring, string>
+but expected one of:
+proc fun1(a1: MyInt; a2: Mystring)
+  first type mismatch at position: 1
+  required type for a1: MyInt
+  but expression 'default(Mystring)' is of type: Mystring
+proc fun1(a1: float; a2: Mystring)
+  first type mismatch at position: 1
+  required type for a1: float
+  but expression 'default(Mystring)' is of type: Mystring
+
+expression: fun1(default(Mystring), "asdf")
+'''
+  errormsg: "type mismatch"
+"""
+
+
+
+
+
+
+
+
+
+
+
+## line 100
+block:
+  # bug #11061 Type mismatch error "first type mismatch at" points to wrong argument/position
+  # Note: the error msg now gives correct position for mismatched argument
+  type
+    A = object of RootObj
+    B = object of A
+
+  proc f(b: B) = discard
+  proc f(a: A) = discard
+
+  f(A(), "extra")
+#[
+this one is similar but error msg was even more misleading, since the user
+would think float != float64 where in fact the issue is another param:
+first type mismatch at position: 1; required type: float; but expression 'x = 1.2' is of type: float64
+  proc f(x: string, a0 = 0, a1 = 0, a2 = 0) = discard
+  proc f(x: float, a0 = 0, a1 = 0, a2 = 0) = discard
+  f(x = float(1.2), a0 = 0, a0 = 0)
+]#
+
+block:
+  # bug #7808 Passing tuple with proc leads to confusing errors
+  # Note: the error message now shows `closure` which helps debugging the issue
+  proc foo(x: (string, proc ())) = x[1]()
+  foo(("foobar", proc () = echo("Hello!")))
+
+block:
+  # bug #8305 type mismatch error drops crucial pragma info when there's only 1 argument
+  proc fun(s: string): string {.  .} = discard
+  proc foo[T, S](op: proc (x: T): S {. cdecl .}): auto = 1
+  proc foo[T, S](op: proc (x: T): S {. safecall .}): auto = 1
+  echo foo(fun)
+
+block:
+  # bug #10285 Function signature don't match when inside seq/array/openarray
+  # Note: the error message now shows `closure` which helps debugging the issue
+  # out why it doesn't match
+  proc takesFunc(f: proc (x: int) {.gcsafe, locks: 0.}) =
+    echo "takes single Func"
+  proc takesFuncs(fs: openarray[proc (x: int) {.gcsafe, locks: 0.}]) =
+    echo "takes multiple Func"
+  takesFunc(proc (x: int) {.gcsafe, locks: 0.} = echo x)         # works
+  takesFuncs([proc (x: int) {.gcsafe, locks: 0.} = echo x])      # fails
+
+block:
+  # bug https://github.com/nim-lang/Nim/issues/11061#issuecomment-508970465
+  # better fix for removal of `errCannotBindXTwice` due to #3836
+  proc f(a0: uint8, b: string) = discard
+  f(10, a0 = 5, "")
+
+block:
+  # bug: https://github.com/nim-lang/Nim/issues/11061#issuecomment-508969796
+  # sigmatch gets confused with param/arg position after varargs
+  proc f(a1: int) = discard
+  proc f(a1: string, a2: varargs[string], a3: float, a4: var string) = discard
+  f("asdf", "1", "2", "3", "4", 2.3, "bad")
+
+block:
+  # bug: https://github.com/nim-lang/Nim/issues/11061#issuecomment-508970046
+  # err msg incorrectly said something is immutable
+  proc f(x: string, a0: var int) = discard
+  proc f(x: string, a0: string) = discard
+  var foo = ""
+  f(foo, a0 = 12)
+
+block:
+  type Mystring = string
+  type MyInt = int
+  proc fun1(a1: MyInt, a2: Mystring) = discard
+  proc fun1(a1: float, a2: Mystring) = discard
+  fun1(Mystring.default, "asdf")
+
diff --git a/tests/errmsgs/tunknown_named_parameter.nim b/tests/errmsgs/tunknown_named_parameter.nim
index 3051787ea..e9be23068 100644
--- a/tests/errmsgs/tunknown_named_parameter.nim
+++ b/tests/errmsgs/tunknown_named_parameter.nim
@@ -4,14 +4,14 @@ errormsg: "type mismatch: got <string, set[char], maxsplits: int literal(1)>"
 nimout: '''
 proc rsplit(s: string; sep: char; maxsplit: int = -1): seq[string]
   first type mismatch at position: 2
-  required type: char
+  required type for sep: char
   but expression '{':'}' is of type: set[char]
 proc rsplit(s: string; seps: set[char] = Whitespace; maxsplit: int = -1): seq[string]
   first type mismatch at position: 3
   unknown named parameter: maxsplits
 proc rsplit(s: string; sep: string; maxsplit: int = -1): seq[string]
   first type mismatch at position: 2
-  required type: string
+  required type for sep: string
   but expression '{':'}' is of type: set[char]
 
 expression: rsplit("abc:def", {':'}, maxsplits = 1)
diff --git a/tests/errmsgs/twrong_at_operator.nim b/tests/errmsgs/twrong_at_operator.nim
index 5413515cb..7ce077003 100644
--- a/tests/errmsgs/twrong_at_operator.nim
+++ b/tests/errmsgs/twrong_at_operator.nim
@@ -1,11 +1,17 @@
 discard """
 errormsg: "type mismatch: got <array[0..0, type int]>"
-line: 16
+line: 22
 nimout: '''
-twrong_at_operator.nim(16, 30) Error: type mismatch: got <array[0..0, type int]>
+twrong_at_operator.nim(22, 30) Error: type mismatch: got <array[0..0, type int]>
 but expected one of:
 proc `@`[T](a: openArray[T]): seq[T]
+  first type mismatch at position: 1
+  required type for a: openarray[T]
+  but expression '[int]' is of type: array[0..0, type int]
 proc `@`[IDX, T](a: array[IDX, T]): seq[T]
+  first type mismatch at position: 1
+  required type for a: array[IDX, T]
+  but expression '[int]' is of type: array[0..0, type int]
 
 expression: @[int]
 '''
diff --git a/tests/typerel/t7600_1.nim b/tests/typerel/t7600_1.nim
index e3a5fefa2..e9d01bd0d 100644
--- a/tests/typerel/t7600_1.nim
+++ b/tests/typerel/t7600_1.nim
@@ -1,8 +1,11 @@
 discard """
 errormsg: "type mismatch: got <Thin[system.int]>"
-nimout: '''t7600_1.nim(18, 6) Error: type mismatch: got <Thin[system.int]>
+nimout: '''t7600_1.nim(21, 6) Error: type mismatch: got <Thin[system.int]>
 but expected one of:
 proc test[T](x: Paper[T])
+  first type mismatch at position: 1
+  required type for x: Paper[test.T]
+  but expression 'tn' is of type: Thin[system.int]
 
 expression: test tn'''
 """
diff --git a/tests/typerel/t7600_2.nim b/tests/typerel/t7600_2.nim
index 7badb69cf..371707f4c 100644
--- a/tests/typerel/t7600_2.nim
+++ b/tests/typerel/t7600_2.nim
@@ -1,8 +1,11 @@
 discard """
 errormsg: "type mismatch: got <Thin>"
-nimout: '''t7600_2.nim(17, 6) Error: type mismatch: got <Thin>
+nimout: '''t7600_2.nim(20, 6) Error: type mismatch: got <Thin>
 but expected one of:
 proc test(x: Paper)
+  first type mismatch at position: 1
+  required type for x: Paper
+  but expression 'tn' is of type: Thin
 
 expression: test tn'''
 """
diff --git a/tests/varres/tprevent_forloopvar_mutations.nim b/tests/varres/tprevent_forloopvar_mutations.nim
index 43cc04f30..398191658 100644
--- a/tests/varres/tprevent_forloopvar_mutations.nim
+++ b/tests/varres/tprevent_forloopvar_mutations.nim
@@ -1,10 +1,12 @@
 discard """
   errmsg: "type mismatch: got <int>"
-  line: 15
+  line: 17
   nimout: '''type mismatch: got <int>
 but expected one of:
 proc inc[T: Ordinal | uint | uint64](x: var T; y = 1)
-  for a 'var' type a variable needs to be passed, but 'i' is immutable
+  first type mismatch at position: 1
+  required type for x: var T: Ordinal or uint or uint64
+  but expression 'i' is immutable, not 'var'
 
 expression: inc i
 '''