summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semmagic.nim2
-rw-r--r--compiler/sigmatch.nim8
-rw-r--r--compiler/sizealignoffsetimpl.nim8
-rw-r--r--tests/destructor/tatomicptrs.nim52
4 files changed, 59 insertions, 11 deletions
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 2aae562f9..6ce6fc12e 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -346,7 +346,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
       result.info = n.info
       result.typ = n.typ
     else:
-      localError(c.config, n.info, "cannot evaluate 'sizeof' because its type is not defined completely")
+      localError(c.config, n.info, "cannot evaluate 'sizeof' because its type is not defined completely, type: " & n[1].typ.typeToString)
       result = n
   of mAlignOf:
     result = newIntNode(nkIntLit, getAlign(c.config, n[1].typ))
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 4adf0bed3..a9ea2f697 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -432,7 +432,7 @@ proc handleFloatRange(f, a: PType): TTypeRelation =
     else: result = isNone
 
 proc genericParamPut(c: var TCandidate; last, fGenericOrigin: PType) =
- if fGenericOrigin != nil and last.kind == tyGenericInst and
+  if fGenericOrigin != nil and last.kind == tyGenericInst and
      last.len-1 == fGenericOrigin.len:
    for i in countup(1, sonsLen(fGenericOrigin) - 1):
      let x = PType(idTableGet(c.bindings, fGenericOrigin.sons[i]))
@@ -1034,8 +1034,8 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
 
   template doBind: bool = trDontBind notin flags
 
-  # var and static arguments match regular modifier-free types
-  var a = maybeSkipDistinct(c, aOrig.skipTypes({tyStatic, tyVar, tyLent}), c.calleeSym)
+  # var, sink and static arguments match regular modifier-free types
+  var a = maybeSkipDistinct(c, aOrig.skipTypes({tyStatic, tyVar, tyLent, tySink}), c.calleeSym)
   # XXX: Theoretically, maybeSkipDistinct could be called before we even
   # start the param matching process. This could be done in `prepareOperand`
   # for example, but unfortunately `prepareOperand` is not called in certain
@@ -1045,7 +1045,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
     return typeRel(c, f, lastSon(aOrig))
 
   if a.kind == tyGenericInst and
-      skipTypes(f, {tyVar, tyLent}).kind notin {
+      skipTypes(f, {tyVar, tyLent, tySink}).kind notin {
         tyGenericBody, tyGenericInvocation,
         tyGenericInst, tyGenericParam} + tyTypeClasses:
     return typeRel(c, f, lastSon(a))
diff --git a/compiler/sizealignoffsetimpl.nim b/compiler/sizealignoffsetimpl.nim
index 4791788fa..f5ecc04b1 100644
--- a/compiler/sizealignoffsetimpl.nim
+++ b/compiler/sizealignoffsetimpl.nim
@@ -237,9 +237,9 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
     # recursive tuplers are not allowed and should be detected in the frontend
     if base.kind == tyTuple:
       computeSizeAlign(conf, base)
-      if base.size == szIllegalRecursion:
-        typ.size = szIllegalRecursion
-        typ.align = szIllegalRecursion
+      if base.size < 0:
+        typ.size = base.size
+        typ.align = base.align
         return
 
     typ.align = int16(conf.target.ptrSize)
@@ -379,7 +379,7 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
       typ.size = typ.lastSon.size
       typ.align = typ.lastSon.align
 
-  of tyGenericInst, tyDistinct, tyGenericBody, tyAlias:
+  of tyGenericInst, tyDistinct, tyGenericBody, tyAlias, tySink:
     computeSizeAlign(conf, typ.lastSon)
     typ.size = typ.lastSon.size
     typ.align = typ.lastSon.align
diff --git a/tests/destructor/tatomicptrs.nim b/tests/destructor/tatomicptrs.nim
index d20596415..fd8fc34d9 100644
--- a/tests/destructor/tatomicptrs.nim
+++ b/tests/destructor/tatomicptrs.nim
@@ -8,6 +8,8 @@ allocating
 deallocating
 deallocating
 deallocating
+allocating
+deallocating
 '''
   cmd: '''nim c --newruntime $file'''
 """
@@ -23,8 +25,7 @@ template incRef(x) =
 
 template decRef(x): untyped = atomicDec(x.refcount)
 
-proc makeShared*[T](x: T): SharedPtr[T] =
-  # XXX could benefit from 'sink' parameter.
+proc makeShared*[T](x: sink T): SharedPtr[T] =
   # XXX could benefit from a macro that generates it.
   result = cast[SharedPtr[T]](allocShared(sizeof(x)))
   result.x[] = x
@@ -59,6 +60,9 @@ proc `=sink`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) =
       echo "deallocating"
     dest.x = src.x
 
+proc get*[T](s: SharedPtr[T]): lent T =
+  s.x[]
+
 template `.`*[T](s: SharedPtr[T]; field: untyped): untyped =
   s.x.field
 
@@ -99,3 +103,47 @@ proc main =
 
 main()
 
+
+
+#-------------------------------------------------------
+#bug #9781
+
+type
+  MySeq* [T] = object
+    refcount: int
+    len: int
+    data: ptr UncheckedArray[T]
+
+proc `=destroy`*[T](m: var MySeq[T]) {.inline.} =
+  if m.data != nil:
+    deallocShared(m.data)
+    m.data = nil
+
+proc `=`*[T](m: var MySeq[T], m2: MySeq[T]) =
+  if m.data == m2.data: return
+  if m.data != nil:
+    `=destroy`(m)
+
+  m.len = m2.len
+  let bytes = m.len.int * sizeof(float) 
+  if bytes > 0:
+    m.data = cast[ptr UncheckedArray[T]](allocShared(bytes))
+    copyMem(m.data, m2.data, bytes)
+
+proc `=sink`*[T](m: var MySeq[T], m2: MySeq[T]) {.inline.} =
+  if m.data != m2.data:
+    if m.data != nil:
+      `=destroy`(m)
+    m.len = m2.len
+    m.data = m2.data
+
+proc len*[T](m: MySeq[T]): int {.inline.} = m.len
+
+proc newMySeq*[T](size: int, initial_value: T): MySeq[T] =
+  result.len = size
+  if size > 0:
+    result.data = cast[ptr UncheckedArray[T]](allocShared(sizeof(T) * size))
+
+
+let x = makeShared(newMySeq(10, 1.0))
+doAssert: x.get().len == 10