Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"interface" concepts or something... I guess #24491

Draft
wants to merge 3 commits into
base: devel
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
471 changes: 359 additions & 112 deletions compiler/concepts.nim

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions compiler/semtypinst.nim
Original file line number Diff line number Diff line change
Expand Up @@ -608,10 +608,13 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType, isInstValue = false):
result = t
if t == nil: return

var et = t
if t.isConcept:
et = t.reduceToBase
const lookupMetas = {tyStatic, tyGenericParam, tyConcept} + tyTypeClasses - {tyAnything}
if t.kind in lookupMetas or
(t.kind == tyAnything and tfRetType notin t.flags):
let lookup = cl.typeMap.lookup(t)
if et.kind in lookupMetas or
(et.kind == tyAnything and tfRetType notin et.flags):
let lookup = cl.typeMap.lookup(et)
if lookup != nil: return lookup

case t.kind
Expand Down
41 changes: 2 additions & 39 deletions compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,8 @@ proc sumGeneric(t: PType): int =
result += sumGeneric(a)
break
else:
if t.isConcept:
result += t.reduceToBase.conceptBody.len
break

proc complexDisambiguation(a, b: PType): int =
Expand Down Expand Up @@ -595,45 +597,6 @@ proc handleFloatRange(f, a: PType): TTypeRelation =
else: result = isIntConv
else: result = isNone

proc reduceToBase(f: PType): PType =
#[
Returns the lowest order (most general) type that that is compatible with the input.
E.g.
A[T] = ptr object ... A -> ptr object
A[N: static[int]] = array[N, int] ... A -> array
]#
case f.kind:
of tyGenericParam:
if f.len <= 0 or f.skipModifier == nil:
result = f
else:
result = reduceToBase(f.skipModifier)
of tyGenericInvocation:
result = reduceToBase(f.baseClass)
of tyCompositeTypeClass, tyAlias:
if not f.hasElementType or f.elementType == nil:
result = f
else:
result = reduceToBase(f.elementType)
of tyGenericInst:
result = reduceToBase(f.skipModifier)
of tyGenericBody:
result = reduceToBase(f.typeBodyImpl)
of tyUserTypeClass:
if f.isResolvedUserTypeClass:
result = f.base # ?? idk if this is right
else:
result = f.skipModifier
of tyStatic, tyOwned, tyVar, tyLent, tySink:
result = reduceToBase(f.base)
of tyInferred:
# This is not true "After a candidate type is selected"
result = reduceToBase(f.base)
of tyRange:
result = f.elementType
else:
result = f

proc genericParamPut(c: var TCandidate; last, fGenericOrigin: PType) =
if fGenericOrigin != nil and last.kind == tyGenericInst and
last.kidsLen-1 == fGenericOrigin.kidsLen:
Expand Down
50 changes: 50 additions & 0 deletions compiler/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ const
# typedescX is used if we're sure tyTypeDesc should be included (or skipped)
typedescPtrs* = abstractPtrs + {tyTypeDesc}
typedescInst* = abstractInst + {tyTypeDesc, tyOwned, tyUserTypeClass}

# incorrect definition of `[]` and `[]=` for these types in
arrPutGetMagicApplies* = {tyArray, tyOpenArray, tyString, tySequence, tyCstring, tyTuple}

proc invalidGenericInst*(f: PType): bool =
result = f.kind == tyGenericInst and skipModifier(f) == nil
Expand Down Expand Up @@ -2038,3 +2041,50 @@ proc genericRoot*(t: PType): PType =
result = t.sym.typ
else:
result = nil

proc reduceToBase*(f: PType): PType =
#[
Returns the lowest order (most general) type that that is compatible with the input.
E.g.
A[T] = ptr object ... A -> ptr object
A[N: static[int]] = array[N, int] ... A -> array
]#
case f.kind:
of tyGenericParam:
if f.len <= 0 or f.skipModifier == nil:
result = f
else:
result = reduceToBase(f.skipModifier)
of tyGenericInvocation:
result = reduceToBase(f.baseClass)
of tyCompositeTypeClass, tyAlias:
if not f.hasElementType or f.elementType == nil:
result = f
else:
result = reduceToBase(f.elementType)
of tyGenericInst:
result = reduceToBase(f.skipModifier)
of tyGenericBody:
result = reduceToBase(f.typeBodyImpl)
of tyUserTypeClass:
if f.isResolvedUserTypeClass:
result = f.base
else:
result = f.skipModifier
of tyStatic, tyOwned, tyVar, tyLent, tySink:
result = reduceToBase(f.base)
of tyInferred:
# This is not true "After a candidate type is selected"
result = reduceToBase(f.base)
of tyRange:
result = f.elementType
else:
result = f

