mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-18 13:30:33 +00:00
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:
@@ -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
|
||||
@@ -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])
|
||||
|
||||
@@ -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)
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user