diff options
-rw-r--r-- | compiler/sigmatch.nim | 18 | ||||
-rw-r--r-- | tests/converter/tconvert.nim | 16 | ||||
-rw-r--r-- | tests/converter/tconverter_unique_ptr.nim | 60 |
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 |