summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorTimothee Cour <timothee.cour2@gmail.com>2018-10-13 16:16:04 -0700
committerAndreas Rumpf <rumpf_a@web.de>2018-10-14 01:16:04 +0200
commiteb946f37a7c56fb64703357a67ed098ac8dfd936 (patch)
tree87c87454fad5a77a13b8db7d05a37222bdb030ec
parent8232bd04f9edc4b3accb114c9bd6e60190b68396 (diff)
downloadNim-eb946f37a7c56fb64703357a67ed098ac8dfd936.tar.gz
fixes #8671; show helpful msg (lookup symbol, eg iterator) on 'attempting to call undeclared routine' error (#8786)
-rw-r--r--compiler/semcall.nim32
-rw-r--r--tests/enum/tenumitems.nim2
-rw-r--r--tests/errmsgs/undeclared_routime.nim13
-rw-r--r--tests/errmsgs/undeclared_routime2.nim9
-rw-r--r--tests/errmsgs/undeclared_routime3.nim13
-rw-r--r--tests/errmsgs/undeclared_routime4.nim10
-rw-r--r--tests/errmsgs/undeclared_routime5.nim9
-rw-r--r--tests/errmsgs/undeclared_routime_compiles.nim11
-rw-r--r--tests/misc/tissue710.nim2
-rw-r--r--tests/misc/tnoop.nim7
10 files changed, 98 insertions, 10 deletions
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 71a9197b7..61d6113dc 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -224,6 +224,7 @@ const
   errButExpected = "but expected one of: "
   errUndeclaredField = "undeclared field: '$1'"
   errUndeclaredRoutine = "attempting to call undeclared routine: '$1'"
+  errBadRoutine = "attempting to call routine: '$1'$2"
   errAmbiguousCallXYZ = "ambiguous call; both $1 and $2 match for: $3"
 
 proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
@@ -262,6 +263,30 @@ proc bracketNotFoundError(c: PContext; n: PNode) =
   else:
     notFoundError(c, n, errors)
 
+proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string =
+  if c.compilesContextId > 0:
+    # we avoid running more diagnostic when inside a `compiles(expr)`, to
+    # errors while running diagnostic (see test D20180828T234921), and
+    # also avoid slowdowns in evaluating `compiles(expr)`.
+    discard
+  else:
+    var o: TOverloadIter
+    var sym = initOverloadIter(o, c, f)
+    while sym != nil:
+      proc toHumanStr(kind: TSymKind): string =
+        result = $kind
+        assert result.startsWith "sk"
+        result = result[2..^1].toLowerAscii
+      result &= "\n  found '$1' of kind '$2'" % [getSymRepr(c.config, sym), sym.kind.toHumanStr]
+      sym = nextOverloadIter(o, c, n)
+
+  let ident = considerQuotedIdent(c, f, n).s
+  if nfDotField in n.flags and nfExplicitCall notin n.flags:
+    result = errUndeclaredField % ident & result
+  else:
+    if result.len == 0: result = errUndeclaredRoutine % ident
+    else: result = errBadRoutine % [ident, result]
+
 proc resolveOverloads(c: PContext, n, orig: PNode,
                       filter: TSymKinds, flags: TExprFlags,
                       errors: var CandidateErrors,
@@ -330,11 +355,8 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
       pickBest(callOp)
 
     if overloadsState == csEmpty and result.state == csEmpty:
-      if efNoUndeclared notin flags:
-        if nfDotField in n.flags and nfExplicitCall notin n.flags:
-          localError(c.config, n.info, errUndeclaredField % considerQuotedIdent(c, f, n).s)
-        else:
-          localError(c.config, n.info, errUndeclaredRoutine % considerQuotedIdent(c, f, n).s)
+      if efNoUndeclared notin flags: # for tests/pragmas/tcustom_pragma.nim
+        localError(c.config, n.info, getMsgDiagnostic(c, flags, n, f))
       return
     elif result.state != csMatch:
       if nfExprCall in n.flags:
diff --git a/tests/enum/tenumitems.nim b/tests/enum/tenumitems.nim
index 38233aad7..6d13dd162 100644
--- a/tests/enum/tenumitems.nim
+++ b/tests/enum/tenumitems.nim
@@ -1,6 +1,6 @@
 discard """
   line: 7
-  errormsg: "attempting to call undeclared routine: 'items'"
+  errormsg: "attempting to call routine: 'items'"
 """
 
 type a = enum b,c,d
diff --git a/tests/errmsgs/undeclared_routime.nim b/tests/errmsgs/undeclared_routime.nim
new file mode 100644
index 000000000..426507652
--- /dev/null
+++ b/tests/errmsgs/undeclared_routime.nim
@@ -0,0 +1,13 @@
+discard """
+cmd: '''nim c --hints:off $file'''
+errormsg: "attempting to call routine: 'myiter'"
+nimout: '''undeclared_routime.nim(13, 15) Error: attempting to call routine: 'myiter'
+  found 'undeclared_routime.myiter(a: string)[declared in undeclared_routime.nim(10, 9)]' of kind 'iterator'
+  found 'undeclared_routime.myiter()[declared in undeclared_routime.nim(11, 9)]' of kind 'iterator'
+'''
+"""
+
+iterator myiter(a:string): int = discard
+iterator myiter(): int = discard
+
+let a = myiter(1)
diff --git a/tests/errmsgs/undeclared_routime2.nim b/tests/errmsgs/undeclared_routime2.nim
new file mode 100644
index 000000000..3e48b48f4
--- /dev/null
+++ b/tests/errmsgs/undeclared_routime2.nim
@@ -0,0 +1,9 @@
+discard """
+cmd: '''nim c --hints:off $file'''
+errormsg: "invalid pragma: myPragma"
+"""
+
+proc myPragma():int=discard
+iterator myPragma():int=discard
+proc myfun(a:int): int {.myPragma.} = 1
+let a = myfun(1)
diff --git a/tests/errmsgs/undeclared_routime3.nim b/tests/errmsgs/undeclared_routime3.nim
new file mode 100644
index 000000000..052adfc08
--- /dev/null
+++ b/tests/errmsgs/undeclared_routime3.nim
@@ -0,0 +1,13 @@
+discard """
+cmd: '''nim c --hints:off $file'''
+errormsg: "undeclared field: 'bar'"
+nimout: '''undeclared_routime3.nim(13, 10) Error: undeclared field: 'bar'
+  found 'undeclared_routime3.bar()[declared in undeclared_routime3.nim(12, 9)]' of kind 'iterator'
+'''
+"""
+
+
+type Foo = object
+var a = Foo()
+iterator bar():int=discard
+let a = a.bar
diff --git a/tests/errmsgs/undeclared_routime4.nim b/tests/errmsgs/undeclared_routime4.nim
new file mode 100644
index 000000000..674caa421
--- /dev/null
+++ b/tests/errmsgs/undeclared_routime4.nim
@@ -0,0 +1,10 @@
+discard """
+cmd: '''nim c --hints:off $file'''
+errormsg: "undeclared field: 'bar'"
+nimout: '''undeclared_routime4.nim(10, 10) Error: undeclared field: 'bar'
+'''
+"""
+
+type Foo = object
+var a = Foo()
+let a = a.bar
diff --git a/tests/errmsgs/undeclared_routime5.nim b/tests/errmsgs/undeclared_routime5.nim
new file mode 100644
index 000000000..4394134ab
--- /dev/null
+++ b/tests/errmsgs/undeclared_routime5.nim
@@ -0,0 +1,9 @@
+discard """
+cmd: '''nim c --hints:off $file'''
+errormsg: "undeclared identifier: 'myfun'"
+nimout: '''undeclared_routime5.nim(9, 9) Error: undeclared identifier: 'myfun'
+'''
+"""
+
+
+let a = myfun(1)
diff --git a/tests/errmsgs/undeclared_routime_compiles.nim b/tests/errmsgs/undeclared_routime_compiles.nim
new file mode 100644
index 000000000..21daf82bf
--- /dev/null
+++ b/tests/errmsgs/undeclared_routime_compiles.nim
@@ -0,0 +1,11 @@
+# D20180828T234921:here
+template foo*(iter: untyped): untyped =
+  when compiles(iter.unexistingField): 0
+  elif compiles(iter.len): 1
+  else: 2
+
+proc foo[A]()=
+  let a2 = @[10, 11]
+  let a3 = foo(pairs(a2))
+
+foo[int]()
diff --git a/tests/misc/tissue710.nim b/tests/misc/tissue710.nim
index 3b6d3e5f3..e2cca0024 100644
--- a/tests/misc/tissue710.nim
+++ b/tests/misc/tissue710.nim
@@ -1,7 +1,7 @@
 discard """
   file: "tissue710.nim"
   line: 8
-  errorMsg: "attempting to call undeclared routine: '||'"
+  errorMsg: "attempting to call routine: '||'"
 """
 var sum = 0
 for x in 3..1000:
diff --git a/tests/misc/tnoop.nim b/tests/misc/tnoop.nim
index 1e3fbe6cf..e1e25b44e 100644
--- a/tests/misc/tnoop.nim
+++ b/tests/misc/tnoop.nim
@@ -1,10 +1,11 @@
 discard """
+  nimout: '''
+  found 'a' of kind 'var''''
   file: "tnoop.nim"
-  line: 11
-  errormsg: "attempting to call undeclared routine: 'a'"
+  line: 12
+  errormsg: "attempting to call routine: 'a'"
 """
 
-
 var
   a: int