proc isConcept*(t: PType): bool=
if t.kind == tyConcept:
true
elif t.kind in {tyGenericInst, tyCompositeTypeClass, tyGenericInvocation}:
t.reduceToBase.kind == tyConcept
else:
false
3 changes: 3 additions & 0 deletions lib/system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type
##
## The coercion `type(x)` can be used to obtain the type of the given
## expression `x`.
TypeEach[T] = object

type
TypeOfMode* = enum ## Possible modes of `typeof`.
Expand Down Expand Up @@ -76,6 +77,8 @@ proc typeof*(x: untyped; mode = typeOfIter): typedesc {.
# since `typeOfProc` expects a typed expression and `myFoo2()` can
# only be used in a `for` context.

template each*(a: untyped): untyped = TypeEach[a]

proc `or`*(a, b: typedesc): typedesc {.magic: "TypeTrait", noSideEffect.}
## Constructs an `or` meta class.

Expand Down
13 changes: 13 additions & 0 deletions tests/concepts/conceptv2negative/tauto.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
discard """
action: "reject"
"""
type
A = object
C1 = concept
proc p(s: Self, a: auto)
C1Impl = object

proc p(x: C1Impl, a: A)= discard
proc spring(x: C1)= discard

spring(C1Impl())
13 changes: 13 additions & 0 deletions tests/concepts/conceptv2negative/tgenobj.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
discard """
action: "reject"
"""
type
A[T] = object
C1 = concept
proc p(s: Self, a: A)
C1Impl = object

proc p(x: C1Impl, a: A[int])= discard
proc spring(x: C1)= discard

spring(C1Impl())
12 changes: 12 additions & 0 deletions tests/concepts/conceptv2negative/tmarrget.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
discard """
action: "reject"
"""

# stop mArrGet magic from giving everything `[]`
type
C[T] = concept
proc `[]`(b: Self, i: int): T
A = object

proc p(a: C): int = assert false
discard p(A())
18 changes: 18 additions & 0 deletions tests/concepts/conceptv2negative/tnoimplicitbindingcontainer.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
discard """
action: "reject"
"""
type
Sizeable = concept
proc size(s: Self): int
Buffer = concept
proc w(s: Self, data: Sizeable)
Serializable[T: Buffer] = concept
proc w(b: T, s: Self)
ArrayLike = concept
proc size(s: Self): int
ArrayImpl = object

proc size(x: ArrayImpl): int= discard

proc spring(data: Serializable)= discard
spring(ArrayImpl())
18 changes: 18 additions & 0 deletions tests/concepts/conceptv2negative/tnoimplicitbindingeach.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
discard """
action: "reject"
"""
type
Sizeable = concept
proc size(s: Self): int
Buffer = concept
proc w(s: Self, data: Sizeable)
Serializable = concept
proc w(b: each Buffer, s: Self)
ArrayLike = concept
proc size(s: Self): int
ArrayImpl = object

proc size(x: ArrayImpl): int= discard

proc spring(data: Serializable)= discard
spring(ArrayImpl())
16 changes: 16 additions & 0 deletions tests/concepts/conceptv2negative/tnottype.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
discard """
action: "reject"
"""
type
Sizeable = concept
proc size(s: Self): int
Buffer = concept
proc w(s: Self, data: Sizeable)
Serializable = concept
proc w(b: each Buffer, s: Self)
ArrayImpl = object

proc size(x: ArrayImpl): int= discard

proc spring(data: Serializable)= discard
spring(ArrayImpl())
12 changes: 12 additions & 0 deletions tests/concepts/conceptv2negative/tor.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
discard """
action: "reject"
"""
type
C1 = concept
proc p(s: Self, a: int | float | string)
C1Impl = object

proc p(x: C1Impl, a: int | float)= discard
proc spring(x: C1)= discard

spring(C1Impl())
12 changes: 12 additions & 0 deletions tests/concepts/conceptv2negative/ttypedesc.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
discard """
action: "reject"
"""
type
C1 = concept
proc p(s: Self, a: typedesc)
C1Impl = object

proc p(x: C1Impl, a: typedesc[SomeInteger])= discard
proc spring(x: C1)= discard

spring(C1Impl())
Loading
Loading