diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 88d7512373..dfc2b80c10 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -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 diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 4c2d84c29f..275a2bea3c 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -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..= 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 = diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index 94d8721b96..23f533f59e 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -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: diff --git a/tests/arc/t24720.nim b/tests/arc/t24720.nim new file mode 100644 index 0000000000..172ec0386b --- /dev/null +++ b/tests/arc/t24720.nim @@ -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() \ No newline at end of file