From 7ae39f9ceef81ba4bbed3bf81c5e3cdd2eb501dc Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Tue, 17 May 2022 17:03:57 +0200 Subject: [PATCH] workaround codegen error for `Base10.decode` 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. --- stew/base10.nim | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/stew/base10.nim b/stew/base10.nim index 02faacfd..e089a683 100644 --- a/stew/base10.nim +++ b/stew/base10.nim @@ -1,4 +1,4 @@ -## Copyright (c) 2021 Status Research & Development GmbH +## Copyright (c) 2021-2022 Status Research & Development GmbH ## Licensed under either of ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT)) @@ -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)