summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/sigmatch.nim18
-rw-r--r--tests/converter/tconvert.nim16
-rw-r--r--tests/converter/tconverter_unique_ptr.nim60
3 files changed, 82 insertions, 12 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index a9ea2f697..d66e8d121 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -1835,7 +1835,7 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
     if destIsGeneric:
       dest = generateTypeInstance(c, m.bindings, arg, dest)
     let fdest = typeRel(m, f, dest)
-    if fdest in {isEqual, isGeneric}:
+    if fdest in {isEqual, isGeneric} and not (dest.kind == tyLent and f.kind == tyVar):
       markUsed(c.config, arg.info, c.converters[i], c.graph.usageSym)
       var s = newSymNode(c.converters[i])
       s.typ = c.converters[i].typ
@@ -2231,8 +2231,15 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
       else:
         m.state = csNoMatch
         return
+    
     if formal.typ.kind == tyVar:
-      if not n.isLValue:
+      let arg_converter = if arg.kind == nkHiddenDeref: arg[0] else: arg
+      if arg_converter.kind == nkHiddenCallConv:
+        if arg_converter.typ.kind != tyVar:
+          m.state = csNoMatch
+          m.mutabilityProblem = uint8(f-1)
+          return  
+      elif not n.isLValue:
         m.state = csNoMatch
         m.mutabilityProblem = uint8(f-1)
         return
@@ -2243,6 +2250,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
         else: 0
     # iterates over the actual given arguments
     a = 1
+    arg: PNode # current prepared argument
 
   m.state = csMatch # until proven otherwise
   m.call = newNodeI(n.kind, n.info)
@@ -2297,7 +2305,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
       m.typedescMatched = false
       n.sons[a].sons[1] = prepareOperand(c, formal.typ, n.sons[a].sons[1])
       n.sons[a].typ = n.sons[a].sons[1].typ
-      var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
+      arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
                                 n.sons[a].sons[1], n.sons[a].sons[1])
       if arg == nil:
         m.state = csNoMatch
@@ -2334,7 +2342,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           m.typedescMatched = false
           incl(marker, formal.position)
           n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
-          var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
+          arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
                                     n.sons[a], nOrig.sons[a])
           if arg != nil and m.baseTypeMatch and container != nil:
             addSon(container, arg)
@@ -2368,7 +2376,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           m.baseTypeMatch = false
           m.typedescMatched = false
           n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
-          var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
+          arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
                                     n.sons[a], nOrig.sons[a])
           if arg == nil:
             m.state = csNoMatch
diff --git a/tests/converter/tconvert.nim b/tests/converter/tconvert.nim
index 8aa4e97a3..5eee2a92d 100644
--- a/tests/converter/tconvert.nim
+++ b/tests/converter/tconvert.nim
@@ -26,3 +26,19 @@ block:
   var x = "101"
   var y: int = x # instantiate withVar
   doAssert(y == ord('0'))
+
+
+######################
+# bug #3503
+type Foo = object
+  r: float
+
+converter toFoo(r: float): Foo =
+  result.r = r
+
+proc `+=`*(x: var Foo, r: float) =
+  x.r += r
+
+var a: Foo
+a.r += 3.0
+
diff --git a/tests/converter/tconverter_unique_ptr.nim b/tests/converter/tconverter_unique_ptr.nim
index 15ec609a3..25b001d52 100644
--- a/tests/converter/tconverter_unique_ptr.nim
+++ b/tests/converter/tconverter_unique_ptr.nim
@@ -2,9 +2,7 @@
 discard """
   file: "tconverter_unique_ptr.nim"
   targets: "c cpp"
-  output: '''5
-2.0 5
-'''
+  output: ""
 """
 
 ## Bugs 9698 and 9699
@@ -22,6 +20,8 @@ type
     data: ptr UncheckedArray[float]
 
 proc `$`(x: MyLen): string {.borrow.}
+proc `==`(x1, x2: MyLen): bool {.borrow.}
+
 
 proc `=destroy`*(m: var MySeq) {.inline.} =
   if m.data != nil:
@@ -50,10 +50,12 @@ proc len*(m: MySeq): MyLen {.inline.} = m.len
 
 proc lenx*(m: var MySeq): MyLen {.inline.} = m.len
 
-
 proc `[]`*(m: MySeq; i: MyLen): float {.inline.} =
   m.data[i.int]
 
+proc `[]`*(m: var MySeq; i: MyLen): var float {.inline.} =
+  m.data[i.int]
+
 proc `[]=`*(m: var MySeq; i: MyLen, val: float) {.inline.} =
   m.data[i.int] = val
 
@@ -97,11 +99,55 @@ proc newUniquePtr*[T](val: sink T): UniquePtr[T] =
 converter convertPtrToObj*[T](p: UniquePtr[T]): var T =
   result = p.val[]
 
-
 var pu = newUniquePtr(newMySeq(5, 1.0))
-echo pu.len
+let pu2 = newUniquePtr(newMySeq(5, 1.0))
+doAssert: pu.len == 5
+doAssert: pu2.len == 5
+doAssert: pu.lenx == 5
+doAssert: pu2.lenx == 5
 
 pu[0] = 2.0
-echo pu[0], " ", pu.lenx
+pu2[0] = 2.0
+doAssert pu[0] == 2.0
+doAssert: pu2[0] == 2.0
+
+##-----------------------------------------------------------------------------------------
+## Bugs #9735 and #9736 
+type
+  ConstPtr*[T] = object
+    ## This pointer makes it impossible to change underlying value
+    ## as it returns only `lent T`
+    val: ptr T
 
+proc `=destroy`*[T](p: var ConstPtr[T]) =
+  if p.val != nil:
+    `=destroy`(p.val[])
+    dealloc(p.val)
+    p.val = nil
+
+proc `=`*[T](dest: var ConstPtr[T], src: ConstPtr[T]) {.error.}
+
+proc `=sink`*[T](dest: var ConstPtr[T], src: ConstPtr[T]) {.inline.} =
+  if dest.val != nil and dest.val != src.val:
+    `=destroy`(dest)
+  dest.val = src.val
+
+proc newConstPtr*[T](val: sink T): ConstPtr[T] =
+  result.val = cast[type(result.val)](alloc(sizeof(result.val[])))
+  reset(result.val[])
+  result.val[] = val
+
+converter convertConstPtrToObj*[T](p: ConstPtr[T]): lent T =
+  result = p.val[]
 
+var pc = newConstPtr(newMySeq(3, 1.0))
+let pc2 = newConstPtr(newMySeq(3, 1.0))
+doAssert: pc.len == 3
+doAssert: pc.len == 3
+doAssert: compiles(pc.lenx == 2) == false
+doAssert: compiles(pc2.lenx == 2) == false
+doAssert: compiles(pc[0] = 2.0) == false
+doAssert: compiles(pc2[0] = 2.0) == false
+
+doAssert: pc[0] == 1.0
+doAssert: pc2[0] == 1.0