diff options
-rw-r--r-- | compiler/sigmatch.nim | 10 | ||||
-rw-r--r-- | compiler/transf.nim | 49 | ||||
-rw-r--r-- | compiler/types.nim | 3 | ||||
-rw-r--r-- | doc/contributing.rst | 35 | ||||
-rw-r--r-- | tests/converter/tconvert.nim | 8 |
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')) |