fixes a multimethod regression
This commit is contained in:
parent
46f33515d7
commit
f8914cc3b0
3 changed files with 33 additions and 8 deletions
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue