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:
Jason Beetham
2021-10-26 03:29:07 -06:00
committed by GitHub
parent 83a2515af7
commit 8d5a275189
4 changed files with 56 additions and 3 deletions

View File

@@ -703,7 +703,16 @@ proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym =
call.add(newIdentNode(fn.name, fn.info))
for i in 1..<fn.typ.n.len:
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
var x: PType
if param.typ.kind == tyVar:
@@ -721,4 +730,4 @@ proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym =
result = nil
elif result.magic in {mArrPut, mArrGet}:
# cannot borrow these magics for now
result = nil
result = nil

View File

@@ -145,7 +145,11 @@ proc instantiateBody(c: PContext, n, params: PNode, result, orig: PSym) =
if sfGenSym in param.flags:
idTablePut(symMap, params[i].sym, result.typ.n[param.position+1].sym)
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)
excl(result.flags, sfForward)
trackProc(c, result, result.ast[bodyPos])

View File

@@ -124,6 +124,14 @@ proc transformSymAux(c: PTransf, n: PNode): PNode =
var tc = c.transCon
if sfBorrow in s.flags and s.kind in routineKinds:
# 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)
if b.kind != nkSym: internalError(c.graph.config, n.info, "wrong AST for borrowed symbol")
b = newSymNode(b.sym, n.info)

View 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