summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorJason Beetham <beefers331@gmail.com>2021-10-26 03:29:07 -0600
committerGitHub <noreply@github.com>2021-10-26 11:29:07 +0200
commit8d5a27518929bd4c54f4beb7e40a5fc382d3dd05 (patch)
tree2280f8122f8e5daad73e93e3faee1db865258bd5 /compiler
parent83a2515af7aeb9a1c12015321243399a0d1f4c95 (diff)
downloadNim-8d5a27518929bd4c54f4beb7e40a5fc382d3dd05.tar.gz
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
Diffstat (limited to 'compiler')
-rw-r--r--compiler/semcall.nim13
-rw-r--r--compiler/seminst.nim6
-rw-r--r--compiler/transf.nim8
3 files changed, 24 insertions, 3 deletions
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index a3064788e..36658d472 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -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
\ No newline at end of file
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 456e40a94..6fae0583d 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -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])
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 89fa89701..edb8d3573 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -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)