fixes a multimethod regression

This commit is contained in:
Andreas Rumpf 2017-02-24 13:02:36 +01:00
commit f8914cc3b0
3 changed files with 33 additions and 8 deletions

View file

@ -35,15 +35,18 @@ proc genConv(n: PNode, d: PType, downcast: bool): PNode =
else: else:
result = n 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 = proc methodCall*(n: PNode): PNode =
result = n result = n
# replace ordinary method by dispatcher method: # replace ordinary method by dispatcher method:
let dispn = lastSon(result.sons[0].sym.ast) let disp = getDispatcher(result.sons[0].sym)
if dispn.kind == nkSym: if disp != nil:
let disp = dispn.sym
if sfDispatcher notin disp.flags:
localError(n.info, "'" & $result & "' lacks a dispatcher")
return
result.sons[0].sym = disp result.sons[0].sym = disp
# change the arguments to up/downcasts to fit the dispatcher's parameters: # change the arguments to up/downcasts to fit the dispatcher's parameters:
for i in countup(1, sonsLen(result)-1): for i in countup(1, sonsLen(result)-1):

View file

@ -1443,6 +1443,19 @@ proc semProc(c: PContext, n: PNode): PNode =
proc semMethod(c: PContext, n: PNode): PNode = 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) 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 = 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")

View file

@ -1,15 +1,24 @@
discard """ discard """
output: "wof!" output: '''wof!
wof!'''
""" """
# bug #1659 # bug #1659
type Animal = ref object {.inheritable.} type Animal = ref object {.inheritable.}
type Dog = ref object of Animal type Dog = ref object of Animal
method say(a: Animal): auto = "wat!" method say(a: Animal): auto {.base.} = "wat!"
method say(a: Dog): auto = "wof!" method say(a: Dog): auto = "wof!"
proc saySomething(a: Animal): auto = a.say() proc saySomething(a: Animal): auto = a.say()
method ec(a: Animal): auto {.base.} = echo "wat!"
method ec(a: Dog): auto = echo "wof!"
proc ech(a: Animal): auto = a.ec()
var a = Dog() var a = Dog()
echo saySomething(a) echo saySomething(a)
ech a