diff options
-rw-r--r-- | compiler/sem.nim | 3 | ||||
-rw-r--r-- | compiler/semcall.nim | 41 | ||||
-rw-r--r-- | compiler/semdata.nim | 3 | ||||
-rw-r--r-- | compiler/semexprs.nim | 5 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 20 | ||||
-rw-r--r-- | compiler/types.nim | 29 | ||||
-rw-r--r-- | lib/core/typeinfo.nim | 1 | ||||
-rw-r--r-- | lib/impure/zipfiles.nim | 2 | ||||
-rw-r--r-- | lib/system.nim | 26 |
9 files changed, 81 insertions, 49 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) + + # 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)) + 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 .. <arg.len: result.add(" | ") - result.add typeToString(arg[i].typ) + result.add typeToString(arg[i].typ, prefer) else: - result = arg.typ.typeToString + result = arg.typ.typeToString(prefer) -proc describeArgs*(c: PContext, n: PNode, startIdx = 1): string = +proc describeArgs*(c: PContext, n: PNode, startIdx = 1; + prefer: TPreferedDesc = preferName): string = result = "" for i in countup(startIdx, n.len - 1): var arg = n.sons[i] @@ -227,7 +229,7 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1): string = arg = c.semOperand(c, n.sons[i]) n.sons[i] = arg if arg.typ.kind == tyError: return - add(result, argTypeToString(arg)) + add(result, argTypeToString(arg, prefer)) if i != sonsLen(n) - 1: add(result, ", ") proc typeRel*(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation @@ -480,8 +482,8 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate, dummyParam.typ = dummyType addDecl(c, dummyParam) - var checkedBody = c.semTryExpr(c, body.n[3].copyTree, bufferErrors = false) - m.errors = bufferedMsgs + var checkedBody = c.semTryExpr(c, body.n[3].copyTree) + #m.errors = bufferedMsgs clearBufferedMsgs() if checkedBody == nil: return isNone diff --git a/compiler/types.nim b/compiler/types.nim index 07a0cf941..e03762155 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -16,11 +16,10 @@ proc firstOrd*(t: PType): BiggestInt proc lastOrd*(t: PType): BiggestInt proc lengthOrd*(t: PType): BiggestInt type - TPreferedDesc* = enum - preferName, preferDesc, preferExported + TPreferedDesc* = enum + preferName, preferDesc, preferExported, preferModuleInfo -proc typeToString*(typ: PType, prefer: TPreferedDesc = preferName): string -proc getProcHeader*(sym: PSym): string +proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string proc base*(t: PType): PType # ------------------- type iterator: ---------------------------------------- type @@ -121,7 +120,7 @@ proc isCompatibleToCString(a: PType): bool = (a.sons[1].kind == tyChar): result = true -proc getProcHeader(sym: PSym): string = +proc getProcHeader*(sym: PSym; prefer: TPreferedDesc = preferName): string = result = sym.owner.name.s & '.' & sym.name.s & '(' var n = sym.typ.n for i in countup(1, sonsLen(n) - 1): @@ -129,13 +128,14 @@ proc getProcHeader(sym: PSym): string = if p.kind == nkSym: add(result, p.sym.name.s) add(result, ": ") - add(result, typeToString(p.sym.typ)) + add(result, typeToString(p.sym.typ, prefer)) if i != sonsLen(n)-1: add(result, ", ") else: internalError("getProcHeader") add(result, ')') - if n.sons[0].typ != nil: result.add(": " & typeToString(n.sons[0].typ)) - + if n.sons[0].typ != nil: + result.add(": " & typeToString(n.sons[0].typ, prefer)) + proc elemType*(t: PType): PType = assert(t != nil) case t.kind @@ -415,10 +415,14 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = var t = typ result = "" if t == nil: return - if prefer == preferName and t.sym != nil and sfAnon notin t.sym.flags: + if prefer in {preferName, preferModuleInfo} and t.sym != nil and + sfAnon notin t.sym.flags: if t.kind == tyInt and isIntLit(t): return t.sym.name.s & " literal(" & $t.n.intVal & ")" - return t.sym.name.s + if prefer == preferName: + return t.sym.name.s + else: + return t.sym.skipGenericOwner.name.s & '.' & t.sym.name.s case t.kind of tyInt: if not isIntLit(t) or prefer == preferExported: @@ -492,8 +496,9 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = result = "set[" & typeToString(t.sons[0]) & ']' of tyOpenArray: result = "openarray[" & typeToString(t.sons[0]) & ']' - of tyDistinct: - result = "distinct " & typeToString(t.sons[0], preferName) + of tyDistinct: + result = "distinct " & typeToString(t.sons[0], + if prefer == preferModuleInfo: preferModuleInfo else: preferName) of tyTuple: # we iterate over t.sons here, because t.n may be nil result = "tuple[" diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim index 842a944e1..84281485f 100644 --- a/lib/core/typeinfo.nim +++ b/lib/core/typeinfo.nim @@ -13,6 +13,7 @@ {.push hints: off.} +include "system/inclrtl.nim" include "system/hti.nim" {.pop.} diff --git a/lib/impure/zipfiles.nim b/lib/impure/zipfiles.nim index 8e5c24b8b..c22294061 100644 --- a/lib/impure/zipfiles.nim +++ b/lib/impure/zipfiles.nim @@ -57,7 +57,7 @@ proc addFile*(z: var TZipArchive, dest, src: string) = ## may contain a path that will be created. assert(z.mode != fmRead) if not fileExists(src): - raise newException(EIO, "File '" & src & "' does not exist") + raise newException(IOError, "File '" & src & "' does not exist") var zipsrc = zip_source_file(z.w, src, 0, -1) if zipsrc == nil: #echo("Dest: " & dest) diff --git a/lib/system.nim b/lib/system.nim index 795203e4e..a9b4da77a 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2030,16 +2030,17 @@ when not defined(nimrodVM) and hostOS != "standalone": ## returns an informative string about the GC's activity. This may be useful ## for tweaking. - proc GC_ref*[T](x: ref T) {.magic: "GCref", benign.} - proc GC_ref*[T](x: seq[T]) {.magic: "GCref", benign.} - proc GC_ref*(x: string) {.magic: "GCref", benign.} + # XXX mark these as 'locks: 0' once 0.10.0 has been released + proc GC_ref*[T](x: ref T) {.magic: "GCref", gcsafe.} + proc GC_ref*[T](x: seq[T]) {.magic: "GCref", gcsafe.} + proc GC_ref*(x: string) {.magic: "GCref", gcsafe.} ## marks the object `x` as referenced, so that it will not be freed until ## it is unmarked via `GC_unref`. If called n-times for the same object `x`, ## n calls to `GC_unref` are needed to unmark `x`. - proc GC_unref*[T](x: ref T) {.magic: "GCunref", benign.} - proc GC_unref*[T](x: seq[T]) {.magic: "GCunref", benign.} - proc GC_unref*(x: string) {.magic: "GCunref", benign.} + proc GC_unref*[T](x: ref T) {.magic: "GCunref", gcsafe.} + proc GC_unref*[T](x: seq[T]) {.magic: "GCunref", gcsafe.} + proc GC_unref*(x: string) {.magic: "GCunref", gcsafe.} ## see the documentation of `GC_ref`. template accumulateResult*(iter: expr) = @@ -2178,9 +2179,14 @@ when not declared(sysFatal): e.msg = message & arg raise e -proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo", benign.} - ## get type information for `x`. Ordinary code should not use this, but - ## the `typeinfo` module instead. +when defined(nimlocks): + proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo", gcsafe, locks: 0.} + ## get type information for `x`. Ordinary code should not use this, but + ## the `typeinfo` module instead. +else: + proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo", gcsafe.} + ## get type information for `x`. Ordinary code should not use this, but + ## the `typeinfo` module instead. {.push stackTrace: off.} proc abs*(x: int): int {.magic: "AbsI", noSideEffect.} = @@ -2379,7 +2385,7 @@ when not defined(JS): #and not defined(NimrodVM): when not defined(booting): proc writeln*[Ty](f: File, x: varargs[Ty, `$`]) {.inline, - tags: [WriteIOEffect], benign.} + tags: [WriteIOEffect], gcsafe, locks: 0.} ## writes the values `x` to `f` and then writes "\n". ## May throw an IO exception. else: |