mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 08:54:53 +00:00
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.
This commit is contained in:
@@ -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:
|
||||
|
||||
29
tests/vm/tconstarrayresem.nim
Normal file
29
tests/vm/tconstarrayresem.nim
Normal file
@@ -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())
|
||||
Reference in New Issue
Block a user