From 7a48942719f4a557abafefd6d5cbd8b25a283e3a Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 26 Oct 2014 19:54:43 +0100 Subject: [PATCH] nicer error messages (untested) --- compiler/sem.nim | 3 +-- compiler/semcall.nim | 43 ++++++++++++++++++++++++++++++----------- compiler/semdata.nim | 3 +-- compiler/semexprs.nim | 5 ++--- compiler/sigmatch.nim | 20 ++++++++++--------- compiler/types.nim | 29 +++++++++++++++------------ lib/core/typeinfo.nim | 1 + lib/impure/zipfiles.nim | 2 +- lib/system.nim | 26 +++++++++++++++---------- 9 files changed, 82 insertions(+), 50 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 63475a566..81846e1b4 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -40,8 +40,7 @@ proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) proc addParams(c: PContext, n: PNode, kind: TSymKind) proc maybeAddResult(c: PContext, s: PSym, n: PNode) proc instGenericContainer(c: PContext, n: PNode, header: PType): PType -proc tryExpr(c: PContext, n: PNode, - flags: TExprFlags = {}, bufferErrors = false): PNode +proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode proc fixImmediateParams(n: PNode): PNode proc activate(c: PContext, n: PNode) proc semQuoteAst(c: PContext, n: PNode): PNode diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 6f92a75a6..a4490b782 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -39,7 +39,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode, initialBinding: PNode, filter: TSymKinds, best, alt: var TCandidate, - errors: var seq[string]) = + errors: var CandidateErrors) = var o: TOverloadIter var sym = initOverloadIter(o, c, headSymbol) var symScope = o.lastOverloadScope @@ -58,10 +58,10 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode, z.calleeSym = sym matches(c, n, orig, z) if errors != nil: - errors.safeAdd(getProcHeader(sym)) + errors.safeAdd(sym) if z.errors != nil: for err in z.errors: - errors[errors.len - 1].add("\n " & err) + 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) @@ -74,7 +74,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode, else: discard sym = nextOverloadIter(o, c, headSymbol) -proc notFoundError*(c: PContext, n: PNode, errors: seq[string]) = +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). @@ -83,18 +83,39 @@ proc notFoundError*(c: PContext, n: PNode, errors: seq[string]) = globalError(n.info, errTypeMismatch, "") if errors.len == 0: localError(n.info, errExprXCannotBeCalled, n[0].renderTree) - var result = msgKindToString(errTypeMismatch) - add(result, describeArgs(c, n, 1)) - add(result, ')') + + # to avoid confusing errors like: + # got (SslPtr, SocketHandle) + # but expected one of: + # openssl.SSL_set_fd(ssl: SslPtr, fd: SocketHandle): cint + # we do a pre-analysis. If all types produce the same string, we will add + # module information. + let proto = describeArgs(c, n, 1, preferName) + var prefer = preferName + for err in errors: + var errProto = "(" + let n = err.typ.n + for i in countup(1, n.len - 1): + var p = n.sons[i] + if p.kind == nkSym: + add(errProto, typeToString(p.sym.typ, prefer)) + if i != n.len-1: add(errProto, ", ") + # else: ignore internal error as we're already in error handling mode + add(errProto, ')') + if errProto == proto: + prefer = preferModuleInfo + break + # now use the information stored in 'prefer' to produce a nice error message: + var result = msgKindToString(errTypeMismatch) + add(result, describeArgs(c, n, 1, prefer)) + add(result, ')') var candidates = "" for err in errors: - add(candidates, err) + add(candidates, err.getProcHeader(prefer)) 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]) = @@ -114,7 +135,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode, else: initialBinding = nil - var errors: seq[string] + var errors: CandidateErrors var usedSyms: seq[PNode] template pickBest(headSymbol: expr) = diff --git a/compiler/semdata.nim b/compiler/semdata.nim index bc7b8cdc2..921e87d30 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -72,8 +72,7 @@ type libs*: TLinkedList # all libs used by this module semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.} - semTryExpr*: proc (c: PContext, n: PNode,flags: TExprFlags = {}, - bufferErrors = false): PNode {.nimcall.} + semTryExpr*: proc (c: PContext, n: PNode,flags: TExprFlags = {}): PNode {.nimcall.} semTryConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} semOperand*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.} semConstBoolExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # XXX bite the bullet diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index f2d0c0b82..f156470fe 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1551,8 +1551,7 @@ proc semQuoteAst(c: PContext, n: PNode): PNode = newNode(nkCall, n.info, quotes)]) result = semExpandToAst(c, result) -proc tryExpr(c: PContext, n: PNode, - flags: TExprFlags = {}, bufferErrors = false): PNode = +proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = # watch out, hacks ahead: let oldErrorCount = msgs.gErrorCounter let oldErrorMax = msgs.gErrorMax @@ -1566,7 +1565,7 @@ proc tryExpr(c: PContext, n: PNode, let oldOwnerLen = len(gOwners) let oldGenerics = c.generics let oldErrorOutputs = errorOutputs - errorOutputs = if bufferErrors: {eInMemory} else: {} + #errorOutputs = if bufferErrors: {eInMemory} else: {} let oldContextLen = msgs.getInfoContextLen() let oldInGenericContext = c.inGenericContext diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index b5e01811e..4a3773ed8 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -22,6 +22,7 @@ type TCandidateState* = enum csEmpty, csMatch, csNoMatch + CandidateErrors* = seq[PSym] TCandidate* {.final.} = object c*: PContext exactMatches*: int # also misused to prefer iters over procs @@ -45,7 +46,7 @@ type # a distrinct type typedescMatched: bool inheritancePenalty: int # to prefer closest father object type - errors*: seq[string] # additional clarifications to be displayed to the + errors*: CandidateErrors # additional clarifications to be displayed to the # user if overload resolution fails TTypeRelation* = enum # order is important! @@ -202,16 +203,17 @@ proc writeMatches*(c: TCandidate) = writeln(stdout, "intconv matches: " & $c.intConvMatches) writeln(stdout, "generic matches: " & $c.genericMatches) -proc argTypeToString(arg: PNode): string = +proc argTypeToString(arg: PNode; prefer: TPreferedDesc): string = if arg.kind in nkSymChoices: - result = typeToString(arg[0].typ) + result = typeToString(arg[0].typ, prefer) for i in 1 ..