Skip to content

Commit 118232e

Browse files
authored
not nil: progress (#1095)
1 parent 73c7761 commit 118232e

File tree

11 files changed

+105
-20
lines changed

11 files changed

+105
-20
lines changed

src/hexer/duplifier.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ proc trNewobj(c: var Context; n: var Cursor; e: Expects; kind: ExprKind) =
680680

681681
let baseType = refType.firstSon
682682
var refTypeCopy = refType
683-
let typeKey = takeMangle(refTypeCopy, c.lifter.bits)
683+
let typeKey = takeMangle(refTypeCopy, Frontend, c.lifter.bits)
684684
let typeSym = pool.syms.getOrIncl(typeKey & GeneratedTypeSuffix)
685685

686686
copyIntoKind c.dest, CastX, info:

src/hexer/lifter.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ proc requestLifting(c: var LiftingCtx; op: AttachedOp; t: TypeCursor): SymId =
188188
if result != SymId(0):
189189
return result
190190

191-
let key = mangle(t, c.bits)
191+
let key = mangle(t, Frontend, c.bits)
192192
result = c.structuralTypeToHook[op].getOrDefault(key)
193193
if result == SymId(0):
194194
let name = generateHookName(c, op, key)

src/hexer/nifcgen.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ proc trAsNamedType(c: var EContext; n: var Cursor) =
330330
let info = n.info
331331
var body = n
332332
let k = body.typeKind
333-
let key = takeMangle(n, c.bits)
333+
let key = takeMangle(n, Backend, c.bits)
334334

335335
var val = c.newTypes.getOrDefault(key)
336336
if val == SymId(0):

src/nimony/contracts.nim

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type
4040
directlyInitialized: HashSet[SymId]
4141
startInstr: Cursor
4242
errors: TokenBuf
43+
procCanRaise: bool
4344

4445
proc 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+
633641
proc 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)

