diff options
author | metagn <metagngn@gmail.com> | 2024-10-03 20:35:53 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-03 19:35:53 +0200 |
commit | d98ef312f0cf8745d39c940b16d8d2dce1dfa70f (patch) | |
tree | d4e69247521cab04e5a4e07931f02c25dbf232f9 | |
parent | 89978b48baeed0c745d45d666a9786c8d9457581 (diff) | |
download | Nim-d98ef312f0cf8745d39c940b16d8d2dce1dfa70f.tar.gz |
don't construct array type for already typed `nkBracket` node (#24224)
fixes #23010, split from #24195 When resemming bracket nodes, the compiler currently unconditionally makes a new node with an array type based on the node. However the VM can generate bracket nodes with `seq` types, which this erases. To fix this, if a bracket node already has a type, we still resem the bracket node, but don't construct a new type for it, instead using the type of the original node. A version of this was rejected that didn't resem the node at all if it was typed, but I can't find it. The difference with this one is that the individual elements are still resemmed. This should fix the break caused by #24184 so we could redo it after this PR but it might still have issues, not to mention the related pre-existing issues like #22793, #12559 etc.
-rw-r--r-- | compiler/semexprs.nim | 65 | ||||
-rw-r--r-- | tests/vm/tconstarrayresem.nim | 29 |
2 files changed, 72 insertions, 22 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 6a3b40111..2885142a7 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -722,29 +722,41 @@ proc arrayConstrType(c: PContext, n: PNode): PType = proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode = result = newNodeI(nkBracket, n.info) - result.typ = newTypeS(tyArray, c) + # nkBracket nodes can also be produced by the VM as seq constant nodes + # in which case, we cannot produce a new array type for the node, + # as this might lose type info even when the node has array type + let constructType = n.typ.isNil var expectedElementType, expectedIndexType: PType = nil - if expectedType != nil: - let expected = expectedType.skipTypes(abstractRange-{tyDistinct}) - case expected.kind + var expectedBase: PType = nil + if constructType: + result.typ = newTypeS(tyArray, c) + rawAddSon(result.typ, nil) # index type + if expectedType != nil: + expectedBase = expectedType.skipTypes(abstractRange-{tyDistinct}) + else: + result.typ = n.typ + expectedBase = n.typ.skipTypes(abstractRange) # include tyDistinct this time + if expectedBase != nil: + case expectedBase.kind of tyArray: - expectedIndexType = expected[0] - expectedElementType = expected[1] - of tyOpenArray: - expectedElementType = expected[0] + expectedIndexType = expectedBase[0] + expectedElementType = expectedBase[1] + of tyOpenArray, tySequence: + # typed bracket expressions can also have seq type + expectedElementType = expectedBase[0] else: discard - rawAddSon(result.typ, nil) # index type var firstIndex, lastIndex: Int128 = Zero indexType = getSysType(c.graph, n.info, tyInt) lastValidIndex = lastOrd(c.config, indexType) if n.len == 0: - rawAddSon(result.typ, - if expectedElementType != nil and - typeAllowed(expectedElementType, skLet, c) == nil: - expectedElementType - else: - newTypeS(tyEmpty, c)) # needs an empty basetype! + if constructType: + rawAddSon(result.typ, + if expectedElementType != nil and + typeAllowed(expectedElementType, skLet, c) == nil: + expectedElementType + else: + newTypeS(tyEmpty, c)) # needs an empty basetype! lastIndex = toInt128(-1) else: var x = n[0] @@ -761,9 +773,13 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PTyp x = x[1] let yy = semExprWithType(c, x, {efTypeAllowed}, expectedElementType) - var typ = yy.typ - if expectedElementType == nil: - expectedElementType = typ + var typ: PType + if constructType: + typ = yy.typ + if expectedElementType == nil: + expectedElementType = typ + else: + typ = expectedElementType result.add yy #var typ = skipTypes(result[0].typ, {tyGenericInst, tyVar, tyLent, tyOrdinal}) for i in 1..<n.len: @@ -783,15 +799,20 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PTyp let xx = semExprWithType(c, x, {efTypeAllowed}, expectedElementType) result.add xx - typ = commonType(c, typ, xx.typ) + if constructType: + typ = commonType(c, typ, xx.typ) #n[i] = semExprWithType(c, x, {}) #result.add fitNode(c, typ, n[i]) inc(lastIndex) - addSonSkipIntLit(result.typ, typ, c.idgen) + if constructType: + addSonSkipIntLit(result.typ, typ, c.idgen) for i in 0..<result.len: result[i] = fitNode(c, typ, result[i], result[i].info) - result.typ.setIndexType makeRangeType(c, toInt64(firstIndex), toInt64(lastIndex), n.info, - indexType) + if constructType: + result.typ.setIndexType( + makeRangeType(c, + toInt64(firstIndex), toInt64(lastIndex), + n.info, indexType)) proc fixAbstractType(c: PContext, n: PNode) = for i in 1..<n.len: diff --git a/tests/vm/tconstarrayresem.nim b/tests/vm/tconstarrayresem.nim new file mode 100644 index 000000000..6701cfe4d --- /dev/null +++ b/tests/vm/tconstarrayresem.nim @@ -0,0 +1,29 @@ +# issue #23010 + +type + Result[T, E] = object + case oResult: bool + of false: + discard + of true: + vResult: T + + Opt[T] = Result[T, void] + +template ok[T, E](R: type Result[T, E], x: untyped): R = + R(oResult: true, vResult: x) + +template c[T](v: T): Opt[T] = Opt[T].ok(v) + +type + FixedBytes[N: static[int]] = distinct array[N, byte] + + H = object + d: FixedBytes[2] + +const b = default(H) +template g(): untyped = + const t = default(H) + b + +discard c(g()) |