diff options
Diffstat (limited to 'compiler/semcall.nim')
-rw-r--r-- | compiler/semcall.nim | 88 |
1 files changed, 52 insertions, 36 deletions
diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 381093531..17dd39595 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -50,7 +50,8 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode, var syms: seq[tuple[a: PSym, b: int]] = @[] while symx != nil: - if symx.kind in filter: syms.add((symx, o.lastOverloadScope)) + if symx.kind in filter: + syms.add((symx, o.lastOverloadScope)) symx = nextOverloadIter(o, c, headSymbol) if syms.len == 0: return @@ -63,7 +64,6 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode, let sym = syms[i][0] determineType(c, sym) initCandidate(c, z, sym, initialBinding, syms[i][1]) - z.calleeSym = sym #if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140: # gDebug = true @@ -75,7 +75,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode, errors.add(err) if z.state == csMatch: # little hack so that iterators are preferred over everything else: - if sym.kind in skIterators: inc(z.exactMatches, 200) + if sym.kind == skIterator: inc(z.exactMatches, 200) case best.state of csEmpty, csNoMatch: best = z of csMatch: @@ -95,7 +95,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) = # Gives a detailed error message; this is separated from semOverloadedCall, # as semOverlodedCall is already pretty slow (and we need this information # only in case of an error). - if c.compilesContextId > 0: + if c.compilesContextId > 0 and optReportConceptFailures notin gGlobalOptions: # fail fast: globalError(n.info, errTypeMismatch, "") if errors.isNil or errors.len == 0: @@ -133,12 +133,10 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) = add(candidates, "\n") if candidates != "": add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates) - localError(n.info, errGenerated, result) - -proc gatherUsedSyms(c: PContext, usedSyms: var seq[PNode]) = - for scope in walkScopes(c.currentScope): - if scope.usingSyms != nil: - for s in scope.usingSyms: usedSyms.safeAdd(s) + if c.compilesContextId > 0 and optReportConceptFailures in gGlobalOptions: + globalError(n.info, errGenerated, result) + else: + localError(n.info, errGenerated, result) proc resolveOverloads(c: PContext, n, orig: PNode, filter: TSymKinds; @@ -153,31 +151,30 @@ proc resolveOverloads(c: PContext, n, orig: PNode, else: initialBinding = nil - var usedSyms: seq[PNode] - - template pickBest(headSymbol: expr) = + template pickBest(headSymbol) = pickBestCandidate(c, headSymbol, n, orig, initialBinding, filter, result, alt, errors) - gatherUsedSyms(c, usedSyms) - if usedSyms != nil: - var hiddenArg = if usedSyms.len > 1: newNode(nkClosedSymChoice, n.info, usedSyms) - else: usedSyms[0] - - 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 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) @@ -252,12 +249,13 @@ proc resolveOverloads(c: PContext, n, orig: PNode, proc instGenericConvertersArg*(c: PContext, a: PNode, x: TCandidate) = - if a.kind == nkHiddenCallConv and a.sons[0].kind == nkSym and - isGenericRoutine(a.sons[0].sym): - let finalCallee = generateInstance(c, a.sons[0].sym, x.bindings, a.info) - a.sons[0].sym = finalCallee - a.sons[0].typ = finalCallee.typ - #a.typ = finalCallee.typ.sons[0] + if a.kind == nkHiddenCallConv and a.sons[0].kind == nkSym: + let s = a.sons[0].sym + if s.ast != nil and s.ast[genericParamsPos].kind != nkEmpty: + let finalCallee = generateInstance(c, s, x.bindings, a.info) + a.sons[0].sym = finalCallee + a.sons[0].typ = finalCallee.typ + #a.typ = finalCallee.typ.sons[0] proc instGenericConvertersSons*(c: PContext, n: PNode, x: TCandidate) = assert n.kind in nkCallKinds @@ -363,7 +361,19 @@ proc explicitGenericInstError(n: PNode): PNode = proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode = var m: TCandidate - initCandidate(c, m, s, n) + # binding has to stay 'nil' for this to work! + initCandidate(c, m, s, nil) + + for i in 1..sonsLen(n)-1: + let formal = s.ast.sons[genericParamsPos].sons[i-1].typ + let arg = n[i].typ + let tm = typeRel(m, formal, arg, true) + if tm in {isNone, isConvertible}: + if formal.sonsLen > 0 and formal.sons[0].kind != tyNone: + typeMismatch(n, formal.sons[0], arg) + else: + typeMismatch(n, formal, arg) + break var newInst = generateInstance(c, s, m.bindings, n.info) markUsed(n.info, s) styleCheckUse(n.info, s) @@ -392,7 +402,7 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = for i in countup(0, len(a)-1): var candidate = a.sons[i].sym if candidate.kind in {skProc, skMethod, skConverter, - skIterator, skClosureIterator}: + skIterator}: # it suffices that the candidate has the proper number of generic # type parameters: if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1: @@ -416,7 +426,13 @@ proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym = let param = fn.typ.n.sons[i] let t = skipTypes(param.typ, abstractVar-{tyTypeDesc}) if t.kind == tyDistinct or param.typ.kind == tyDistinct: hasDistinct = true - call.add(newNodeIT(nkEmpty, fn.info, t.baseOfDistinct)) + var x: PType + if param.typ.kind == tyVar: + x = newTypeS(tyVar, c) + x.addSonSkipIntLit t.baseOfDistinct + else: + x = t.baseOfDistinct + call.add(newNodeIT(nkEmpty, fn.info, x)) if hasDistinct: var resolved = semOverloadedCall(c, call, call, {fn.kind}) if resolved != nil: |