From e0197a838027dffbf1c28f88666bb034156d5ebc Mon Sep 17 00:00:00 2001 From: Ryan McConnell Date: Fri, 13 Dec 2024 09:13:19 -0500 Subject: [PATCH] couple cases of valid concept bindings (#24513) see tests --------- Co-authored-by: Andreas Rumpf --- compiler/concepts.nim | 42 ++++++++++++++++++++++++++-------- compiler/sigmatch.nim | 39 ------------------------------- compiler/types.nim | 42 ++++++++++++++++++++++++++++++++++ tests/concepts/tconceptsv2.nim | 36 +++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 48 deletions(-) diff --git a/compiler/concepts.nim b/compiler/concepts.nim index 23f8c5d87c..139f851667 100644 --- a/compiler/concepts.nim +++ b/compiler/concepts.nim @@ -89,29 +89,52 @@ proc existingBinding(m: MatchCon; key: PType): PType = proc conceptMatchNode(c: PContext; n: PNode; m: var MatchCon): bool -proc matchType(c: PContext; f, a: PType; m: var MatchCon): bool +proc matchType(c: PContext; f, ao: PType; m: var MatchCon): bool + +proc acceptsAllTypes(t: PType): bool= + result = false + if t.kind == tyAnything: + result = true + elif t.kind == tyGenericParam: + if tfImplicitTypeParam in t.flags: + result = true + if not t.hasElementType or t.elementType.kind == tyNone: + result = true proc matchKids(c: PContext; f, a: PType; m: var MatchCon, start=0): bool= result = true for i in start.. 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: diff --git a/compiler/types.nim b/compiler/types.nim index 18f90b75ac..1834acdffa 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -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 system.nim + arrPutGetMagicApplies* = {tyArray, tyOpenArray, tyString, tySequence, tyCstring, tyTuple} proc invalidGenericInst*(f: PType): bool = result = f.kind == tyGenericInst and skipModifier(f) == nil @@ -2038,3 +2041,42 @@ 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 # ?? 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 diff --git a/tests/concepts/tconceptsv2.nim b/tests/concepts/tconceptsv2.nim index f72f522ee6..0db79c0269 100644 --- a/tests/concepts/tconceptsv2.nim +++ b/tests/concepts/tconceptsv2.nim @@ -5,6 +5,7 @@ B[system.int] A[system.string] A[array[0..0, int]] A[seq[int]] +char ''' """ import conceptsv2_helper @@ -128,3 +129,38 @@ block: # more complex recursion var a = BufferImpl[5]() launch(a, WritableImpl()) + +block: # capture p1[T] + type + A[T] = object + C = concept + proc p1(x: Self, i: int): float + + proc p1[T](a: A[T], idx: int): T = default(T) + proc p(a: C): int = discard + proc p[T](a: T):int = assert false + + discard p(A[float]()) + +block: # mArrGet binding + type + ArrayLike[T] = concept + proc len(x: Self): int + proc `[]`(b: Self, i: int): T + + proc p[T](a: ArrayLike[T]): int= discard + discard p([1,2]) + +block: + type + A[T] = object + ArrayLike[T] = concept + proc len(x: Self): int + proc `[]`(b: Self, i: int): T + proc tell(s: Self, x: A[int]) + + proc tell(x: string, h: A[int])= discard + + proc spring[T](w: ArrayLike[T])= echo T + + spring("hi")