summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/sem.nim3
-rw-r--r--compiler/semcall.nim41
-rw-r--r--compiler/semdata.nim3
-rw-r--r--compiler/semexprs.nim5
-rw-r--r--compiler/sigmatch.nim20
-rw-r--r--compiler/types.nim29
-rw-r--r--lib/core/typeinfo.nim1
-rw-r--r--lib/impure/zipfiles.nim2
-rw-r--r--lib/system.nim26
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: