diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/guards.nim | 19 | ||||
-rw-r--r-- | compiler/sempass2.nim | 9 |
2 files changed, 27 insertions, 1 deletions
diff --git a/compiler/guards.nim b/compiler/guards.nim index aece63b19..f02a53684 100644 --- a/compiler/guards.nim +++ b/compiler/guards.nim @@ -345,12 +345,22 @@ proc impliesIn(fact, loc, aSet: PNode): TImplication = result = geImpliesIn(fact.sons[2], fact.sons[1].pred, aSet) of mNot, mOr, mAnd: internalError(loc.info, "impliesIn") else: discard - + +proc valueIsNil(n: PNode): TImplication = + if n.kind == nkNilLit: impYes + elif n.kind in {nkStrLit..nkTripleStrLit, nkBracket, nkObjConstr}: impNo + else: impUnknown + proc impliesIsNil(fact, eq: PNode): TImplication = case fact.sons[0].sym.magic of mIsNil: if sameTree(fact.sons[1], eq.sons[1]): result = impYes + of someEq: + if sameTree(fact.sons[1], eq.sons[1]): + result = valueIsNil(fact.sons[2].skipConv) + elif sameTree(fact.sons[2], eq.sons[1]): + result = valueIsNil(fact.sons[1].skipConv) of mNot, mOr, mAnd: internalError(eq.info, "impliesIsNil") else: discard @@ -539,6 +549,13 @@ proc addDiscriminantFact*(m: var TModel, n: PNode) = fact.sons[2] = n.sons[1] m.add fact +proc addAsgnFact*(m: var TModel, key, value: PNode) = + var fact = newNodeI(nkCall, key.info, 3) + fact.sons[0] = newSymNode(getSysMagic("==", mEqI)) + fact.sons[1] = key + fact.sons[2] = value + m.add fact + proc addCaseBranchFacts*(m: var TModel, n: PNode, i: int) = let branch = n.sons[i] if branch.kind == nkOfBranch: diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 2c87c3b2c..1fc74d31c 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -309,6 +309,12 @@ proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) = let n = n.skipConv if paramType != nil and tfNotNil in paramType.flags and n.typ != nil and tfNotNil notin n.typ.flags: + if n.kind == nkAddr: + # addr(x[]) can't be proven, but addr(x) can: + if not containsNode(n, {nkDerefExpr, nkHiddenDeref}): return + elif n.kind == nkSym and n.sym.kind in RoutineKinds: + # 'p' is not nil obviously: + return case impliesNotNil(tracked.guards, n) of impUnknown: Message(n.info, errGenerated, @@ -481,6 +487,7 @@ proc track(tracked: PEffects, n: PNode) = initVar(tracked, n.sons[0]) invalidateFacts(tracked.guards, n.sons[0]) track(tracked, n.sons[0]) + addAsgnFact(tracked.guards, n.sons[0], n.sons[1]) notNilCheck(tracked, n.sons[1], n.sons[0].typ) of nkVarSection: for child in n: @@ -489,6 +496,7 @@ proc track(tracked: PEffects, n: PNode) = track(tracked, last) for i in 0 .. child.len-3: initVar(tracked, child.sons[i]) + addAsgnFact(tracked.guards, child.sons[i], last) notNilCheck(tracked, last, child.sons[i].typ) # since 'var (a, b): T = ()' is not even allowed, there is always type # inference for (a, b) and thus no nil checking is necessary. @@ -523,6 +531,7 @@ proc track(tracked: PEffects, n: PNode) = if sfDiscriminant in x.sons[0].sym.flags: addDiscriminantFact(tracked.guards, x) setLen(tracked.guards, oldFacts) + of nkTypeSection: discard else: for i in 0 .. <safeLen(n): track(tracked, n.sons[i]) |