Files
Nim/tests/concepts/tconceptsv2.nim
Ryan McConnell 86bbc73b3a concept patch: inheritance (#25317)
adds some inheritance support

---------

Co-authored-by: Andreas Rumpf <araq4k@proton.me>
2025-12-03 17:51:18 +01:00

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)