diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 23362151b..7f7005633 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -126,7 +126,8 @@ proc gatherUsedSyms(c: PContext, usedSyms: var seq[PNode]) = for s in scope.usingSyms: usedSyms.safeAdd(s) proc resolveOverloads(c: PContext, n, orig: PNode, - filter: TSymKinds): TCandidate = + filter: TSymKinds; + errors: var CandidateErrors): TCandidate = var initialBinding: PNode var alt: TCandidate var f = n.sons[0] @@ -137,7 +138,6 @@ proc resolveOverloads(c: PContext, n, orig: PNode, else: initialBinding = nil - var errors: CandidateErrors var usedSyms: seq[PNode] template pickBest(headSymbol: expr) = @@ -207,7 +207,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode, errors = @[] pickBest(f) - notFoundError(c, n, errors) + #notFoundError(c, n, errors) return @@ -293,12 +293,32 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode = result.sons[0] = newSymNode(finalCallee, result.sons[0].info) result.typ = finalCallee.typ.sons[0] +proc canDeref(n: PNode): bool {.inline.} = + result = n.len >= 2 and (let t = n[1].typ; + t != nil and t.skipTypes({tyGenericInst}).kind in {tyPtr, tyRef}) + +proc tryDeref(n: PNode): PNode = + result = newNodeI(nkHiddenDeref, n.info) + result.typ = n.typ.skipTypes(abstractInst).sons[0] + result.addSon(n) + proc semOverloadedCall(c: PContext, n, nOrig: PNode, filter: TSymKinds): PNode = - var r = resolveOverloads(c, n, nOrig, filter) + var errors: CandidateErrors + + var r = resolveOverloads(c, n, nOrig, filter, errors) if r.state == csMatch: result = semResolvedCall(c, n, r) + elif experimentalMode(c) and canDeref(n): + # try to deref the first argument and then try overloading resolution again: + n.sons[1] = n.sons[1].tryDeref + var r = resolveOverloads(c, n, nOrig, filter, errors) + if r.state == csMatch: result = semResolvedCall(c, n, r) + else: + notFoundError(c, n, errors) + else: + notFoundError(c, n, errors) # else: result = errorNode(c, n) - + proc explicitGenericInstError(n: PNode): PNode = localError(n.info, errCannotInstantiateX, renderTree(n)) result = n diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 8221ed372..577dc465f 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -750,6 +750,18 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode, incl(c.p.owner.flags, sfSideEffect) proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode + +proc resolveIndirectCall(c: PContext; n, nOrig: PNode; + t: PType): TCandidate = + initCandidate(c, result, t) + matches(c, n, nOrig, result) + if result.state != csMatch: + # try to deref the first argument: + if experimentalMode(c) and canDeref(n): + n.sons[1] = n.sons[1].tryDeref + initCandidate(c, result, t) + matches(c, n, nOrig, result) + proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = result = nil checkMinSonsLen(n, 1) @@ -773,9 +785,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}) if t != nil and t.kind == tyProc: # This is a proc variable, apply normal overload resolution - var m: TCandidate - initCandidate(c, m, t) - matches(c, n, nOrig, m) + let m = resolveIndirectCall(c, n, nOrig, t) if m.state != csMatch: if c.inCompilesContext > 0: # speed up error generation: