mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-27 09:01:37 +00:00
fixes #24720; std lib iterators unnecessarily require value copies
This commit is contained in:
@@ -65,7 +65,7 @@ proc semTypeOf(c: PContext; n: PNode): PNode =
|
||||
t.incl tfNonConstExpr
|
||||
else:
|
||||
t = base
|
||||
result.typ = makeTypeDesc(c, t)
|
||||
result.typ = makeTypeDesc(c, decayTypeOfView(c, t))
|
||||
|
||||
type
|
||||
SemAsgnMode = enum asgnNormal, noOverloadedSubscript, noOverloadedAsgn
|
||||
|
||||
@@ -1879,6 +1879,38 @@ proc fixupTypeOf(c: PContext, prev: PType, typ: PType) =
|
||||
if prev.kind != tyGenericBody:
|
||||
assignType(prev, result)
|
||||
|
||||
proc decayTypeOfView(c: PContext, typ: PType): PType =
|
||||
if typ == nil: return nil
|
||||
let t = typ.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
case t.kind
|
||||
of tyVar, tyLent:
|
||||
result = decayTypeOfView(c, t.elementType)
|
||||
of tyTuple:
|
||||
var changed = false
|
||||
var kids = newSeq[PType](t.len)
|
||||
for i in 0..<t.len:
|
||||
kids[i] = decayTypeOfView(c, t[i])
|
||||
if kids[i] != t[i]: changed = true
|
||||
if changed:
|
||||
result = copyType(t, c.idgen, t.owner)
|
||||
for i in 0..<kids.len:
|
||||
result[i] = kids[i]
|
||||
if t.n != nil:
|
||||
result.n = copyNode(t.n)
|
||||
for it in t.n:
|
||||
if it.kind == nkSym and it.sym.kind == skField:
|
||||
let field = copySym(it.sym, c.idgen)
|
||||
field.ast = it.sym.ast
|
||||
if field.position >= 0 and field.position < kids.len:
|
||||
field.typ = kids[field.position]
|
||||
result.n.add newSymNode(field, it.info)
|
||||
else:
|
||||
result.n.add copyTree(it)
|
||||
else:
|
||||
result = typ
|
||||
else:
|
||||
result = typ
|
||||
|
||||
proc semTypeExpr(c: PContext, n: PNode; prev: PType): PType =
|
||||
var n = semExprWithType(c, n, {efDetermineType})
|
||||
if n.typ.kind == tyTypeDesc:
|
||||
@@ -2078,6 +2110,7 @@ proc semTypeOf(c: PContext; n: PNode; prev: PType): PType =
|
||||
result.incl tfNonConstExpr
|
||||
else:
|
||||
result = base
|
||||
result = decayTypeOfView(c, result)
|
||||
fixupTypeOf(c, prev, result)
|
||||
|
||||
proc semTypeOf2(c: PContext; n: PNode; prev: PType): PType =
|
||||
@@ -2103,6 +2136,7 @@ proc semTypeOf2(c: PContext; n: PNode; prev: PType): PType =
|
||||
result.incl tfNonConstExpr
|
||||
else:
|
||||
result = base
|
||||
result = decayTypeOfView(c, result)
|
||||
fixupTypeOf(c, prev, result)
|
||||
|
||||
proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||
|
||||
@@ -739,7 +739,7 @@ template withValue*[A, B](t: Table[A, B], key: A,
|
||||
discard
|
||||
|
||||
|
||||
iterator pairs*[A, B](t: Table[A, B]): (A, B) =
|
||||
iterator pairs*[A, B](t: Table[A, B]): (lent A, lent B) =
|
||||
## Iterates over any `(key, value)` pair in the table `t`.
|
||||
##
|
||||
## See also:
|
||||
@@ -1201,7 +1201,7 @@ proc `==`*[A, B](s, t: TableRef[A, B]): bool =
|
||||
|
||||
|
||||
|
||||
iterator pairs*[A, B](t: TableRef[A, B]): (A, B) =
|
||||
iterator pairs*[A, B](t: TableRef[A, B]): (lent A, lent B) =
|
||||
## Iterates over any `(key, value)` pair in the table `t`.
|
||||
##
|
||||
## See also:
|
||||
@@ -1789,7 +1789,7 @@ proc `==`*[A, B](s, t: OrderedTable[A, B]): bool =
|
||||
|
||||
|
||||
|
||||
iterator pairs*[A, B](t: OrderedTable[A, B]): (A, B) =
|
||||
iterator pairs*[A, B](t: OrderedTable[A, B]): (lent A, lent B) =
|
||||
## Iterates over any `(key, value)` pair in the table `t` in insertion
|
||||
## order.
|
||||
##
|
||||
@@ -2212,7 +2212,7 @@ proc `==`*[A, B](s, t: OrderedTableRef[A, B]): bool =
|
||||
|
||||
|
||||
|
||||
iterator pairs*[A, B](t: OrderedTableRef[A, B]): (A, B) =
|
||||
iterator pairs*[A, B](t: OrderedTableRef[A, B]): (lent A, lent B) =
|
||||
## Iterates over any `(key, value)` pair in the table `t` in insertion
|
||||
## order.
|
||||
##
|
||||
@@ -2622,7 +2622,7 @@ proc `==`*[A](s, t: CountTable[A]): bool =
|
||||
equalsImpl(s, t)
|
||||
|
||||
|
||||
iterator pairs*[A](t: CountTable[A]): (A, int) =
|
||||
iterator pairs*[A](t: CountTable[A]): (lent A, int) =
|
||||
## Iterates over any `(key, value)` pair in the table `t`.
|
||||
##
|
||||
## See also:
|
||||
@@ -2899,7 +2899,7 @@ proc `==`*[A](s, t: CountTableRef[A]): bool =
|
||||
else: result = s[] == t[]
|
||||
|
||||
|
||||
iterator pairs*[A](t: CountTableRef[A]): (A, int) =
|
||||
iterator pairs*[A](t: CountTableRef[A]): (lent A, int) =
|
||||
## Iterates over any `(key, value)` pair in the table `t`.
|
||||
##
|
||||
## See also:
|
||||
|
||||
20
tests/arc/t24720.nim
Normal file
20
tests/arc/t24720.nim
Normal file
@@ -0,0 +1,20 @@
|
||||
discard """
|
||||
matrix: "--mm:orc"
|
||||
output: '''
|
||||
found entry
|
||||
'''
|
||||
"""
|
||||
|
||||
import std/tables
|
||||
type NoCopies = object
|
||||
|
||||
proc `=copy`(a: var NoCopies, b: NoCopies) {.error.}
|
||||
|
||||
# bug #24720
|
||||
proc foo() =
|
||||
var t: Table[int, NoCopies]
|
||||
t[3] = NoCopies() # only moves
|
||||
for k, v in t.pairs(): # lent values, no need to copy!
|
||||
echo "found entry"
|
||||
|
||||
foo()
|
||||
Reference in New Issue
Block a user