mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-17 10:07:09 +00:00
fixes #22276
When matching against `tyFromExpr`, the compiler tries to instantiate it
then operates on the potentially instantiated type. But the way it does
this is inverted, it checks if the instantiated type matches the
argument type, not if the argument type matches the instantiated type.
This has been the case since
ac271e76b1 (diff-251afcd01d239369019495096c187998dd6695b6457528953237a7e4a10f7138),
which doesn't comment on it, so I'm guessing this isn't intended. I
don't know if it would break anything though.
269 lines
6.9 KiB
Nim
269 lines
6.9 KiB
Nim
block: # issue #4228
|
|
template seqType(t: typedesc): typedesc =
|
|
when t is int:
|
|
seq[int]
|
|
else:
|
|
seq[string]
|
|
|
|
proc mkSeq[T: int|string](v: T): seqType(T) =
|
|
result = newSeq[T](1)
|
|
result[0] = v
|
|
|
|
doAssert mkSeq("a") == @["a"]
|
|
doAssert mkSeq(1) == @[1]
|
|
|
|
block: # expanded version of t8545
|
|
template bar(a: static[bool]): untyped =
|
|
when a:
|
|
int
|
|
else:
|
|
float
|
|
|
|
proc main() =
|
|
proc foo1(a: static[bool]): auto = 1
|
|
doAssert foo1(true) == 1
|
|
|
|
proc foo2(a: static[bool]): bar(a) = 1
|
|
doAssert foo2(true) == 1
|
|
doAssert foo2(true) is int
|
|
doAssert foo2(false) == 1.0
|
|
doAssert foo2(false) is float
|
|
|
|
proc foo3(a: static[bool]): bar(cast[bool](a)) = 1
|
|
doAssert foo3(true) == 1
|
|
doAssert foo3(true) is int
|
|
doAssert foo3(false) == 1.0
|
|
doAssert foo3(false) is float
|
|
|
|
proc foo4(a: static[bool]): bar(static(a)) = 1
|
|
doAssert foo4(true) == 1
|
|
doAssert foo4(true) is int
|
|
doAssert foo4(false) == 1.0
|
|
doAssert foo4(false) is float
|
|
|
|
static: main()
|
|
main()
|
|
|
|
block: # issue #8406
|
|
macro f(x: static[int]): untyped = discard
|
|
proc g[X: static[int]](v: f(X)) = discard
|
|
|
|
import macros
|
|
|
|
block: # issue #8551
|
|
macro distinctBase2(T: typedesc): untyped =
|
|
let typeNode = getTypeImpl(T)
|
|
expectKind(typeNode, nnkBracketExpr)
|
|
if typeNode[0].typeKind != ntyTypeDesc:
|
|
error "expected typeDesc, got " & $typeNode[0]
|
|
var typeSym = typeNode[1]
|
|
|
|
typeSym = getTypeImpl(typeSym)
|
|
|
|
if typeSym.typeKind != ntyDistinct:
|
|
error "type is not distinct: " & $typeSym.typeKind
|
|
|
|
typeSym = typeSym[0]
|
|
typeSym
|
|
|
|
func distinctBase[T](a: T): distinctBase2(T) = distinctBase2(T)(a)
|
|
|
|
type T = distinct int
|
|
doAssert distinctBase(T(0)) is int
|
|
|
|
block:
|
|
type Foo[T] = object
|
|
x: T
|
|
|
|
proc foo(x: Foo): Foo[x.T] =
|
|
doAssert typeof(result) is typeof(x)
|
|
|
|
var a: Foo[int]
|
|
let b: Foo[int] = foo(a)
|
|
doAssert b.x is int
|
|
|
|
block:
|
|
type Foo[T: static int] = object
|
|
x: array[T, int]
|
|
|
|
proc double(x: int): int = x * 2
|
|
|
|
proc foo[T: static int](x: Foo[T]): Foo[T.double] =
|
|
doAssert typeof(result).T == double(typeof(x).T)
|
|
|
|
var a: Foo[3]
|
|
let b: Foo[6] = foo(a)
|
|
doAssert $typeof(foo(a)) == "Foo[6]"
|
|
|
|
block:
|
|
type Foo[T: static int] = object
|
|
x: array[T, int]
|
|
|
|
proc foo(x: Foo): Foo[x.T] =
|
|
doAssert typeof(result).T == typeof(x).T
|
|
doAssert typeof(result) is typeof(x)
|
|
|
|
var a: Foo[3]
|
|
let b: Foo[3] = foo(a)
|
|
doAssert $typeof(foo(a)) == "Foo[3]"
|
|
|
|
block: # issue #7006
|
|
type
|
|
Node[T] = object
|
|
val: T
|
|
next: ref Node[T]
|
|
HHSet[T, Key] = object
|
|
data: seq[Node[T]]
|
|
proc rawGet(hhs:HHSet; key: hhs.Key): ptr Node[hhs.T] =
|
|
return nil # body doesn't matter
|
|
var hhs: HHSet[string, cstring]
|
|
discard hhs.rawGet("hello".cstring)
|
|
|
|
block: # issue #7008
|
|
type Node[T] = object
|
|
val: T
|
|
# Compiles fine
|
|
proc concreteProc(s: Node[cstring]; key: s.T) = discard
|
|
# Also fine
|
|
proc implicitGenericProc1(s: Node; key: s.T) = discard
|
|
# still fine
|
|
proc explicitGenericProc1[T](s: Node[T]; key: T) = discard
|
|
# Internal Compiler Error!
|
|
proc explicitGenericProc2[T](s: Node[T]; key: s.T) = discard
|
|
let n = Node[int](val: 5)
|
|
implicitGenericProc1(n, 5) # works
|
|
explicitGenericProc1(n, 5) # works
|
|
explicitGenericProc2(n, 5) # doesn't
|
|
|
|
block: # issue #20027
|
|
block:
|
|
type Test[T] = object
|
|
proc run(self: Test): self.T = discard
|
|
discard run(Test[int]())
|
|
block:
|
|
type Test[T] = object
|
|
proc run[T](self: Test[T]): self.T = discard
|
|
discard run(Test[int]())
|
|
block:
|
|
type Test[T] = object
|
|
proc run(self: Test[auto]): self.T = discard
|
|
discard run(Test[int]())
|
|
|
|
block: # issue #11112
|
|
proc foo[A, B]: type(A.default + B.default) =
|
|
discard
|
|
doAssert foo[int, int]() is int
|
|
|
|
block: # tyStatic and tyFromExpr instantiation mid-match
|
|
proc bar(x: int): int = x * 3
|
|
proc bar2(x: static int): int = x * 4
|
|
type Foo[T: static int] = distinct array[T, int]
|
|
proc foo[T: static int](x: Foo[T], y: Foo[bar(T)]) = discard
|
|
proc foo2[T: static int](x: Foo[T], y: Foo[bar2(T)]) = discard
|
|
foo(Foo[1]([1]), Foo[3]([1, 2, 3]))
|
|
foo2(Foo[1]([1]), Foo[4]([1, 2, 3, 4]))
|
|
|
|
block: # issue #4990
|
|
type Foo[I: static[int], A: static[array[I, int]]] = object
|
|
curIndex: int
|
|
|
|
proc next[I: static[int], A: static[array[I, int]]](f: Foo[I, A]): string =
|
|
discard
|
|
const arr = [1, 2, 3]
|
|
var f: Foo[arr.len, arr]
|
|
discard next(f)
|
|
|
|
block: # issue #4990 comment
|
|
type
|
|
Foo[A: static[int], B: static[int], TokenType: enum, EofToken: static[TokenType]] = object
|
|
curIndex: int
|
|
MyEnum = enum
|
|
meA, meB
|
|
Bar = Foo[2, 3, MyEnum, meA]
|
|
proc next[A: static[int], B: static[int], TokenType: enum,
|
|
EofToken: static[TokenType]](f: Foo[A, B, TokenType, EofToken],
|
|
a: static[(array[A, int], array[B, int])]): TokenType =
|
|
TokenType(a[0][f.curIndex])
|
|
const
|
|
a = [1, 2]
|
|
b = [3, 4, 5]
|
|
template next(bar: Bar): MyEnum =
|
|
next(Foo[2, 3, MyEnum, meA](bar), (a, b))
|
|
let bar = Bar(curIndex: 0)
|
|
doAssert bar.next() == meB
|
|
|
|
block: # issue #14053
|
|
template returnType(value: static[int]): typedesc =
|
|
when value == 1:
|
|
int
|
|
else:
|
|
float
|
|
proc fun(value: static[int]): returnType(value) = discard
|
|
doAssert fun(1) is int
|
|
template returnType2(value: static[int]): typedesc =
|
|
int
|
|
proc fun2(value: static[int]): returnType2(value) = discard
|
|
doAssert fun2(1) is int
|
|
|
|
block: # issue #7547
|
|
macro foo(N: static[int]): untyped =
|
|
result = getType(int)
|
|
type
|
|
Foo[N: static[int]] = foo(N)
|
|
ContainsFoo[N: static[int]] = object
|
|
Ffoo: Foo[N]
|
|
proc initFoo(N: static[int]): Foo[N] = discard
|
|
proc initContainsFoo(size: static[int]): ContainsFoo[size] = discard
|
|
var a: Foo[10] # Works
|
|
doAssert a is int
|
|
let b = initFoo(10) # Works
|
|
doAssert b is int
|
|
let c = ContainsFoo[5]() # Works
|
|
doAssert c.Ffoo is int
|
|
let z = initContainsFoo(5) # Error: undeclared identifier: 'N'
|
|
doAssert z.Ffoo is int
|
|
|
|
block: # issue #22607, needs nkWhenStmt to be handled like nkRecWhen
|
|
proc test[x: static bool](
|
|
t: (
|
|
when x:
|
|
int
|
|
else:
|
|
float
|
|
)
|
|
) = discard
|
|
test[true](1.int)
|
|
test[false](1.0)
|
|
doAssert not compiles(test[])
|
|
|
|
block: # `when` in static signature
|
|
template ctAnd(a, b): bool =
|
|
when a:
|
|
when b: true
|
|
else: false
|
|
else: false
|
|
template test(): untyped =
|
|
when ctAnd(declared(SharedTable), typeof(result) is SharedTable):
|
|
result = SharedTable()
|
|
else:
|
|
result = 123
|
|
proc foo[T](): T = test()
|
|
proc bar[T](x = foo[T]()): T = x
|
|
doAssert bar[int]() == 123
|
|
|
|
block: # issue #22276
|
|
type Foo = enum A, B
|
|
macro test(y: static[Foo]): untyped =
|
|
if y == A:
|
|
result = parseExpr("proc (x: int)")
|
|
else:
|
|
result = parseExpr("proc (x: float)")
|
|
proc foo(y: static[Foo], x: test(y)) = # We want to make the type of `x` depend on what `y` is
|
|
x(9)
|
|
foo(A, proc (x: int) = doAssert x == 9)
|
|
var a: int
|
|
foo(A, proc (x: int) =
|
|
a = x * 2)
|
|
doAssert a == 18
|
|
foo(B, proc (x: float) = doAssert x == 9)
|