seq pop malfunctions in array of seqs
### Description

Following code

```nim
proc main() =
  var trimMap = [@[1], @[2]]
  var z = 0
  for j in 0 ..< 2:
    var i = trimMap.high
    while i >= 0:
      #let len {.volatile} = trimMap[i].len # this way it "works"
      let len = trimMap[i].len
      if len > 0:
        z = trimMap[i].pop()
        echo "set"
        break
      dec i
    echo "popped ", i
    doAssert z != 0
  echo "z", z

main()
```

prints:

```
set
popped 1
set
popped 1
fatal.nim(53)            sysFatal
Error: unhandled exception: z.nim(15, 5) `z != 0`  [AssertionDefect]
```

on both devel and 2.0.14, when compiled like:

```
nim c --mm:arc -d:danger -d:lto --cc:clang z.nim
```

with clang version 18.1.8.  (-d:release instead of -d:danger has the same effect.)

The crash disappears if I do any of:

* set len to volatile
* --passc:-fno-strict-aliasing
* disable LTO
* --mm:refc

It also disappears if I switch to GCC, but this is probably by accident.
The original program that I reduced this from crashes under GCC as well.


<details>
<summary>
len is supposed to be set in shrink:
</summary>

```c
/* z.nim.c */
struct tySequence__qwqHTkRvwhrRyENtudHQ7g {
	NI len;
	tySequence__qwqHTkRvwhrRyENtudHQ7g_Content* p;
};
struct tySequence__qwqHTkRvwhrRyENtudHQ7g_Content {
	NI cap;
	NI data[SEQ_DECL_SIZE];
};

static N_INLINE(NI, pop__z_u27)(tySequence__qwqHTkRvwhrRyENtudHQ7g* s_p0) {
	NI result;
NI L;
NI T1_;
T1_ = (*s_p0).len;
L = ((NI) (T1_ - ((NI) 1)));
result = ((*s_p0)).p->data[L];
((*s_p0)).p->data[L] = 0;
shrink__z_u42(s_p0, (L));
	return result;
}

/* system.nim.c */
typedef struct tyObject_NimSeqPayload__g7Ny9bTlNzn6dsxoJOHv6LQ tyObject_NimSeqPayload__g7Ny9bTlNzn6dsxoJOHv6LQ;
/* ^ incomplete struct; never gets defined anywhere */
struct tyObject_NimSeqV2__PEQQ33xihBDluJkSxo81LQ {
	NI len;
	tyObject_NimSeqPayload__g7Ny9bTlNzn6dsxoJOHv6LQ* p;
};

N_LIB_PRIVATE N_NIMCALL(void, shrink__z_u42)(tySequence__qwqHTkRvwhrRyENtudHQ7g* x_p0, NI newLen_p1) {
	(*((tyObject_NimSeqV2__PEQQ33xihBDluJkSxo81LQ*) (x_p0))).len = newLen_p1;
}
```

Perhaps the cast violates strict aliasing?
</details>


### Nim Version

```
Nim Compiler Version 2.3.1 [Linux: amd64]
Compiled at 2025-01-01
Copyright (c) 2006-2025 by Andreas Rumpf

git hash: 3dda60a8ce32cb7d5e3e99111399a1550c145176
active boot switches: -d:release
```


### Current Output

_No response_

### Expected Output

```text
set
popped 1
set
popped 0
z1
```


### Known Workarounds

_No response_

### Additional Information

ETA: this seems to fix it

```
diff --git a/lib/system/seqs_v2.nim b/lib/system/seqs_v2.nim
index 572e77408..3817b6bc5 100644
--- a/lib/system/seqs_v2.nim
+++ b/lib/system/seqs_v2.nim
@@ -133,7 +133,7 @@ proc shrink*[T](x: var seq[T]; newLen: Natural) {.tags: [], raises: [].} =
         reset x[i]
     # XXX This is wrong for const seqs that were moved into 'x'!
     {.noSideEffect.}:
-      cast[ptr NimSeqV2[T]](addr x).len = newLen
+      cast[ptr int](addr x)[] = newLen
 
 proc grow*[T](x: var seq[T]; newLen: Natural; value: T) {.nodestroy.} =
   let oldLen = x.len
```

C allows aliasing with the first member, so it makes sense.
But if it's a strict aliasing problem, then it's not an adequate fix, because the cast is also performed in other functions.