diff options
-rw-r--r-- | compiler/sem.nim | 2 | ||||
-rw-r--r-- | compiler/semexprs.nim | 5 | ||||
-rw-r--r-- | compiler/sempass2.nim | 5 | ||||
-rw-r--r-- | tests/constructors/tinvalid_construction.nim | 5 |
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 |