mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-28 09:31:38 +00:00
* Nil checking * Enable current older not nil checking again, run new checking only under flag, skip our test * Enable tests, work on try/except and bugs, fix notnil tests * Enable strictNotNil tests (currently with lowercase category) and add some expected output * Work on try/except/finally: still some things unclear and a lot of code can raise out of try * Fix the notnil build by going back to the old version of a test which I shouldn't have changed * Fix test : use action compile * Work on mutation and aliasing: not finished * Render var parititions graph, try to understand it, fix a nilcheck if bug * Rebase, progress on working with partitions * Improve time logic * Fix some bugs, use graph indices instead of symbol in nil map * Fix bugs, test simpler ident aliasing for now, support two mutation levels * Support ContentMutation and ReAssignment: for now just detect possible re assignment for var parameters of calls * Enable several simple passing tests * Cleanup a bit, fix condition/branch infix-related bug * Remove some files, address some comments by Araq * Use internalError and no quit for now * Separate tests with expected warnings and with expected ok, fix a bug with if with a single branch related to copyMap * Fix new data structures, bugs: make tests pass, disable some for now * Work on fixing errors with non-sym nodes, aliasing: tests fail * Work on alias support: simple set-based logic, todo more tests and ref sets? * Use ref sets: TODO can we think of handle seq-s similar to varpartitions' Araq ones * Handle defers in one place, stop raising in reverse to make an async test compile with strictNotNil, add a commented out test * Dot expressions: call/reassignment. Other refactorings and distinct, SeqOfDistinct support. Checkout an older varpartitions * Work on field tracking * Backup : trying to fix bugs when running some stdlib stuff for running an async test * Start a section about strict not nil checking in experimental manual * Fix experimental strict not nil manual section and move it to another file based on Araq feedback * Fix unstructured flow and double warning problems, fix manual, cleanup * Fix if/elif/else : take in account structure according to Araq feedback * Refactor a bit * Work on bracket expr support, re-enable tests, clarify in manual/tests/implementation static index support for now * Work on compiling stdlib and compiler with strictNotNil * Small fixes to the manual for strictNotNil * Fix idgen for strict check nil rebase * Enable some simple tests, remove old stuff, comment out code/print * Copy the original varpartitions source instead of my changes * Remove some files
183 lines
4.0 KiB
Nim
183 lines
4.0 KiB
Nim
discard """
|
|
cmd: "nim check --warningAsError:StrictNotNil $file"
|
|
action: "compile"
|
|
"""
|
|
|
|
import tables
|
|
|
|
{.experimental: "strictNotNil".}
|
|
|
|
type
|
|
Nilable* = ref object
|
|
a*: int
|
|
field*: Nilable
|
|
|
|
NonNilable* = Nilable not nil
|
|
|
|
Nilable2* = nil NonNilable
|
|
|
|
|
|
# proc `[]`(a: Nilable, b: int): Nilable =
|
|
# nil
|
|
|
|
|
|
# Nilable tests
|
|
|
|
|
|
|
|
# # test and
|
|
proc testAnd(a: Nilable) =
|
|
echo not a.isNil and a.a > 0 # ok
|
|
|
|
|
|
# test else branch and inferring not isNil
|
|
# proc testElse(a: Nilable, b: int) =
|
|
# if a.isNil:
|
|
# echo 0
|
|
# else:
|
|
# echo a.a
|
|
|
|
# test that here we can infer that n can't be nil anymore
|
|
proc testNotNilAfterAssign(a: Nilable, b: int) =
|
|
var n = a # a: MaybeNil n: MaybeNil
|
|
if n.isNil: # n: Safe a: MaybeNil
|
|
n = Nilable() # n: Safe a: MaybeNil
|
|
echo n.a # ok
|
|
|
|
proc callVar(a: var Nilable) =
|
|
a = nil
|
|
|
|
proc testVarAlias(a: Nilable) = # a: 0 aliasA: 1 {0} {1}
|
|
var aliasA = a # {0, 1} 0 MaybeNil 1 MaybeNil
|
|
if not a.isNil: # {0, 1} 0 Safe 1 Safe
|
|
callVar(aliasA) # {0, 1} 0 MaybeNil 1 MaybeNil
|
|
# if aliasA stops being in alias: it might be nil, but then a is still not nil
|
|
# if not: it cant be nil as it still points here
|
|
echo a.a # ok
|
|
|
|
proc testAliasCheck(a: Nilable) =
|
|
var aliasA = a
|
|
if not a.isNil:
|
|
echo aliasA.a # ok
|
|
|
|
proc testFieldCheck(a: Nilable) =
|
|
if not a.isNil and not a.field.isNil:
|
|
echo a.field.a # ok
|
|
|
|
proc testTrackField =
|
|
var a = Nilable(field: Nilable())
|
|
echo a.field.a # ok
|
|
|
|
proc testNonNilDeref(a: NonNilable) =
|
|
echo a.a # ok
|
|
|
|
# # not only calls: we can use partitions for dependencies for field aliases
|
|
# # so we can detect on change what does this affect or was this mutated between us and the original field
|
|
|
|
|
|
# proc testUniqueHashTree(a: Nilable): Nilable =
|
|
# # TODO what would be a clash
|
|
# var field = 0
|
|
# if not a.isNil and not a.field.isNil:
|
|
# # echo a.field.a
|
|
# echo a[field].a
|
|
# result = Nilable()
|
|
|
|
proc testSeparateShadowingResult(a: Nilable): Nilable =
|
|
result = Nilable()
|
|
if not a.isNil:
|
|
var result: Nilable = nil
|
|
echo result.a
|
|
|
|
|
|
proc testNonNilCString(a: cstring not nil) =
|
|
echo a[0] # ok
|
|
|
|
proc testNonNilPtr(a: ptr int not nil) =
|
|
echo a[] # ok
|
|
|
|
|
|
# proc testTryCatchDetectNoRaise(a: Nilable) =
|
|
# var other = Nilable()
|
|
# try:
|
|
# other = nil
|
|
# other = a
|
|
# other = Nilable()
|
|
# except:
|
|
# other = nil
|
|
# echo other.a # ok
|
|
|
|
# proc testTryCatchDetectFinally =
|
|
# var other = Nilable()
|
|
# try:
|
|
# other = nil
|
|
# other = Nilable()
|
|
# except:
|
|
# other = Nilable()
|
|
# finally:
|
|
# other = nil
|
|
# echo other.a # can't deref other: it is nil
|
|
|
|
# proc testTryCatchDetectNilableWithRaise(b: bool) =
|
|
# var other = Nilable()
|
|
# try:
|
|
# if b:
|
|
# other = nil
|
|
# else:
|
|
# other = Nilable()
|
|
# var other2 = raiseCall()
|
|
# except:
|
|
# echo other.a # ok
|
|
|
|
# echo other.a # can't deref a: it might be nil
|
|
|
|
proc testRaise(a: Nilable) =
|
|
if a.isNil:
|
|
raise newException(ValueError, "a == nil")
|
|
echo a.a # ok
|
|
|
|
# proc testBlockScope(a: Nilable) =
|
|
# var other = a
|
|
# block:
|
|
# var other = Nilable()
|
|
# echo other.a # ok
|
|
# echo other.a # can't deref other: it might be nil
|
|
|
|
# # (ask Araq about this: not supported yet) ok we can't really get the nil value from here, so should be ok
|
|
# proc testDirectRaiseCall: NonNilable =
|
|
# var a = raiseCall()
|
|
# result = NonNilable()
|
|
|
|
proc testStmtList =
|
|
var a = Nilable()
|
|
block:
|
|
a = nil
|
|
a = Nilable()
|
|
echo a.a # ok
|
|
|
|
proc testItemDerefNoWarning(a: var seq[Nilable]) =
|
|
a[0] = Nilable() # good: now .. if we dont track, how do we know
|
|
echo a[0].a # ok
|
|
var b = 1
|
|
|
|
const c = 0
|
|
a[c] = Nilable()
|
|
echo a[0].a # ok
|
|
|
|
# proc callChange(a: Nilable) =
|
|
# a.field = nil
|
|
|
|
# proc testCallAlias =
|
|
# var a = Nilable(field: Nilable())
|
|
# callChange(a)
|
|
# echo a.field.a # can't deref a.field, it might be nil
|
|
|
|
# # proc test10(a: Nilable) =
|
|
# # if not a.isNil and not a.b.isNil:
|
|
# # c_memset(globalA.addr, 0, globalA.sizeOf.csize_t)
|
|
# # globalA = nil
|
|
# # echo a.a # can't deref a: it might be nil
|
|
|
|
var nilable: Nilable
|
|
var withField = Nilable(a: 0, field: Nilable())
|