summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorTimothee Cour <timothee.cour2@gmail.com>2021-02-05 07:32:10 -0800
committerGitHub <noreply@github.com>2021-02-05 16:32:10 +0100
commit3eebbb234d6c2ed27c00e97fae5b60805b29e91b (patch)
treedd4ed8ff07356c2f7286fa8bef4e2e8ade05675b
parent6dc7ece36a45d3993500e7e4fa1d1815575caed1 (diff)
downloadNim-3eebbb234d6c2ed27c00e97fae5b60805b29e91b.tar.gz
fix `of` procs + runnableExamples (#16932)
-rw-r--r--lib/system.nim33
1 files changed, 25 insertions, 8 deletions
diff --git a/lib/system.nim b/lib/system.nim
index d036e8428..371611f70 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -904,14 +904,31 @@ template disarm*(x: typed) =
   ## experimental API!
   x = nil
 
-proc `of`*[T, S](x: typedesc[T], y: typedesc[S]): bool {.magic: "Of", noSideEffect.}
-proc `of`*[T, S](x: T, y: typedesc[S]): bool {.magic: "Of", noSideEffect.}
-proc `of`*[T, S](x: T, y: S): bool {.magic: "Of", noSideEffect.}
-  ## Checks if `x` has a type of `y`.
-  ##
-  ## .. code-block:: Nim
-  ##   assert(FloatingPointDefect of Exception)
-  ##   assert(DivByZeroDefect of Exception)
+proc `of`*[T, S](x: T, y: typedesc[S]): bool {.magic: "Of", noSideEffect.} =
+  ## Checks if `x` is an instance of `y`.
+  runnableExamples:
+    type
+      Base = ref object of RootObj
+      Sub1 = ref object of Base
+      Sub2 = ref object of Base
+      Unrelated = ref object
+
+    var base: Base = Sub1() # downcast
+    doAssert base of Base # generates `CondTrue` (statically true)
+    doAssert base of Sub1
+    doAssert base isnot Sub1
+    doAssert not (base of Sub2)
+
+    base = Sub2() # re-assign
+    doAssert base of Sub2
+    doAssert Sub2(base) != nil # upcast
+    doAssertRaises(ObjectConversionDefect): discard Sub1(base)
+
+    var sub1 = Sub1()
+    doAssert sub1 of Base
+    doAssert sub1.Base of Sub1
+
+    doAssert not compiles(base of Unrelated)
 
 proc cmp*[T](x, y: T): int =
   ## Generic compare proc.