src/nimony/sem.nim

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3285,7 +3285,15 @@ proc semLocalTypeImpl(c: var SemContext; n: var Cursor; context: TypeDeclContext
32853285
c.dest.addDotToken()
32863286
else:
32873287
takeTree c, n
3288-
of PtrT, RefT, MutT, OutT, LentT, SinkT, NotT, UarrayT,
3288+
of PtrT, RefT:
3289+
if tryTypeClass(c, n):
3290+
return
3291+
takeToken c, n
3292+
semLocalTypeImpl c, n, InLocalDecl
3293+
if n.kind != ParRi:
3294+
takeTree c, n # notnil, nil
3295+
takeParRi c, n
3296+
of MutT, OutT, LentT, SinkT, NotT, UarrayT,
32893297
StaticT, TypedescT:
32903298
if tryTypeClass(c, n):
32913299
return

src/nimony/typekeys.nim

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ include nifprelude
99
import ".." / nimony / nimony_model
1010
import treemangler
1111

12-
proc mangleImpl(b: var Mangler; c: var Cursor) =
12+
type
13+
MangleMode* = enum
14+
Backend, Frontend
15+
16+
proc mangleImpl(b: var Mangler; c: var Cursor; mm: MangleMode) =
1317
var nested = 0
1418
while true:
1519
case c.kind
@@ -20,13 +24,13 @@ proc mangleImpl(b: var Mangler; c: var Cursor) =
2024
skip c # name
2125
skip c # export marker
2226
skip c # pragmas
23-
mangleImpl b, c # type is interesting
27+
mangleImpl b, c, mm # type is interesting
2428
skip c # value
2529
inc c # ParRi
2630
elif tag == "array":
2731
b.addTree tag
2832
inc c
29-
mangleImpl b, c # type is interesting
33+
mangleImpl b, c, mm # type is interesting
3034
if c.kind == ParLe and c.typeKind == RangetypeT:
3135
inc c # RangeT
3236
skip c # type is irrelevant, we care about the length
@@ -39,7 +43,7 @@ proc mangleImpl(b: var Mangler; c: var Cursor) =
3943
inc c # ParRi
4044
b.addIntLit(last - first + 1)
4145
else:
42-
mangleImpl b, c
46+
mangleImpl b, c, mm
4347
inc nested
4448
elif tag == "tuple":
4549
b.addTree(tag)
@@ -48,10 +52,10 @@ proc mangleImpl(b: var Mangler; c: var Cursor) =
4852
if c.substructureKind == KvU:
4953
inc c
5054
skip c # name
51-
mangleImpl b, c # type is interesting
55+
mangleImpl b, c, mm # type is interesting
5256
inc c # ParRi
5357
else:
54-
mangleImpl b, c
58+
mangleImpl b, c, mm
5559
b.endTree()
5660
inc c # ParRi
5761
elif tag == "u" or tag == "i" or tag == "f":
@@ -66,6 +70,15 @@ proc mangleImpl(b: var Mangler; c: var Cursor) =
6670
b.addIntLit(bits)
6771
inc c
6872
inc nested
73+
elif mm == Backend and tag in ["ref", "ptr"]:
74+
b.addTree(tag)
75+
inc c
76+
mangleImpl b, c, mm
77+
if c.kind != ParRi:
78+
skip c
79+
assert c.kind == ParRi
80+
b.endTree()
81+
inc c
6982
else:
7083
b.addTree(tag)
7184
inc nested
@@ -109,15 +122,15 @@ proc mangleImpl(b: var Mangler; c: var Cursor) =
109122
inc c
110123
if nested == 0: break
111124

112-
proc takeMangle*(c: var Cursor; bits = -1): string =
125+
proc takeMangle*(c: var Cursor; mm: MangleMode; bits = -1): string =
113126
var b = createMangler(30, bits)
114-
mangleImpl b, c
127+
mangleImpl b, c, mm
115128
result = b.extract()
116129

117-
proc mangle*(c: Cursor; bits = -1): string =
130+
proc mangle*(c: Cursor; mm: MangleMode; bits = -1): string =
118131
var c = c
119-
takeMangle c, bits
132+
takeMangle c, mm, bits
120133

121-
proc mangle*(b: var Mangler; c: Cursor) =
134+
proc mangle*(b: var Mangler; c: Cursor; mm: MangleMode) =
122135
var c = c
123-
mangleImpl b, c
136+
mangleImpl b, c, mm

src/nimony/vtables_frontend.nim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ proc methodKey*(name: string; a: Cursor): string =
6868
var b = createMangler(60)
6969
while a.kind != ParRi:
7070
let pa = takeLocal(a, SkipFinalParRi)
71-
mangle b, pa.typ
71+
mangle b, pa.typ, Frontend
7272
inc a
7373
# also add return type:
74-
mangle b, a
74+
mangle b, a, Frontend
7575
skip a
7676
let (callConv, hasRaises) = processPragmas(a)
7777
result = name & ":" & b.extract() & ":" & $callConv & ":" & hasRaises
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
import std / syncio
3+
4+
type
5+
Myref = ref object
6+
x: int
7+
8+
proc p(): Myref not nil {.raises.} = Myref(x: 5)
9+
10+
proc hah {.raises.} =
11+
var r: Myref not nil
12+
r = p()
13+
echo r[].x
14+
15+
try:
16+
hah()
17+
except:
18+
echo "god riddance"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
5

tests/nimony/notnil/tnilref.nim

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
import std / syncio
3+
4+
type
5+
Myref = ref object
6+
x: int
7+
8+
proc p(): Myref not nil {.raises.} = Myref(x: 5)
9+
10+
proc hah2 {.raises.} =
11+
var r: nil Myref
12+
r = p()
13+
echo r[].x
14+
15+
proc other =
16+
var r: nil Myref = nil
17+
if r != nil:
18+
echo r[].x
19+
else:
20+
echo "is nil"
21+
22+
try:
23+
hah2()
24+
other()
25+
except:
26+
echo "god riddance"

0 commit comments

Comments
 (0)