workaround codegen error for `Base10.decode` (#111)

Calling `Base10.decode` may lead to different structures being generated
for use with `uint64`.

The one normally generated is:

```
struct tyObject_Result__559ckyoL0ZZBsNFIYXjaoeg {NIM_BOOL o;
union{
struct {NCSTRING e;
} _o_1;
struct {unsigned long long v;
} _o_2;
};
```

But sometimes, it may be generated as:

```
struct tyObject_Result__xZhi1m1g75ioXsKjx9bN5bg {NIM_BOOL o;
union{
struct {NCSTRING e;
} _o_1;
struct {NU64 v;
} _o_2;
};
```

When the latter is generated, the compiler throws with:
```
error: passing 'tyObject_Result__xZhi1m1g75ioXsKjx9bN5bg' (aka 'struct tyObject_Result__xZhi1m1g75ioXsKjx9bN5bg') to parameter of incompatible type 'tyObject_Result__559ckyoL0ZZBsNFIYXjaoeg' (aka 'struct tyObject_Result__559ckyoL0ZZBsNFIYXjaoeg')
```
for
```
proc getInt*(ht: HttpTables, key: string): uint64 =
  let res = Base10.decode(uint64, ht.getString(key))
  if res.isOk():
    res.get()    # This line may lead to the compiler error above
  else:
    0'u64
```

By passing the type as a generic param, the `unsigned long long` version
gets consistently generated / used regardless of include order.

Minimal POC to trigger the bug, from `nimbus-eth2` root:
```
echo 'import beacon_chain/conf, beacon_chain/sync/sync_manager' >x.nim
nim c -d:"libp2p_pki_schemes=secp256k1" -r x
```
Swapping include order (`conf` after `sync_manager`) works.
This commit is contained in:
Etan Kissling 2023-08-25 00:04:33 +02:00 committed by GitHub
parent b17ac2e753
commit 3159137d9a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 3 additions and 2 deletions

View File

@ -39,8 +39,9 @@ type
data*: array[maxLen(Base10, T), byte]
len*: int8 # >= 1 when holding valid unsigned integer
proc decode*[A: byte|char](B: typedesc[Base10], T: typedesc[SomeUnsignedInt],
src: openArray[A]): Result[T, cstring] =
proc decode*[A: byte|char, T: SomeUnsignedInt](
B: typedesc[Base10], t: typedesc[T],
src: openArray[A]): Result[T, cstring] =
## Convert base10 encoded string or array of bytes to unsigned integer.
const
MaxValue = T(high(T) div 10)