summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semmagic.nim5
-rw-r--r--lib/pure/typetraits.nim17
-rw-r--r--lib/std/jsonutils.nim4
-rw-r--r--lib/system/repr_v2.nim2
4 files changed, 18 insertions, 10 deletions
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 04f4c4729..87f7da815 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -190,9 +190,10 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym)
     result = newIntNodeT(toInt128(operand.len), traitCall, c.idgen, c.graph)
   of "distinctBase":
     var arg = operand.skipTypes({tyGenericInst})
+    let rec = semConstExpr(c, traitCall[2]).intVal != 0
     while arg.kind == tyDistinct:
-      arg = arg.base
-      arg = arg.skipTypes(skippedTypes + {tyGenericInst})
+      arg = arg.base.skipTypes(skippedTypes + {tyGenericInst})
+      if not rec: break
     result = getTypeDescNode(c, arg, operand.owner, traitCall.info)
   else:
     localError(c.config, traitCall.info, "unknown trait: " & s)
diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim
index e63585f63..8dc1b8cf2 100644
--- a/lib/pure/typetraits.nim
+++ b/lib/pure/typetraits.nim
@@ -110,25 +110,32 @@ template pointerBase*[T](_: typedesc[ptr T | ref T]): typedesc =
     assert (var s = "abc"; s[0].addr).typeof.pointerBase is char
   T
 
-proc distinctBase*(T: typedesc): typedesc {.magic: "TypeTrait".} =
+proc distinctBase*(T: typedesc, recursive: static bool = true): typedesc {.magic: "TypeTrait".} =
   ## Returns the base type for distinct types, or the type itself otherwise.
+  ## If `recursive` is false, only the immediate distinct base will be returned.
   ##
   ## **See also:**
-  ## * `distinctBase template <#distinctBase.t,T>`_
+  ## * `distinctBase template <#distinctBase.t,T,static[bool]>`_
   runnableExamples:
     type MyInt = distinct int
+    type MyOtherInt = distinct MyInt
     doAssert distinctBase(MyInt) is int
+    doAssert distinctBase(MyOtherInt) is int
+    doAssert distinctBase(MyOtherInt, false) is MyInt
     doAssert distinctBase(int) is int
 
 since (1, 1):
-  template distinctBase*[T](a: T): untyped =
-    ## Overload of `distinctBase <#distinctBase,typedesc>`_ for values.
+  template distinctBase*[T](a: T, recursive: static bool = true): untyped =
+    ## Overload of `distinctBase <#distinctBase,typedesc,static[bool]>`_ for values.
     runnableExamples:
       type MyInt = distinct int
+      type MyOtherInt = distinct MyInt
       doAssert 12.MyInt.distinctBase == 12
+      doAssert 12.MyOtherInt.distinctBase == 12
+      doAssert 12.MyOtherInt.distinctBase(false) is MyInt
       doAssert 12.distinctBase == 12
     when T is distinct:
-      distinctBase(typeof(a))(a)
+      distinctBase(typeof(a), recursive)(a)
     else: # avoids hint ConvFromXtoItselfNotNeeded
       a
 
diff --git a/lib/std/jsonutils.nim b/lib/std/jsonutils.nim
index c141985d3..727a75288 100644
--- a/lib/std/jsonutils.nim
+++ b/lib/std/jsonutils.nim
@@ -78,8 +78,8 @@ proc initToJsonOptions*(): ToJsonOptions =
   ## initializes `ToJsonOptions` with sane options.
   ToJsonOptions(enumMode: joptEnumOrd, jsonNodeMode: joptJsonNodeAsRef)
 
-proc distinctBase(T: typedesc): typedesc {.magic: "TypeTrait".}
-template distinctBase[T](a: T): untyped = distinctBase(typeof(a))(a)
+proc distinctBase(T: typedesc, recursive: static bool = true): typedesc {.magic: "TypeTrait".}
+template distinctBase[T](a: T, recursive: static bool = true): untyped = distinctBase(typeof(a), recursive)(a)
 
 macro getDiscriminants(a: typedesc): seq[string] =
   ## return the discriminant keys
diff --git a/lib/system/repr_v2.nim b/lib/system/repr_v2.nim
index 8471ea148..f99f09799 100644
--- a/lib/system/repr_v2.nim
+++ b/lib/system/repr_v2.nim
@@ -1,7 +1,7 @@
 proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
   ## imported from typetraits
 
-proc distinctBase(T: typedesc): typedesc {.magic: "TypeTrait".}
+proc distinctBase(T: typedesc, recursive: static bool = true): typedesc {.magic: "TypeTrait".}
   ## imported from typetraits
 
 proc repr*(x: NimNode): string {.magic: "Repr", noSideEffect.}