mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-12 14:23:45 +00:00
603 lines
12 KiB
Nim
603 lines
12 KiB
Nim
discard """
|
|
action: "run"
|
|
output: '''
|
|
B[system.int]
|
|
A[system.string]
|
|
A[array[0..0, int]]
|
|
A[seq[int]]
|
|
100
|
|
a
|
|
b
|
|
c
|
|
a
|
|
b
|
|
c
|
|
1
|
|
2
|
|
'''
|
|
"""
|
|
import conceptsv2_helper
|
|
|
|
block: # issue #24451
|
|
type
|
|
A = object
|
|
x: int
|
|
B[T] = object
|
|
b: T
|
|
AConcept = concept
|
|
proc implementation(s: var Self, p1: B[int])
|
|
|
|
proc implementation(r: var A, p1: B[int])=
|
|
echo typeof(p1)
|
|
|
|
proc accept(r: var AConcept)=
|
|
r.implementation(B[int]())
|
|
|
|
var a = A()
|
|
a.accept()
|
|
|
|
block: # typeclass
|
|
type
|
|
A[T] = object
|
|
x: int
|
|
AConcept = concept
|
|
proc implementation(s: Self)
|
|
|
|
proc implementation(r: A) =
|
|
echo typeof(r)
|
|
|
|
proc accept(r: AConcept) =
|
|
r.implementation()
|
|
|
|
var a = A[string]()
|
|
a.accept()
|
|
|
|
block:
|
|
type
|
|
SomethingLike[T] = concept
|
|
proc len(s: Self): int
|
|
proc `[]`(s: Self; index: int): T
|
|
|
|
A[T] = object
|
|
x: T
|
|
|
|
proc initA(x: SomethingLike): auto =
|
|
A[type x](x: x)
|
|
|
|
var a: array[1, int]
|
|
var s: seq[int]
|
|
echo typeof(initA(a))
|
|
echo typeof(initA(s))
|
|
|
|
block:
|
|
proc iGetShadowed(s: int)=
|
|
discard
|
|
proc spring(x: ShadowConcept)=
|
|
discard
|
|
let a = DummyFitsObj()
|
|
spring(a)
|
|
|
|
block:
|
|
type
|
|
Buffer = concept
|
|
proc put(s: Self)
|
|
ArrayBuffer[T: static int] = object
|
|
proc put(x: ArrayBuffer)=discard
|
|
proc p(a: Buffer)=discard
|
|
var buffer = ArrayBuffer[5]()
|
|
p(buffer)
|
|
|
|
block: # composite typeclass matching
|
|
type
|
|
A[T] = object
|
|
Buffer = concept
|
|
proc put(s: Self, i: A)
|
|
BufferImpl = object
|
|
WritableImpl = object
|
|
|
|
proc launch(a: var Buffer)=discard
|
|
proc put(x: BufferImpl, i: A)=discard
|
|
|
|
var a = BufferImpl()
|
|
launch(a)
|
|
|
|
block: # simple recursion
|
|
type
|
|
Buffer = concept
|
|
proc put(s: var Self, i: auto)
|
|
proc second(s: Self)
|
|
Writable = concept
|
|
proc put(w: var Buffer, s: Self)
|
|
BufferImpl[T: static int] = object
|
|
WritableImpl = object
|
|
|
|
proc launch(a: var Buffer, b: Writable)= discard
|
|
proc put[T](x: var BufferImpl, i: T)= discard
|
|
proc second(x: BufferImpl)= discard
|
|
proc put(x: var Buffer, y: WritableImpl)= discard
|
|
|
|
var a = BufferImpl[5]()
|
|
launch(a, WritableImpl())
|
|
|
|
block: # more complex recursion
|
|
type
|
|
Buffer = concept
|
|
proc put(s: var Self, i: auto)
|
|
proc second(s: Self)
|
|
Writable = concept
|
|
proc put(w: var Buffer, s: Self)
|
|
BufferImpl[T: static int] = object
|
|
WritableImpl = object
|
|
|
|
proc launch(a: var Buffer, b: Writable)= discard
|
|
proc put[T](x: var Buffer, i: T)= discard
|
|
proc put(x: var BufferImpl, i: object)= discard
|
|
proc second(x: BufferImpl)= discard
|
|
proc put(x: var Buffer, y: WritableImpl)= discard
|
|
|
|
var a = BufferImpl[5]()
|
|
launch(a, WritableImpl())
|
|
|
|
block: # co-dependent concepts
|
|
type
|
|
Writable = concept
|
|
proc w(b: var Buffer; s: Self): int
|
|
Buffer = concept
|
|
proc w(s: var Self; data: Writable): int
|
|
SizedWritable = concept
|
|
proc size(x: Self): int
|
|
proc w(b: var Buffer, x: Self): int
|
|
BufferImpl = object
|
|
|
|
proc w(x: var BufferImpl, d: int): int = return 100
|
|
proc size(d: int): int = sizeof(int)
|
|
|
|
proc p(b: var Buffer, data: SizedWritable): int =
|
|
b.w(data)
|
|
|
|
var b = BufferImpl()
|
|
echo p(b, 5)
|
|
|
|
block: # indirect concept matching
|
|
type
|
|
Sizeable = concept
|
|
proc size(s: Self): int
|
|
Buffer = concept
|
|
proc w(s: Self, data: Sizeable)
|
|
Serializable = concept
|
|
proc something(s: Self)
|
|
proc w(b: Buffer, s: Self)
|
|
BufferImpl = object
|
|
ArrayImpl = object
|
|
|
|
proc something(s: ArrayImpl)= discard
|
|
proc size(s: ArrayImpl): int= discard
|
|
|
|
proc w(x: BufferImpl, d: Sizeable)= discard
|
|
|
|
proc spring(s: Buffer, data: Serializable)=discard
|
|
|
|
spring(BufferImpl(), ArrayImpl())
|
|
|
|
block: # instantiate even when generic params are the same
|
|
type
|
|
ArrayLike[T] = concept
|
|
proc len(x: Self): int
|
|
proc `[]`(b: Self, i: int): T
|
|
proc p[T](x: ArrayLike[T])=
|
|
for k in x:
|
|
echo k
|
|
# For this test to work the second call's instantiation has to be incompatible with the first on the back end
|
|
p(['a','b','c'])
|
|
p("abc")
|
|
|
|
block: # reject improper generic variables in candidates
|
|
type
|
|
ArrayLike[T] = concept
|
|
proc len(x: Self): int
|
|
proc g(b: Self, i: int): T
|
|
FreakString = concept
|
|
proc len(x: Self): int
|
|
proc characterSize(s: Self): int
|
|
A = object
|
|
|
|
proc g[T, H](s: T, i: H): H = default(T)
|
|
proc len(s: A): int = discard
|
|
proc characterSize(s: A): int = discard
|
|
|
|
proc p(symbol: ArrayLike[char]): int = assert false
|
|
proc p(symbol: FreakString): int=discard
|
|
|
|
discard p(A())
|
|
|
|
block: # typerel disambiguation by concept subset
|
|
type
|
|
ArrayLike[T] = concept
|
|
proc len(x: Self): int
|
|
proc characterSize(s: Self): int
|
|
FreakString = concept
|
|
proc len(x: Self): int
|
|
proc characterSize(s: Self): int
|
|
proc tieBreaker(s: Self, j: int): float
|
|
A = object
|
|
|
|
proc len(s: A): int = discard
|
|
proc characterSize(s: A): int = discard
|
|
proc tieBreaker(s: A, h: int):float = 0.0
|
|
|
|
proc p(symbol: ArrayLike[char]): int = assert false
|
|
proc p(symbol: FreakString): int=discard
|
|
|
|
discard p(A())
|
|
|
|
block: # tie break via sumGeneric
|
|
type
|
|
C1 = concept
|
|
proc p1(x: Self, b: int)
|
|
proc p2(x: Self, b: float)
|
|
proc p3(x: Self, b: string)
|
|
C2 = concept
|
|
proc b1(x: Self, b: int)
|
|
proc b2(x: Self, b: float)
|
|
A = object
|
|
|
|
proc p1(x: A, b: int)=discard
|
|
proc p2(x: A, b: float)=discard
|
|
proc p3(x: A, b: string)=discard
|
|
|
|
proc b1(x: A, b: int)=discard
|
|
proc b2(x: A, b: float)=discard
|
|
|
|
proc p(symbol: C1): int = discard
|
|
proc p(symbol: C2): int = assert false
|
|
|
|
discard p(A())
|
|
|
|
block: # not type
|
|
type
|
|
C1 = concept
|
|
proc p(s: Self, a: int)
|
|
C1Impl = object
|
|
|
|
proc p(x: C1Impl, a: not float)= discard
|
|
proc spring(x: C1)= discard
|
|
|
|
spring(C1Impl())
|
|
|
|
block: # not type parameterized
|
|
type
|
|
C1[T: not int] = concept
|
|
proc p(s: Self, a: T)
|
|
C1Impl = object
|
|
|
|
proc p(x: C1Impl, a: float)= discard
|
|
proc spring(x: C1)= discard
|
|
|
|
spring(C1Impl())
|
|
|
|
block: # typedesc
|
|
type
|
|
C1 = concept
|
|
proc p(s: Self, a: typedesc[SomeInteger])
|
|
C1Impl = object
|
|
|
|
proc p(x: C1Impl, a: typedesc)= discard
|
|
proc spring(x: C1)= discard
|
|
|
|
spring(C1Impl())
|
|
|
|
|
|
block: # or
|
|
type
|
|
C1 = concept
|
|
proc p(s: Self, a: int | float)
|
|
C1Impl = object
|
|
|
|
proc p(x: C1Impl, a: int | float | string)= discard
|
|
proc spring(x: C1)= discard
|
|
|
|
spring(C1Impl())
|
|
|
|
block: # or mixed generic param
|
|
type
|
|
C1 = concept
|
|
proc p(s: Self, a: int | float)
|
|
C1Impl = object
|
|
|
|
proc p[T: string | float](x: C1Impl, a: int | T) = discard
|
|
proc spring(x: C1)= discard
|
|
|
|
spring(C1Impl())
|
|
|
|
block: # or parameterized
|
|
type
|
|
C1[T: int | float | string] = concept
|
|
proc p(s: Self, a: T)
|
|
C1Impl = object
|
|
|
|
proc p(x: C1Impl, a: int | float)= discard
|
|
proc spring(x: C1)= discard
|
|
|
|
spring(C1Impl())
|
|
|
|
block: # unconstrained param
|
|
type
|
|
A = object
|
|
C1[T] = concept
|
|
proc p(s: Self, a: T)
|
|
C1Impl = object
|
|
|
|
proc p(x: C1Impl, a: A)= discard
|
|
proc spring(x: C1)= discard
|
|
|
|
spring(C1Impl())
|
|
|
|
block: # unconstrained param sanity check
|
|
type
|
|
A = object
|
|
C1[T: auto] = concept
|
|
proc p(s: Self, a: T)
|
|
C1Impl = object
|
|
|
|
proc p(x: C1Impl, a: A)= discard
|
|
proc spring(x: C1)= discard
|
|
|
|
spring(C1Impl())
|
|
|
|
block: # exact nested concept binding
|
|
type
|
|
Sizeable = concept
|
|
proc size(s: Self): int
|
|
Buffer = concept
|
|
proc w(s: Self, data: Sizeable)
|
|
Serializable = concept
|
|
proc w(b: Buffer, s: Self)
|
|
ArrayLike = concept
|
|
proc len(s: Self): int
|
|
ArrayImpl = object
|
|
|
|
proc len(s: ArrayImpl): int = discard
|
|
proc w(x: Buffer, d: ArrayLike)=discard
|
|
|
|
proc spring(data: Serializable)=discard
|
|
spring(ArrayImpl())
|
|
|
|
block:
|
|
type
|
|
StaticallySized = concept
|
|
proc staticSize(x: typedesc[Self]): int
|
|
proc dynamicSize(x: Self): int
|
|
DynamicallySized = concept
|
|
proc dynamicSize(x: Self): int
|
|
|
|
proc dynamicSize(a: SomeInteger): int = 5
|
|
proc read[T: DynamicallySized](a: var T): int = 1
|
|
proc read[T: SomeInteger](a: var T): int = 2
|
|
|
|
var a: uint16
|
|
assert read(a) == 2
|
|
|
|
block:
|
|
type
|
|
A[X, Y] = object
|
|
x: X
|
|
y: Y
|
|
C1 = concept
|
|
proc p(z: var Self)
|
|
C2 = concept
|
|
proc g(x: var Self, y: int)
|
|
C3 = C1 and C2
|
|
C4 = concept
|
|
proc h(x: Self): C3
|
|
|
|
proc p[X, Y](z: var A[int, float]) = discard
|
|
proc g[X, Y](z: var A[X, Y], y: int) = discard
|
|
proc h[X, Y](z: A[X, Y]): A[X, Y] = discard
|
|
|
|
proc spring(x: C4) = discard
|
|
var d = A[int, float]()
|
|
d.spring()
|
|
|
|
block:
|
|
type
|
|
A[X, Y] = object
|
|
x: X
|
|
y: Y
|
|
B = object
|
|
C1 = concept
|
|
proc p(z: var Self, d: A[int, float])
|
|
|
|
proc p[X: int; Y: float](x: var B, y: A[X, Y]) = discard
|
|
proc spring(x: var C1) = discard
|
|
var d = B()
|
|
d.spring()
|
|
|
|
block:
|
|
type
|
|
A = object
|
|
C1 = concept
|
|
proc p(s: Self; x: auto)
|
|
C2[T: int] = concept
|
|
proc p(s: Self; x: T)
|
|
Impl = object
|
|
|
|
proc p(n: Impl; i: int) = discard
|
|
|
|
proc spring(x: C1): int = 1
|
|
proc spring(x: C2): int = 2
|
|
|
|
assert spring(Impl()) == 2
|
|
|
|
block:
|
|
type
|
|
C1[T] = concept
|
|
proc p(s: var Self; x: T)
|
|
FreakString = concept
|
|
proc p(w: var C1; s: Self)
|
|
proc a(x: Self)
|
|
DynArray[CT, T] = object
|
|
|
|
proc p[CT; T; W; ](w: C1[T]; o: DynArray[CT, T]): int = discard
|
|
proc spring(s: auto) = discard
|
|
proc spring(s: FreakString) = discard
|
|
|
|
spring("hi")
|
|
|
|
block:
|
|
type
|
|
RawWriter = concept
|
|
proc write(s: Self; data: pointer; length: int)
|
|
ArrayBuffer[N: static int] = object
|
|
SeqBuffer = object
|
|
CompatBuffer = ArrayBuffer | SeqBuffer
|
|
|
|
proc write[T:CompatBuffer](a: var T; data: pointer; length: int) =
|
|
discard
|
|
|
|
proc spring(r:RawWriter, i: byte)=discard
|
|
|
|
var s = ArrayBuffer[1500]()
|
|
spring(s, 8.uint8)
|
|
|
|
block:
|
|
type
|
|
Future[T] = object
|
|
SyncType = concept
|
|
proc p(s: Self)
|
|
AsyncType = concept
|
|
proc p(s: Self) : Future[void]
|
|
SyncImpl = object
|
|
AsyncImpl = object
|
|
Container[T] = object
|
|
|
|
proc p(x: SyncImpl) = discard
|
|
proc p(x: AsyncImpl): Future[void] = discard
|
|
|
|
proc p(x: Container[SyncType]) = discard
|
|
proc p(x: Container[AsyncImpl]): Future[void] = discard
|
|
|
|
assert SyncImpl is SyncType
|
|
assert SyncImpl isnot AsyncType
|
|
assert AsyncImpl isnot SyncType
|
|
assert AsyncImpl is AsyncType
|
|
assert Container[SyncImpl] is SyncType
|
|
assert Container[SyncImpl] isnot AsyncType
|
|
assert Container[AsyncImpl] isnot SyncType
|
|
assert Container[AsyncImpl] is AsyncType
|
|
|
|
block:
|
|
type
|
|
C1 = concept
|
|
proc p(x: typedesc[Self]): int
|
|
E1 = enum
|
|
One, Two
|
|
proc p[E: enum](x: typedesc[set[E]]): int = sizeof(set[E])
|
|
|
|
proc spring(x: C1) = discard
|
|
|
|
spring({One,Two})
|
|
|
|
block: # bare `range`
|
|
type
|
|
MyRange = 0..64
|
|
MyConcept = concept
|
|
proc a(x: typedesc[Self])
|
|
|
|
proc a(x: typedesc[range]) = discard
|
|
proc spring(x: typedesc[MyConcept]) = discard
|
|
spring(MyRange)
|
|
|
|
block:
|
|
type
|
|
A = object
|
|
TestConcept =
|
|
concept
|
|
proc x(x: Self)
|
|
|
|
proc x(x: not object) =
|
|
discard
|
|
|
|
assert A isnot TestConcept
|
|
|
|
# this code fails inside a block for some reason
|
|
type Indexable[T] = concept
|
|
proc `[]`(t: Self, i: int): T
|
|
proc len(t: Self): int
|
|
|
|
iterator items[T](t: Indexable[T]): T =
|
|
for i in 0 ..< t.len:
|
|
yield t[i]
|
|
|
|
type Enumerable[T] = concept
|
|
iterator items(t: Self): T
|
|
|
|
proc echoAll[T](t: Enumerable[T]) =
|
|
for item in t:
|
|
echo item
|
|
|
|
type DummyIndexable[T] = distinct seq[T]
|
|
|
|
proc `[]`[T](t: DummyIndexable[T], i: int): T =
|
|
seq[T](t)[i]
|
|
|
|
proc len[T](t: DummyIndexable[T]): int =
|
|
seq[T](t).len
|
|
|
|
|
|
let dummyIndexable = DummyIndexable(@[1, 2])
|
|
echoAll(dummyIndexable)
|
|
|
|
block:
|
|
type
|
|
C = concept
|
|
proc a(x: Self, i: int)
|
|
AObj[T] = object
|
|
x: T
|
|
ARef[T] = ref AObj[T]
|
|
|
|
proc a[T: int](x: ARef[T], i: int) =
|
|
discard
|
|
|
|
assert (ref AObj[int]) is C
|
|
|
|
block:
|
|
type
|
|
C = concept
|
|
proc a(x: Self, i: int)
|
|
AObj[T; B] = object
|
|
x: T
|
|
ARef[T; B] = ref AObj[T,B]
|
|
|
|
proc a[T: int, C: float](x: ARef[T, C], i: int) =
|
|
discard
|
|
|
|
assert (ref AObj[int, int]) isnot C
|
|
assert (ref AObj[int, float]) is C
|
|
|
|
block:
|
|
type
|
|
C = concept
|
|
proc a(x: Self, i: int)
|
|
AObj[T] = object
|
|
ARef[T] = ref AObj[T]
|
|
|
|
proc a(x: ARef, i: int) =
|
|
discard
|
|
|
|
assert (ref AObj[int]) is C
|
|
|
|
block:
|
|
type
|
|
C = concept
|
|
proc x(a:Self, x: int)
|
|
StreamObj = object of RootObj
|
|
Stream = ref StreamObj
|
|
MemMapFileStreamObj = object of Stream
|
|
MemMapFileStream = ref MemMapFileStreamObj
|
|
|
|
proc x(a: Stream, x: int) = discard
|
|
proc spring(x: C) = discard
|
|
|
|
let test = MemMapFileStream()
|
|
spring(test)
|