better 'self' handling for overload resolution

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

View File

@@ -39,8 +39,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
initialBinding: PNode,
filter: TSymKinds,
best, alt: var TCandidate,
errors: var CandidateErrors;
fromUsingStmt: bool) =
errors: var CandidateErrors) =
var o: TOverloadIter
# thanks to the lazy semchecking for operands, we need to iterate over the
# 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]] = @[]
while symx != nil:
if symx.kind in filter:
if fromUsingStmt and (symx.typ.n.len <= 1 or
sfIsSelf notin symx.typ.n[1].sym.flags):
discard "only consider procs that have a 'self' too"
else:
syms.add((symx, o.lastOverloadScope))
syms.add((symx, o.lastOverloadScope))
symx = nextOverloadIter(o, c, headSymbol)
if syms.len == 0: return
@@ -156,30 +151,30 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
else:
initialBinding = nil
template pickBest(headSymbol, fromUsingStmt) =
template pickBest(headSymbol) =
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)
if result.state != csMatch:
n.sons.delete(1)
orig.sons.delete(1)
else: return
pickBest(f, false)
pickBest(f)
let overloadsState = result.state
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:
internalAssert f.kind == nkIdent and n.sonsLen >= 2
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)
n.sons[0] = op
orig.sons[0] = op
pickBest(op, false)
pickBest(op)
if nfExplicitCall in n.flags:
tryOp ".()"
@@ -208,7 +203,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
let callOp = newIdentNode(getIdent".=", n.info)
n.sons[0..1] = [callOp, n[1], calleeName]
orig.sons[0..1] = [callOp, orig[1], calleeName]
pickBest(callOp, false)
pickBest(callOp)
if overloadsState == csEmpty and result.state == csEmpty:
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
errors = @[]
pickBest(f, false)
pickBest(f)
#notFoundError(c, n, errors)
return