diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index dbaf9fcd7ce2e..9dd784ba32e23 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -510,13 +510,18 @@ proc getSeqPayloadType(m: BModule; t: PType): Rope = result = getTypeDescWeak(m, t, check, dkParam) & "_Content" #result = getTypeForward(m, t, hashType(t)) & "_Content" +proc seqPayloadElemType(t: PType): PType = + ## ``seq[var T]`` is a view over a ``seq[T]``. The modifier controls element + ## access but doesn't change the payload's layout. + result = t.skipTypes(abstractInst).elementType.skipTypes({tyVar}) + proc seqPayloadElem(m: BModule; t: PType): Snippet = ## Returns the C type name for a seq's element as stored in the payload, ## suitable for sizeof()/alignof(). Must use dkVar, not the dkParam default, ## because reified openArrays (experimental views) differ: dkParam gives a ## bare pointer (T*) while dkVar gives the two-word struct actually stored. var check = initIntSet() - result = getTypeDescAux(m, t.elementType, check, dkVar) + result = getTypeDescAux(m, seqPayloadElemType(t), check, dkVar) proc seqV2ContentType(m: BModule; t: PType; check: var IntSet) = let sig = hashType(t, m.config) @@ -524,7 +529,7 @@ proc seqV2ContentType(m: BModule; t: PType; check: var IntSet) = if result == "": discard getTypeDescAux(m, t, check, dkVar) else: - let dataTyp = getTypeDescAux(m, t.skipTypes(abstractInst)[0], check, dkVar) + let dataTyp = getTypeDescAux(m, seqPayloadElemType(t), check, dkVar) m.s[cfsTypes].addSimpleStruct(m, name = result & "_Content", baseType = ""): m.s[cfsTypes].addField(name = "cap", typ = NimInt) m.s[cfsTypes].addField(name = "data", diff --git a/tests/views/t26058.nim b/tests/views/t26058.nim new file mode 100644 index 0000000000000..b4523963af12b --- /dev/null +++ b/tests/views/t26058.nim @@ -0,0 +1,45 @@ +{.experimental: "views".} + +block: # bug #26058 + type + Kind = enum + kA, kB + + StateA = object + x: int + + StateB = object + y: string + z: string + + Item = object + cache: int + case kind: Kind + of kA: + stateA: StateA + of kB: + stateB: StateB + + proc update(item: var Item) = + case item.kind + of kA: + item.cache = item.stateA.x + of kB: + item.cache = item.stateB.y.len + + proc updateAll(items: var seq[var Item]): array[2, uint] = + var i = 0 + for item in items.mitems: + result[i] = cast[uint](item.addr) + update(item) + inc i + + var items = @[ + Item(kind: kA, stateA: StateA(x: 1)), + Item(kind: kA, stateA: StateA(x: 2)) + ] + + let addresses = updateAll(items) + doAssert addresses[1] - addresses[0] == sizeof(Item).uint + doAssert items[0].cache == 1 + doAssert items[1].cache == 2