summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/sem.nim2
-rw-r--r--compiler/semexprs.nim5
-rw-r--r--compiler/sempass2.nim5
-rw-r--r--tests/constructors/tinvalid_construction.nim5
4 files changed, 10 insertions, 7 deletions
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 3a4ff2cd9..07b765f88 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -584,7 +584,7 @@ proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
     result = buildEchoStmt(c, result)
   if c.config.cmd == cmdIdeTools:
     appendToModule(c.module, result)
-  trackTopLevelStmt(c, c.module, result)
+  trackStmt(c, c.module, result, isTopLevel = true)
 
 proc recoverContext(c: PContext) =
   # clean up in case of a semantic error: We clean up the stacks, etc. This is
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index d4f33eb41..5484f4594 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -2082,7 +2082,10 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   var err: string
   try:
     result = semExpr(c, n, flags)
-    if c.config.errorCounter != oldErrorCount: result = nil
+    if result != nil:
+      trackStmt(c, c.module, result, isTopLevel = false)
+    if c.config.errorCounter != oldErrorCount:
+      result = nil
   except ERecoverableError:
     discard
   # undo symbol table changes (as far as it's possible):
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index 2d5e3e721..3ad0a1931 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -996,6 +996,7 @@ proc track(tracked: PEffects, n: PNode) =
         createTypeBoundOps(tracked, x[1].typ, n.info)
 
       if x.kind == nkExprColonExpr:
+        notNilCheck(tracked, x[1], x[0].sym.typ)
         checkForSink(tracked.config, tracked.owner, x[1])
       else:
         checkForSink(tracked.config, tracked.owner, x)
@@ -1260,7 +1261,7 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) =
       dataflowAnalysis(s, body)
       when false: trackWrites(s, body)
 
-proc trackTopLevelStmt*(c: PContext; module: PSym; n: PNode) =
+proc trackStmt*(c: PContext; module: PSym; n: PNode, isTopLevel: bool) =
   if n.kind in {nkPragma, nkMacroDef, nkTemplateDef, nkProcDef, nkFuncDef,
                 nkTypeSection, nkConverterDef, nkMethodDef, nkIteratorDef}:
     return
@@ -1268,5 +1269,5 @@ proc trackTopLevelStmt*(c: PContext; module: PSym; n: PNode) =
   var effects = newNode(nkEffectList, n.info)
   var t: TEffects
   initEffects(g, effects, module, t, c)
-  t.isTopLevel = true
+  t.isTopLevel = isTopLevel
   track(t, n)
diff --git a/tests/constructors/tinvalid_construction.nim b/tests/constructors/tinvalid_construction.nim
index eb84c53c8..e6fdbcb85 100644
--- a/tests/constructors/tinvalid_construction.nim
+++ b/tests/constructors/tinvalid_construction.nim
@@ -75,7 +75,7 @@ type
 
 var x = D
 var nilRef: TRefObj
-var notNilRef = TRefObj(x: 20)
+let notNilRef = TRefObjNotNil(x: 20)
 
 proc makeHasNotNils: ref THasNotNils =
   (ref THasNotNils)(a: TRefObj(x: 10),
@@ -102,8 +102,7 @@ reject TObj(a: 10, f: "")       # conflicting fields
 accept TObj(choice: E, e1: TRefObj(x: 10), e2: 10)
 
 accept THasNotNils(a: notNilRef, b: notNilRef, c: nilRef)
-# XXX: the "not nil" logic in the compiler is not strong enough to catch this one yet:
-# reject THasNotNils(a: notNilRef, b: nilRef, c: nilRef)
+reject THasNotNils(a: notNilRef, b: nilRef, c: nilRef)      # `b` shouldn't be nil
 reject THasNotNils(b: notNilRef, c: notNilRef)              # there is a missing not nil field
 reject THasNotNils()                                        # again, missing fields
 accept THasNotNils(a: notNilRef, b: notNilRef)              # it's OK to omit a non-mandatory field