mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-18 13:30:33 +00:00
I think this might not be a comprehensive solution to dealing with
`tyGenericBody` but we take a step forward
#24451
(cherry picked from commit 08c2a1741d)
This commit is contained in:
committed by
narimiran
parent
01b6c5d0d1
commit
d339c58628
@@ -88,6 +88,13 @@ 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 matchKids(c: PContext; f, a: PType; m: var MatchCon, start=0): bool=
|
||||
result = true
|
||||
for i in start..<f.kidsLen - ord(f.kind == tyGenericInst):
|
||||
if not matchType(c, f[i], a[i], m): return false
|
||||
|
||||
proc matchType(c: PContext; f, a: PType; m: var MatchCon): bool =
|
||||
## The heart of the concept matching process. 'f' is the formal parameter of some
|
||||
## routine inside the concept that we're looking for. 'a' is the formal parameter
|
||||
@@ -117,9 +124,7 @@ proc matchType(c: PContext; f, a: PType; m: var MatchCon): bool =
|
||||
result = false
|
||||
if a.kind == tyGenericInst and a.genericHead.kind == tyGenericBody:
|
||||
if sameType(f.genericHead, a.genericHead) and f.kidsLen == a.kidsLen-1:
|
||||
for i in FirstGenericParamAt ..< f.kidsLen:
|
||||
if not matchType(c, f[i], a[i], m): return false
|
||||
return true
|
||||
result = matchKids(c, f, a, m, start=FirstGenericParamAt)
|
||||
of tyGenericParam:
|
||||
let ak = a.skipTypes({tyVar, tySink, tyLent, tyOwned})
|
||||
if ak.kind in {tyTypeDesc, tyStatic} and not isSelf(ak):
|
||||
@@ -151,7 +156,6 @@ proc matchType(c: PContext; f, a: PType; m: var MatchCon): bool =
|
||||
else:
|
||||
result = false
|
||||
#echo "B for ", result, " to ", typeToString(a), " to ", typeToString(m.potentialImplementation)
|
||||
|
||||
of tyVar, tySink, tyLent, tyOwned:
|
||||
# modifiers in the concept must be there in the actual implementation
|
||||
# too but not vice versa.
|
||||
@@ -177,15 +181,20 @@ proc matchType(c: PContext; f, a: PType; m: var MatchCon): bool =
|
||||
m.potentialImplementation = oldPotentialImplementation
|
||||
if not result:
|
||||
m.inferred.setLen oldLen
|
||||
of tyGenericBody:
|
||||
var ak = a
|
||||
if a.kind == tyGenericBody:
|
||||
ak = last(a)
|
||||
result = matchType(c, last(f), ak, m)
|
||||
of tyCompositeTypeClass:
|
||||
result = matchType(c, last(f), a, m)
|
||||
of tyArray, tyTuple, tyVarargs, tyOpenArray, tyRange, tySequence, tyRef, tyPtr,
|
||||
tyGenericInst:
|
||||
# ^ XXX Rewrite this logic, it's more complex than it needs to be.
|
||||
result = false
|
||||
let ak = a.skipTypes(ignorableForArgType - {f.kind})
|
||||
if ak.kind == f.kind and f.kidsLen == ak.kidsLen:
|
||||
for i in 0..<ak.kidsLen:
|
||||
if not matchType(c, f[i], ak[i], m): return false
|
||||
return true
|
||||
result = matchKids(c, f, ak, m)
|
||||
of tyOr:
|
||||
let oldLen = m.inferred.len
|
||||
if a.kind == tyOr:
|
||||
|
||||
41
tests/concepts/tconceptsv2.nim
Normal file
41
tests/concepts/tconceptsv2.nim
Normal file
@@ -0,0 +1,41 @@
|
||||
discard """
|
||||
action: "run"
|
||||
output: '''
|
||||
B[system.int]
|
||||
A[system.string]
|
||||
'''
|
||||
"""
|
||||
|
||||
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()
|
||||
Reference in New Issue
Block a user