summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/cgmeth.nim10
-rw-r--r--lib/pure/segfaults.nim4
-rw-r--r--lib/system.nim8
-rw-r--r--lib/system/chcks.nim6
-rw-r--r--lib/system/jssys.nim4
-rw-r--r--web/news/e031_version_0_16_2.rst3
6 files changed, 26 insertions, 9 deletions
diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim
index d05e395b9..e14306e56 100644
--- a/compiler/cgmeth.nim
+++ b/compiler/cgmeth.nim
@@ -229,6 +229,7 @@ proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym =
   var base = lastSon(methods[0].ast).sym
   result = base
   var paramLen = sonsLen(base.typ)
+  var nilchecks = newNodeI(nkStmtList, base.info)
   var disp = newNodeI(nkIfStmt, base.info)
   var ands = getSysSym("and")
   var iss = getSysSym("of")
@@ -239,7 +240,11 @@ proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym =
       if contains(relevantCols, col):
         var isn = newNodeIT(nkCall, base.info, getSysType(tyBool))
         addSon(isn, newSymNode(iss))
-        addSon(isn, newSymNode(base.typ.n.sons[col].sym))
+        let param = base.typ.n.sons[col].sym
+        addSon(isn, newSymNode(param))
+        if param.typ.skipTypes(abstractInst).kind in {tyRef, tyPtr}:
+          addSon(nilchecks, newTree(nkCall,
+                newSymNode(getCompilerProc"chckNilDisp"), newSymNode(param)))
         addSon(isn, newNodeIT(nkType, base.info, curr.typ.sons[col]))
         if cond != nil:
           var a = newNodeIT(nkCall, base.info, getSysType(tyBool))
@@ -270,7 +275,8 @@ proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym =
       addSon(disp, a)
     else:
       disp = ret
-  result.ast.sons[bodyPos] = disp
+  nilchecks.add disp
+  result.ast.sons[bodyPos] = nilchecks
 
 proc generateMethodDispatchers*(g: ModuleGraph): PNode =
   result = newNode(nkStmtList)
diff --git a/lib/pure/segfaults.nim b/lib/pure/segfaults.nim
index 3823d037c..373508430 100644
--- a/lib/pure/segfaults.nim
+++ b/lib/pure/segfaults.nim
@@ -13,10 +13,6 @@
 ##
 ## Tested on these OSes: Linux, Windows, OSX
 
-type
-  NilAccessError* = object of SystemError ## \
-    ## Raised on dereferences of ``nil`` pointers.
-
 # do allocate memory upfront:
 var se: ref NilAccessError
 new(se)
diff --git a/lib/system.nim b/lib/system.nim
index 94e10d7df..371cf8544 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -558,6 +558,10 @@ type
     ## Raised if it is attempted to send a message to a dead thread.
     ##
     ## See the full `exception hierarchy <manual.html#exception-handling-exception-hierarchy>`_.
+  NilAccessError* = object of SystemError ## \
+    ## Raised on dereferences of ``nil`` pointers.
+    ##
+    ## This is only raised if the ``segfaults.nim`` module was imported!
 
 {.deprecated: [TObject: RootObj, PObject: RootRef, TEffect: RootEffect,
   FTime: TimeEffect, FIO: IOEffect, FReadIO: ReadIOEffect,
@@ -2467,8 +2471,8 @@ template accumulateResult*(iter: untyped) =
 const NimStackTrace = compileOption("stacktrace")
 
 template coroutinesSupportedPlatform(): bool =
-  when defined(sparc) or defined(ELATE) or compileOption("gc", "v2") or 
-    defined(boehmgc) or defined(gogc) or defined(nogc) or defined(gcStack) or 
+  when defined(sparc) or defined(ELATE) or compileOption("gc", "v2") or
+    defined(boehmgc) or defined(gogc) or defined(nogc) or defined(gcStack) or
     defined(gcMarkAndSweep):
     false
   else:
diff --git a/lib/system/chcks.nim b/lib/system/chcks.nim
index 27a3708ea..1520f231e 100644
--- a/lib/system/chcks.nim
+++ b/lib/system/chcks.nim
@@ -50,7 +50,11 @@ proc chckRangeF(x, a, b: float): float =
 
 proc chckNil(p: pointer) =
   if p == nil:
-    sysFatal(ValueError, "attempt to write to a nil address")
+    sysFatal(NilAccessError, "attempt to write to a nil address")
+
+proc chckNilDisp(p: pointer) {.compilerproc.} =
+  if p == nil:
+    sysFatal(NilAccessError, "cannot dispatch; dispatcher is nil")
 
 proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
   # checks if obj is of type subclass:
diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim
index 39ce1183b..9ef4a02f2 100644
--- a/lib/system/jssys.nim
+++ b/lib/system/jssys.nim
@@ -642,6 +642,10 @@ proc toU32*(a: int64): int32 {.asmNoStackFrame, compilerproc.} =
 proc nimMin(a, b: int): int {.compilerproc.} = return if a <= b: a else: b
 proc nimMax(a, b: int): int {.compilerproc.} = return if a >= b: a else: b
 
+proc chckNilDisp(p: pointer) {.compilerproc.} =
+  if p == nil:
+    sysFatal(NilAccessError, "cannot dispatch; dispatcher is nil")
+
 type NimString = string # hack for hti.nim
 include "system/hti"
 
diff --git a/web/news/e031_version_0_16_2.rst b/web/news/e031_version_0_16_2.rst
index 35f3716a3..8517dacb0 100644
--- a/web/news/e031_version_0_16_2.rst
+++ b/web/news/e031_version_0_16_2.rst
@@ -42,6 +42,9 @@ Changes affecting backwards compatibility
   AST that is the same as what is used to define an enum.  Previously the AST
   returned had a repeated ``EnumTy`` node and was missing the initial pragma
   node (which is currently empty for an enum).
+- If the dispatcher parameter's value used in multi method is ``nil``,
+  a ``NilError`` exception is raised. The old behavior was that the method
+  would be a ``nop`` then.
 
 
 Library Additions