4040 directlyInitialized: HashSet [SymId ]
4141 startInstr: Cursor
4242 errors: TokenBuf
43+ procCanRaise: bool
4344
4445proc buildErr (c: var Context ; info: PackedLineInfo ; msg: string ) =
4546 when defined (debug):
@@ -273,7 +274,10 @@ proc wantNotNil(c: var Context; n: Cursor) =
273274 else :
274275 let r = analysableRoot (c, n)
275276 if r == NoSymId :
276- buildErr c, n.info, " cannot analyze expression is not nil: " & asNimCode (n)
277+ if n.exprKind == NewobjX and c.procCanRaise:
278+ discard " fine, nil value is mapped to OOM by the compiler"
279+ else :
280+ buildErr c, n.info, " cannot analyze expression is not nil: " & asNimCode (n)
277281 else :
278282 let fact = inferle.isNotNil (VarId r)
279283 if implies (c.facts, fact):
@@ -630,6 +634,10 @@ proc addAsgnFact(c: var Context; fact: LeXplusC) =
630634 c.facts.add fact
631635 c.facts.add fact.geXplusC
632636
637+ proc cannotBeNil (c: var Context ; n: Cursor ): bool {.inline .} =
638+ let t = getType (c.typeCache, n)
639+ result = markedAs (t, NotnilU )
640+
633641proc analyseAsgn (c: var Context ; pc: var Cursor ) =
634642 inc pc # skip asgn instruction
635643 let expected = getType (c.typeCache, pc)
@@ -645,6 +653,7 @@ proc analyseAsgn(c: var Context; pc: var Cursor) =
645653 # after `x = 4` we know two facts: `x >= 4` and `x <= 4`
646654 inc pc
647655 checkNilMatch c, pc, expected
656+ let rhs = pc
648657 if rightHandSide (c, pc, fact):
649658 if fact.a == fact.b:
650659 variableChangedByDiff (c.facts, fact.a, fact.c)
@@ -653,6 +662,10 @@ proc analyseAsgn(c: var Context; pc: var Cursor) =
653662 addAsgnFact c, fact
654663 else :
655664 invalidateFactsAbout (c.facts, fact.a)
665+
666+ if (rhs.exprKind == NewobjX and c.procCanRaise) or cannotBeNil (c, rhs):
667+ # we know: x != nil after the assignment:
668+ c.facts.add isNotNil (fact.a)
656669 else :
657670 analyseExpr c, pc
658671 checkNilMatch c, pc, expected
@@ -861,10 +874,14 @@ proc checkContracts(c: var Context; n: Cursor) =
861874 # echo "CF IS ", codeListing(c.cf)
862875
863876 c.startInstr = readonlyCursorAt (c.cf, 0 )
877+ c.procCanRaise = false
864878 var body = c.startInstr
865879 if body.stmtKind in {ProcS , FuncS , IteratorS , ConverterS , MethodS , MacroS }:
866880 inc body
867- for i in 0 ..< BodyPos : skip body
881+ for i in 0 ..< BodyPos :
882+ if i == ProcPragmasPos :
883+ c.procCanRaise = hasPragma (body, RaisesP )
884+ skip body
868885
869886 var current = BasicBlockIdx (cursorToPosition (c.cf, body))
870887 var bbs = computeBasicBlocks (c.cf, current.int )
0 commit comments