mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-31 20:49:06 +00:00
unwrap typedesc in semSet to enable stuff like set[T.distinctBase] (#25924)
`distinctBase` results in typedesc, so `set[T.distinctBase]` received `typedesc[range[...]]` as its element type, which `isOrdinalType` rejects. Strip the wrapper in `semSet` before storing the element type and checking ordinality. Also add `tyFromExpr` to the deferred-check set so the error doesn't fire prematurely inside generic bodies - same pattern already used by `semArray`.
This commit is contained in:
@@ -219,9 +219,10 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = newOrPrevType(tySet, prev, c)
|
||||
if n.len == 2 and n[1].kind != nkEmpty:
|
||||
var base = semTypeNode(c, n[1], nil)
|
||||
if base.kind == tyTypeDesc: base = base.base # unwrap from type traits like distinctBase
|
||||
addSonSkipIntLit(result, base, c.idgen)
|
||||
if base.kind in {tyGenericInst, tyAlias, tySink}: base = skipModifier(base)
|
||||
if base.kind notin {tyGenericParam, tyGenericInvocation}:
|
||||
if base.kind notin {tyGenericParam, tyGenericInvocation, tyFromExpr}:
|
||||
if base.kind == tyForward:
|
||||
c.forwardTypeUpdates.add (getCurrOwner(c), result, n)
|
||||
elif not isOrdinalType(base, allowEnumWithHoles = true):
|
||||
|
||||
39
tests/set/tset_range_trait.nim
Normal file
39
tests/set/tset_range_trait.nim
Normal file
@@ -0,0 +1,39 @@
|
||||
# Test that set[] accepts range types via typedesc[R], and set[typedesc[R]]
|
||||
# must unwrap the typedesc wrapper before checking ordinality.
|
||||
|
||||
import std/typetraits
|
||||
|
||||
type
|
||||
TestDistinctRange = distinct range[0 .. 63]
|
||||
|
||||
block: # explicit range type as set base
|
||||
type S = set[range[0 .. 63]]
|
||||
var s: S = {0, 1}
|
||||
doAssert 0 in s
|
||||
|
||||
block: # distinctBase result as set base (non-generic)
|
||||
type S = set[TestDistinctRange.distinctBase]
|
||||
var s: S = {0, 1}
|
||||
doAssert 0 in s
|
||||
|
||||
block: # range alias as set base
|
||||
type RangeAlias = range[0 .. 63]
|
||||
type S = set[RangeAlias]
|
||||
var s: S = {0, 1}
|
||||
doAssert 0 in s
|
||||
|
||||
block: # set[T.distinctBase] in generic body type position
|
||||
proc test[T: TestDistinctRange]() =
|
||||
var s: set[T.distinctBase]
|
||||
s = {0, 1}
|
||||
doAssert 0 in s
|
||||
|
||||
test[TestDistinctRange]()
|
||||
|
||||
block: # passing set[T.distinctBase] to a proc expecting set[0..63]
|
||||
proc accept(x: typedesc[set[0 .. 63]]) = discard
|
||||
|
||||
proc pass[T: TestDistinctRange](p: typedesc[set[T]]) =
|
||||
accept(set[T.distinctBase])
|
||||
|
||||
pass(set[TestDistinctRange])
|
||||
Reference in New Issue
Block a user