better 'self' handling for overload resolution

This commit is contained in:
Andreas Rumpf 2016-02-29 00:25:51 +01:00
commit 554a3e9335

View file

@ -39,8 +39,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
initialBinding: PNode, initialBinding: PNode,
filter: TSymKinds, filter: TSymKinds,
best, alt: var TCandidate, best, alt: var TCandidate,
errors: var CandidateErrors; errors: var CandidateErrors) =
fromUsingStmt: bool) =
var o: TOverloadIter var o: TOverloadIter
# thanks to the lazy semchecking for operands, we need to iterate over the # thanks to the lazy semchecking for operands, we need to iterate over the
# symbol table *before* any call to 'initCandidate' which might invoke # symbol table *before* any call to 'initCandidate' which might invoke
@ -52,11 +51,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
var syms: seq[tuple[a: PSym, b: int]] = @[] var syms: seq[tuple[a: PSym, b: int]] = @[]
while symx != nil: while symx != nil:
if symx.kind in filter: if symx.kind in filter:
if fromUsingStmt and (symx.typ.n.len <= 1 or syms.add((symx, o.lastOverloadScope))
sfIsSelf notin symx.typ.n[1].sym.flags):
discard "only consider procs that have a 'self' too"
else:
syms.add((symx, o.lastOverloadScope))
symx = nextOverloadIter(o, c, headSymbol) symx = nextOverloadIter(o, c, headSymbol)
if syms.len == 0: return if syms.len == 0: return
@ -156,30 +151,30 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
else: else:
initialBinding = nil initialBinding = nil
template pickBest(headSymbol, fromUsingStmt) = template pickBest(headSymbol) =
pickBestCandidate(c, headSymbol, n, orig, initialBinding, pickBestCandidate(c, headSymbol, n, orig, initialBinding,
filter, result, alt, errors, fromUsingStmt) filter, result, alt, errors)
#gatherUsedSyms(c, usedSyms)
if c.p != nil and c.p.selfSym != nil:
# we need to enforce semchecking of selfSym again because it
# might need auto-deref:
var hiddenArg = newSymNode(c.p.selfSym)
hiddenArg.typ = nil
n.sons.insert(hiddenArg, 1)
orig.sons.insert(hiddenArg, 1)
pickBest(f, true) pickBest(f)
if result.state != csMatch:
n.sons.delete(1)
orig.sons.delete(1)
else: return
pickBest(f, false)
let overloadsState = result.state let overloadsState = result.state
if overloadsState != csMatch: if overloadsState != csMatch:
if c.p != nil and c.p.selfSym != nil:
# we need to enforce semchecking of selfSym again because it
# might need auto-deref:
var hiddenArg = newSymNode(c.p.selfSym)
hiddenArg.typ = nil
n.sons.insert(hiddenArg, 1)
orig.sons.insert(hiddenArg, 1)
pickBest(f)
if result.state != csMatch:
n.sons.delete(1)
orig.sons.delete(1)
else: return
if nfDotField in n.flags: if nfDotField in n.flags:
internalAssert f.kind == nkIdent and n.sonsLen >= 2 internalAssert f.kind == nkIdent and n.sonsLen >= 2
let calleeName = newStrNode(nkStrLit, f.ident.s).withInfo(n.info) let calleeName = newStrNode(nkStrLit, f.ident.s).withInfo(n.info)
@ -193,7 +188,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
let op = newIdentNode(getIdent(x), n.info) let op = newIdentNode(getIdent(x), n.info)
n.sons[0] = op n.sons[0] = op
orig.sons[0] = op orig.sons[0] = op
pickBest(op, false) pickBest(op)
if nfExplicitCall in n.flags: if nfExplicitCall in n.flags:
tryOp ".()" tryOp ".()"
@ -208,7 +203,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
let callOp = newIdentNode(getIdent".=", n.info) let callOp = newIdentNode(getIdent".=", n.info)
n.sons[0..1] = [callOp, n[1], calleeName] n.sons[0..1] = [callOp, n[1], calleeName]
orig.sons[0..1] = [callOp, orig[1], calleeName] orig.sons[0..1] = [callOp, orig[1], calleeName]
pickBest(callOp, false) pickBest(callOp)
if overloadsState == csEmpty and result.state == csEmpty: if overloadsState == csEmpty and result.state == csEmpty:
if nfDotField in n.flags and nfExplicitCall notin n.flags: if nfDotField in n.flags and nfExplicitCall notin n.flags:
@ -227,7 +222,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
n.sons[0] = f n.sons[0] = f
errors = @[] errors = @[]
pickBest(f, false) pickBest(f)
#notFoundError(c, n, errors) #notFoundError(c, n, errors)
return return