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.nim88
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: