Fixed distinct composite type class proc borrowing (#18904)
* Fixed composite type class proc borrowing * Moved borrow search into transf * added borrow check to symbol flag
This commit is contained in:
parent
83a2515af7
commit
8d5a275189
4 changed files with 56 additions and 3 deletions
|
|
@ -703,7 +703,16 @@ proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym =
|
||||||
call.add(newIdentNode(fn.name, fn.info))
|
call.add(newIdentNode(fn.name, fn.info))
|
||||||
for i in 1..<fn.typ.n.len:
|
for i in 1..<fn.typ.n.len:
|
||||||
let param = fn.typ.n[i]
|
let param = fn.typ.n[i]
|
||||||
let t = skipTypes(param.typ, abstractVar-{tyTypeDesc, tyDistinct})
|
const desiredTypes = abstractVar + {tyCompositeTypeClass} - {tyTypeDesc, tyDistinct}
|
||||||
|
#[.
|
||||||
|
# We only want the type not any modifiers such as `ptr`, `var`, `ref` ...
|
||||||
|
# tyCompositeTypeClass is here for
|
||||||
|
# when using something like:
|
||||||
|
type Foo[T] = distinct int
|
||||||
|
proc `$`(f: Foo): string {.borrow.}
|
||||||
|
# We want to skip the `Foo` to get `int`
|
||||||
|
]#
|
||||||
|
let t = skipTypes(param.typ, desiredTypes)
|
||||||
if t.kind == tyDistinct or param.typ.kind == tyDistinct: hasDistinct = true
|
if t.kind == tyDistinct or param.typ.kind == tyDistinct: hasDistinct = true
|
||||||
var x: PType
|
var x: PType
|
||||||
if param.typ.kind == tyVar:
|
if param.typ.kind == tyVar:
|
||||||
|
|
@ -721,4 +730,4 @@ proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym =
|
||||||
result = nil
|
result = nil
|
||||||
elif result.magic in {mArrPut, mArrGet}:
|
elif result.magic in {mArrPut, mArrGet}:
|
||||||
# cannot borrow these magics for now
|
# cannot borrow these magics for now
|
||||||
result = nil
|
result = nil
|
||||||
|
|
@ -145,7 +145,11 @@ proc instantiateBody(c: PContext, n, params: PNode, result, orig: PSym) =
|
||||||
if sfGenSym in param.flags:
|
if sfGenSym in param.flags:
|
||||||
idTablePut(symMap, params[i].sym, result.typ.n[param.position+1].sym)
|
idTablePut(symMap, params[i].sym, result.typ.n[param.position+1].sym)
|
||||||
freshGenSyms(c, b, result, orig, symMap)
|
freshGenSyms(c, b, result, orig, symMap)
|
||||||
b = semProcBody(c, b)
|
|
||||||
|
if sfBorrow notin orig.flags:
|
||||||
|
# We do not want to generate a body for generic borrowed procs.
|
||||||
|
# As body is a sym to the borrowed proc.
|
||||||
|
b = semProcBody(c, b)
|
||||||
result.ast[bodyPos] = hloBody(c, b)
|
result.ast[bodyPos] = hloBody(c, b)
|
||||||
excl(result.flags, sfForward)
|
excl(result.flags, sfForward)
|
||||||
trackProc(c, result, result.ast[bodyPos])
|
trackProc(c, result, result.ast[bodyPos])
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,14 @@ proc transformSymAux(c: PTransf, n: PNode): PNode =
|
||||||
var tc = c.transCon
|
var tc = c.transCon
|
||||||
if sfBorrow in s.flags and s.kind in routineKinds:
|
if sfBorrow in s.flags and s.kind in routineKinds:
|
||||||
# simply exchange the symbol:
|
# simply exchange the symbol:
|
||||||
|
var s = s
|
||||||
|
while true:
|
||||||
|
# Skips over all borrowed procs getting the last proc symbol without an implementation
|
||||||
|
let body = getBody(c.graph, s)
|
||||||
|
if body.kind == nkSym and sfBorrow in body.sym.flags and getBody(c.graph, body.sym).kind == nkSym:
|
||||||
|
s = body.sym
|
||||||
|
else:
|
||||||
|
break
|
||||||
b = getBody(c.graph, s)
|
b = getBody(c.graph, s)
|
||||||
if b.kind != nkSym: internalError(c.graph.config, n.info, "wrong AST for borrowed symbol")
|
if b.kind != nkSym: internalError(c.graph.config, n.info, "wrong AST for borrowed symbol")
|
||||||
b = newSymNode(b.sym, n.info)
|
b = newSymNode(b.sym, n.info)
|
||||||
|
|
|
||||||
32
tests/borrow/typeclassborrow.nim
Normal file
32
tests/borrow/typeclassborrow.nim
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
type
|
||||||
|
Foo = distinct seq[int]
|
||||||
|
Bar[N: static[int]] = distinct seq[int]
|
||||||
|
Baz = distinct Bar[10]
|
||||||
|
|
||||||
|
proc newSeq(s: var Foo, n: Natural) {.borrow.}
|
||||||
|
proc newSeq(s: var Bar, n: Natural) {.borrow.}
|
||||||
|
proc newSeq(s: var Baz, n: Natural) {.borrow.}
|
||||||
|
|
||||||
|
|
||||||
|
proc `$`(s: Foo): string {.borrow.}
|
||||||
|
proc `$`(s: Bar): string {.borrow.}
|
||||||
|
proc `$`(s: Baz): string {.borrow.}
|
||||||
|
|
||||||
|
proc doThing(b: Bar) = discard
|
||||||
|
proc doThing(b: Baz) {.borrow.}
|
||||||
|
|
||||||
|
var
|
||||||
|
foo: Foo
|
||||||
|
bar: Bar[10]
|
||||||
|
baz: Baz
|
||||||
|
|
||||||
|
newSeq(foo, 100)
|
||||||
|
newSeq(bar, bar.N)
|
||||||
|
newSeq(baz, 10)
|
||||||
|
|
||||||
|
bar.doThing()
|
||||||
|
baz.doThing()
|
||||||
|
|
||||||
|
assert $seq[int](foo) == $foo
|
||||||
|
assert $seq[int](bar) == $bar
|
||||||
|
assert $seq[int](baz) == $baz
|
||||||
Loading…
Add table
Add a link
Reference in a new issue