summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2017-02-24 13:02:36 +0100
committerAndreas Rumpf <rumpf_a@web.de>2017-02-24 13:02:36 +0100
commitf8914cc3b002916c2b9a9cc548eae610d14ef666 (patch)
treeb5ab9dade22a60973e022907c12d857755d45a52 /compiler
parent46f33515d7ec32215122547bce535e4c91894da3 (diff)
downloadNim-f8914cc3b002916c2b9a9cc548eae610d14ef666.tar.gz
fixes a multimethod regression
Diffstat (limited to 'compiler')
-rw-r--r--compiler/cgmeth.nim15
-rw-r--r--compiler/semstmts.nim13
2 files changed, 22 insertions, 6 deletions
diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim
index 52fd8ab49..3a945ae0a 100644
--- a/compiler/cgmeth.nim
+++ b/compiler/cgmeth.nim
@@ -35,15 +35,18 @@ proc genConv(n: PNode, d: PType, downcast: bool): PNode =
   else:
     result = n
 
+proc getDispatcher*(s: PSym): PSym =
+  ## can return nil if is has no dispatcher.
+  let dispn = lastSon(s.ast)
+  if dispn.kind == nkSym:
+    let disp = dispn.sym
+    if sfDispatcher in disp.flags: result = disp
+
 proc methodCall*(n: PNode): PNode =
   result = n
   # replace ordinary method by dispatcher method:
-  let dispn = lastSon(result.sons[0].sym.ast)
-  if dispn.kind == nkSym:
-    let disp = dispn.sym
-    if sfDispatcher notin disp.flags:
-      localError(n.info, "'" & $result & "' lacks a dispatcher")
-      return
+  let disp = getDispatcher(result.sons[0].sym)
+  if disp != nil:
     result.sons[0].sym = disp
     # change the arguments to up/downcasts to fit the dispatcher's parameters:
     for i in countup(1, sonsLen(result)-1):
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 5ecba3ab0..c28dbf82f 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1443,6 +1443,19 @@ proc semProc(c: PContext, n: PNode): PNode =
 proc semMethod(c: PContext, n: PNode): PNode =
   if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "method")
   result = semProcAux(c, n, skMethod, methodPragmas)
+  # macros can transform converters to nothing:
+  if namePos >= result.safeLen: return result
+  var s = result.sons[namePos].sym
+  # we need to fix the 'auto' return type for the dispatcher here (see tautonotgeneric
+  # test case):
+  let disp = getDispatcher(s)
+  # auto return type?
+  if disp != nil and disp.typ.sons[0] != nil and disp.typ.sons[0].kind == tyExpr:
+    let ret = s.typ.sons[0]
+    disp.typ.sons[0] = ret
+    if disp.ast[resultPos].kind == nkSym:
+      if isEmptyType(ret): disp.ast.sons[resultPos] = emptyNode
+      else: disp.ast[resultPos].sym.typ = ret
 
 proc semConverterDef(c: PContext, n: PNode): PNode =
   if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "converter")