summary refs log tree commit diff stats
path: root/compiler/semcall.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/semcall.nim')
-rw-r--r--compiler/semcall.nim46
1 files changed, 34 insertions, 12 deletions
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 927b23cf2..3971b8ff5 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -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,38 @@ 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, preferName))
+        if i != n.len-1: add(errProto, ", ")
+      # else: ignore internal error as we're already in error handling mode
+    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 +134,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) =
@@ -254,6 +274,7 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
   assert x.state == csMatch
   var finalCallee = x.calleeSym
   markUsed(n.sons[0].info, finalCallee)
+  styleCheckUse(n.sons[0].info, finalCallee)
   if finalCallee.ast == nil:
     internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check!
   if finalCallee.ast.sons[genericParamsPos].kind != nkEmpty:
@@ -286,6 +307,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
   initCandidate(c, m, s, n)
   var newInst = generateInstance(c, s, m.bindings, n.info)
   markUsed(n.info, s)
+  styleCheckUse(n.info, s)
   result = newSymNode(newInst, n.info)
 
 proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = 
@@ -305,7 +327,7 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
     result = explicitGenericSym(c, n, s)
   elif a.kind in {nkClosedSymChoice, nkOpenSymChoice}:
     # choose the generic proc with the proper number of type parameters.
-    # XXX I think this could be improved by reusing sigmatch.ParamTypesMatch.
+    # XXX I think this could be improved by reusing sigmatch.paramTypesMatch.
     # It's good enough for now.
     result = newNodeI(a.kind, n.info)
     for i in countup(0, len(a)-1):