diff options
Diffstat (limited to 'compiler/nilcheck.nim')
-rw-r--r-- | compiler/nilcheck.nim | 65 |
1 files changed, 35 insertions, 30 deletions
diff --git a/compiler/nilcheck.nim b/compiler/nilcheck.nim index b779830d6..7e0efc34b 100644 --- a/compiler/nilcheck.nim +++ b/compiler/nilcheck.nim @@ -7,8 +7,11 @@ # distribution, for details about the copyright. # -import ast, renderer, intsets, tables, msgs, options, lineinfos, strformat, idents, treetab, hashes -import sequtils, strutils, std / sets +import ast, renderer, msgs, options, lineinfos, idents, treetab +import std/[intsets, tables, sequtils, strutils, sets, strformat, hashes] + +when defined(nimPreviewSlimSystem): + import std/assertions # IMPORTANT: notes not up to date, i'll update this comment again # @@ -306,6 +309,7 @@ proc symbol(n: PNode): Symbol = # echo "symbol ", n, " ", n.kind, " ", result.int func `$`(map: NilMap): string = + result = "" var now = map var stack: seq[NilMap] = @[] while not now.isNil: @@ -413,7 +417,7 @@ proc moveOut(ctx: NilCheckerContext, map: NilMap, target: PNode) = if targetSetIndex != noSetIndex: var targetSet = map.sets[targetSetIndex] if targetSet.len > 1: - var other: ExprIndex + var other: ExprIndex = default(ExprIndex) for element in targetSet: if element.ExprIndex != targetIndex: @@ -494,7 +498,7 @@ proc checkCall(n, ctx, map): Check = # check args and handle possible mutations var isNew = false - result.map = map + result = Check(map: map) for i, child in n: discard check(child, ctx, map) @@ -503,7 +507,7 @@ proc checkCall(n, ctx, map): Check = # as it might have been mutated # TODO similar for normal refs and fields: find dependent exprs: brackets - if child.kind == nkHiddenAddr and not child.typ.isNil and child.typ.kind == tyVar and child.typ[0].kind == tyRef: + if child.kind == nkHiddenAddr and not child.typ.isNil and child.typ.kind == tyVar and child.typ.elementType.kind == tyRef: if not isNew: result.map = newNilMap(map) isNew = true @@ -558,7 +562,7 @@ proc derefWarning(n, ctx, map; kind: Nilability) = if n.info in ctx.warningLocations: return ctx.warningLocations.incl(n.info) - var a: seq[History] + var a: seq[History] = @[] if n.kind == nkSym: a = history(map, ctx.index(n)) var res = "" @@ -749,6 +753,7 @@ proc checkReturn(n, ctx, map): Check = proc checkIf(n, ctx, map): Check = ## check branches based on condition + result = default(Check) var mapIf: NilMap = map # first visit the condition @@ -762,7 +767,7 @@ proc checkIf(n, ctx, map): Check = # the state of the conditions: negating conditions before the current one var layerHistory = newNilMap(mapIf) # the state after branch effects - var afterLayer: NilMap + var afterLayer: NilMap = nil # the result nilability for expressions var nilability = Safe @@ -821,7 +826,7 @@ proc checkFor(n, ctx, map): Check = var check2 = check(n.sons[2], ctx, m) var map2 = check2.map - result.map = ctx.union(map0, m) + result = Check(map: ctx.union(map0, m)) result.map = ctx.union(result.map, map2) result.nilability = Safe @@ -849,7 +854,7 @@ proc checkWhile(n, ctx, map): Check = var check2 = check(n.sons[1], ctx, m) var map2 = check2.map - result.map = ctx.union(map0, map1) + result = Check(map: ctx.union(map0, map1)) result.map = ctx.union(result.map, map2) result.nilability = Safe @@ -859,9 +864,10 @@ proc checkInfix(n, ctx, map): Check = ## a or b : map is an union of a and b's ## a == b : use checkCondition ## else: no change, just check args + result = default(Check) if n[0].kind == nkSym: - var mapL: NilMap - var mapR: NilMap + var mapL: NilMap = nil + var mapR: NilMap = nil if n[0].sym.magic notin {mAnd, mEqRef}: mapL = checkCondition(n[1], ctx, map, false, false) mapR = checkCondition(n[2], ctx, map, false, false) @@ -894,7 +900,7 @@ proc checkInfix(n, ctx, map): Check = proc checkIsNil(n, ctx, map; isElse: bool = false): Check = ## check isNil calls ## update the map depending on if it is not isNil or isNil - result.map = newNilMap(map) + result = Check(map: newNilMap(map)) let value = n[1] result.map.store(ctx, ctx.index(n[1]), if not isElse: Nil else: Safe, TArg, n.info, n) @@ -906,24 +912,24 @@ proc infix(ctx: NilCheckerContext, l: PNode, r: PNode, magic: TMagic): PNode = else: "" var cache = newIdentCache() - var op = newSym(skVar, cache.getIdent(name), nextSymId ctx.idgen, nil, r.info) + var op = newSym(skVar, cache.getIdent(name), ctx.idgen, nil, r.info) op.magic = magic result = nkInfix.newTree( newSymNode(op, r.info), l, r) - result.typ = newType(tyBool, nextTypeId ctx.idgen, nil) + result.typ = newType(tyBool, ctx.idgen, nil) proc prefixNot(ctx: NilCheckerContext, node: PNode): PNode = var cache = newIdentCache() - var op = newSym(skVar, cache.getIdent("not"), nextSymId ctx.idgen, nil, node.info) + var op = newSym(skVar, cache.getIdent("not"), ctx.idgen, nil, node.info) op.magic = mNot result = nkPrefix.newTree( newSymNode(op, node.info), node) - result.typ = newType(tyBool, nextTypeId ctx.idgen, nil) + result.typ = newType(tyBool, ctx.idgen, nil) proc infixEq(ctx: NilCheckerContext, l: PNode, r: PNode): PNode = infix(ctx, l, r, mEqRef) @@ -942,9 +948,9 @@ proc checkCase(n, ctx, map): Check = # c2 # also a == true is a , a == false is not a let base = n[0] - result.map = map.copyMap() + result = Check(map: map.copyMap()) result.nilability = Safe - var a: PNode + var a: PNode = nil for child in n: case child.kind: of nkOfBranch: @@ -1214,12 +1220,12 @@ proc check(n: PNode, ctx: NilCheckerContext, map: NilMap): Check = result = check(n.sons[1], ctx, map) of nkStmtList, nkStmtListExpr, nkChckRangeF, nkChckRange64, nkChckRange, nkBracket, nkCurly, nkPar, nkTupleConstr, nkClosure, nkObjConstr, nkElse: - result.map = map + result = Check(map: map) if n.kind in {nkObjConstr, nkTupleConstr}: # TODO deeper nested elements? # A(field: B()) # # field: Safe -> - var elements: seq[(PNode, Nilability)] + var elements: seq[(PNode, Nilability)] = @[] for i, child in n: result = check(child, ctx, result.map) if i > 0: @@ -1239,12 +1245,12 @@ proc check(n: PNode, ctx: NilCheckerContext, map: NilMap): Check = result = check(n.sons[0], ctx, map) of nkIfStmt, nkIfExpr: result = checkIf(n, ctx, map) - of nkAsgn: + of nkAsgn, nkFastAsgn, nkSinkAsgn: result = checkAsgn(n[0], n[1], ctx, map) - of nkVarSection: - result.map = map + of nkVarSection, nkLetSection: + result = Check(map: map) for child in n: - result = checkAsgn(child[0], child[2], ctx, result.map) + result = checkAsgn(child[0].skipPragmaExpr, child[2], ctx, result.map) of nkForStmt: result = checkFor(n, ctx, map) of nkCaseStmt: @@ -1268,8 +1274,7 @@ proc check(n: PNode, ctx: NilCheckerContext, map: NilMap): Check = else: var elementMap = map.copyMap() - var elementCheck: Check - elementCheck.map = elementMap + var elementCheck = Check(map: elementMap) for element in n: elementCheck = check(element, ctx, elementCheck.map) @@ -1283,7 +1288,7 @@ proc typeNilability(typ: PType): Nilability = # echo "typeNilability ", $typ.flags, " ", $typ.kind result = if tfNotNil in typ.flags: Safe - elif typ.kind in {tyRef, tyCString, tyPtr, tyPointer}: + elif typ.kind in {tyRef, tyCstring, tyPtr, tyPointer}: # # tyVar ? tyVarargs ? tySink ? tyLent ? # TODO spec? tests? @@ -1330,7 +1335,7 @@ proc preVisit(ctx: NilCheckerContext, s: PSym, body: PNode, conf: ConfigRef) = ctx.symbolIndices = {resultId: resultExprIndex}.toTable() var cache = newIdentCache() ctx.expressions = SeqOfDistinct[ExprIndex, PNode](@[newIdentNode(cache.getIdent("result"), s.ast.info)]) - var emptySet: IntSet # set[ExprIndex] + var emptySet: IntSet = initIntSet() # set[ExprIndex] ctx.dependants = SeqOfDistinct[ExprIndex, IntSet](@[emptySet]) for i, arg in s.typ.n.sons: if i > 0: @@ -1362,7 +1367,7 @@ proc checkNil*(s: PSym; body: PNode; conf: ConfigRef, idgen: IdGenerator) = continue map.store(context, context.index(child), typeNilability(child.typ), TArg, child.info, child) - map.store(context, resultExprIndex, if not s.typ[0].isNil and s.typ[0].kind == tyRef: Nil else: Safe, TResult, s.ast.info) + map.store(context, resultExprIndex, if not s.typ.returnType.isNil and s.typ.returnType.kind == tyRef: Nil else: Safe, TResult, s.ast.info) # echo "checking ", s.name.s, " ", filename @@ -1378,5 +1383,5 @@ proc checkNil*(s: PSym; body: PNode; conf: ConfigRef, idgen: IdGenerator) = # (ANotNil, BNotNil) : # do we check on asgn nilability at all? - if not s.typ[0].isNil and s.typ[0].kind == tyRef and tfNotNil in s.typ[0].flags: + if not s.typ.returnType.isNil and s.typ.returnType.kind == tyRef and tfNotNil in s.typ.returnType.flags: checkResult(s.ast, context, res.map) |