diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 04f4c47292bd7..87f7da815b21f 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 e63585f6366c7..8dc1b8cf2d6b8 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 c141985d35975..727a75288028f 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 8471ea148a4bd..f99f09799d099 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.}