summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/sigmatch.nim10
-rw-r--r--compiler/transf.nim49
-rw-r--r--compiler/types.nim3
-rw-r--r--doc/contributing.rst35
-rw-r--r--tests/converter/tconvert.nim8
5 files changed, 66 insertions, 39 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 4fd4a3205..4dc7690ef 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -1826,9 +1826,12 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
     let srca = typeRel(m, src, a)
     if srca notin {isEqual, isGeneric, isSubtype}: continue
 
+    # What's done below matches the logic in ``matchesAux``
     let constraint = c.converters[i].typ.n[1].sym.constraint
     if not constraint.isNil and not matchNodeKinds(constraint, arg):
       continue
+    if src.kind in {tyVar, tyLent} and not arg.isLValue:
+      continue
 
     let destIsGeneric = containsGenericType(dest)
     if destIsGeneric:
@@ -1841,9 +1844,16 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
       s.info = arg.info
       result = newNodeIT(nkHiddenCallConv, arg.info, dest)
       addSon(result, s)
+      # We build the call expression by ourselves in order to avoid passing this
+      # expression trough the semantic check phase once again so let's make sure
+      # it is correct
       var param: PNode = nil
       if srca == isSubtype:
         param = implicitConv(nkHiddenSubConv, src, copyTree(arg), m, c)
+      elif src.kind == tyVar:
+        # Analyse the converter return type
+        param = newNodeIT(nkHiddenAddr, arg.info, s.typ[1])
+        param.addSon(copyTree(arg))
       else:
         param = copyTree(arg)
       addSon(result, param)
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 8721661df..800d56b3a 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -242,25 +242,17 @@ proc newLabel(c: PTransf, n: PNode): PSym =
   result = newSym(skLabel, nil, getCurrOwner(c), n.info)
   result.name = getIdent(c.graph.cache, genPrefix & $result.id)
 
-proc freshLabels(c: PTransf, n: PNode; symMap: var TIdTable) =
-  if n.kind in {nkBlockStmt, nkBlockExpr}:
-    if n.sons[0].kind == nkSym:
-      let x = newLabel(c, n[0])
-      idTablePut(symMap, n[0].sym, x)
-      n.sons[0].sym = x
-  if n.kind == nkSym and n.sym.kind == skLabel:
-    let x = PSym(idTableGet(symMap, n.sym))
-    if x != nil: n.sym = x
-  else:
-    for i in 0 ..< safeLen(n): freshLabels(c, n.sons[i], symMap)
-
 proc transformBlock(c: PTransf, n: PNode): PTransNode =
-  var labl: PSym
-  if n.sons[0].kind != nkEmpty:
-    # already named block? -> Push symbol on the stack:
-    labl = n.sons[0].sym
+  var labl: PSym 
+  if c.inlining > 0:
+    labl = newLabel(c, n[0])
+    idNodeTablePut(c.transCon.mapping, n[0].sym, newSymNode(labl))
   else:
-    labl = newLabel(c, n)
+    labl =
+      if n.sons[0].kind != nkEmpty:
+        n.sons[0].sym  # already named block? -> Push symbol on the stack
+      else:
+        newLabel(c, n)
   c.breakSyms.add(labl)
   result = transformSons(c, n)
   discard c.breakSyms.pop
@@ -301,22 +293,10 @@ proc transformWhile(c: PTransf; n: PNode): PTransNode =
     discard c.breakSyms.pop
 
 proc transformBreak(c: PTransf, n: PNode): PTransNode =
-  if n.sons[0].kind != nkEmpty or c.inlining > 0:
-    result = n.PTransNode
-    when false:
-      let lablCopy = idNodeTableGet(c.transCon.mapping, n.sons[0].sym)
-      if lablCopy.isNil:
-        result = n.PTransNode
-      else:
-        result = newTransNode(n.kind, n.info, 1)
-        result[0] = lablCopy.PTransNode
-  elif c.breakSyms.len > 0:
-    # this check can fail for 'nim check'
+  result = transformSons(c, n)
+  if n.sons[0].kind == nkEmpty and c.breakSyms.len > 0:
     let labl = c.breakSyms[c.breakSyms.high]
-    result = transformSons(c, n)
     result[0] = newSymNode(labl).PTransNode
-  else:
-    result = n.PTransNode
 
 proc introduceNewLocalVars(c: PTransf, n: PNode): PTransNode =
   case n.kind
@@ -631,13 +611,8 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
       add(stmtList, newAsgnStmt(c, nkFastAsgn, temp, arg.PTransNode))
       idNodeTablePut(newC.mapping, formal, temp)
 
-  let body = transformBody(c.graph, iter).copyTree
+  let body = transformBody(c.graph, iter)
   pushInfoContext(c.graph.config, n.info)
-  # XXX optimize this somehow. But the check "c.inlining" is not correct:
-  var symMap: TIdTable
-  initIdTable symMap
-  freshLabels(c, body, symMap)
-
   inc(c.inlining)
   add(stmtList, transform(c, body))
   #findWrongOwners(c, stmtList.pnode)
diff --git a/compiler/types.nim b/compiler/types.nim
index 485d3c369..05bae401c 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -397,7 +397,7 @@ const
     "float", "float32", "float64", "float128",
     "uint", "uint8", "uint16", "uint32", "uint64",
     "opt", "sink",
-    "lent", "varargs[$1]", "UncheckedArray[$1]", "Error Type",
+    "lent ", "varargs[$1]", "UncheckedArray[$1]", "Error Type",
     "BuiltInTypeClass", "UserTypeClass",
     "UserTypeClassInst", "CompositeTypeClass", "inferred",
     "and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor",
@@ -1176,6 +1176,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
   case t.kind
   of tyVar, tyLent:
     if kind in {skProc, skFunc, skConst}: return t
+    elif t.kind == tyLent and kind != skResult: return t
     var t2 = skipTypes(t.sons[0], abstractInst-{tyTypeDesc})
     case t2.kind
     of tyVar, tyLent:
diff --git a/doc/contributing.rst b/doc/contributing.rst
index fedabab11..35cdd9f09 100644
--- a/doc/contributing.rst
+++ b/doc/contributing.rst
@@ -367,6 +367,39 @@ General commit rules
 
    eg: use ``git pull --rebase origin devel``. This is to avoid messing up
    git history, see `#8664 <https://github.com/nim-lang/Nim/issues/8664>`_ .
-   Exceptions should be very rare.
+   Exceptions should be very rare: when rebase gives too many conflicts, simply
+   squash all commits using the script shown in
+   https://github.com/nim-lang/Nim/pull/9356
+
+
+5. Do not mix pure formatting changes (eg whitespace changes, nimpretty) or
+   automated changes (eg nimfix) with other code changes: these should be in
+   separate commits (and the merge on github should not squash these into 1).
+
+
+Continuous Integration (CI)
+---------------------------
+
+1. Continuous Integration is by default run on every push in a PR; this clogs
+   the CI pipeline and affects other PR's; if you don't need it (eg for WIP or
+   documentation only changes), add ``[ci skip]`` to your commit message title.
+   This convention is supported by `Appveyor <https://www.appveyor.com/docs/how-to/filtering-commits/#skip-directive-in-commit-message>`_
+   and `Travis <https://docs.travis-ci.com/user/customizing-the-build/#skipping-a-build>`_
+
+
+2. Consider enabling CI (travis and appveyor) in your own Nim fork, and
+   waiting for CI to be green in that fork (fixing bugs as needed) before
+   opening your PR in original Nim repo, so as to reduce CI congestion. Same
+   applies for updates on a PR: you can test commits on a separate private
+   branch before updating the main PR.
+
+Code reviews
+------------
+
+1. Whenever possible, use github's new 'Suggested change' in code reviews, which
+   saves time explaining the change or applying it; see also
+   https://forum.nim-lang.org/t/4317
 
 .. include:: docstyle.rst
+
+
diff --git a/tests/converter/tconvert.nim b/tests/converter/tconvert.nim
index 48367a85b..8aa4e97a3 100644
--- a/tests/converter/tconvert.nim
+++ b/tests/converter/tconvert.nim
@@ -18,3 +18,11 @@ converter toPtr*(some: var TFoo): ptr TFoo = (addr some)
 proc zoot(x: ptr TFoo) = discard
 var x: Tfoo
 zoot(x)
+
+# issue #6544
+converter withVar(b: var string): int = ord(b[1])
+
+block:
+  var x = "101"
+  var y: int = x # instantiate withVar
+  doAssert(y == ord('0'))