feat(rlp/rlpgen): support alias types (#154)

## Why this should be merged

To be able to generate RLP code using type aliases (defined e.g. in
`coreth`).
This can and should be PR-ed upstream as well I think.

## How this works

Call `types.Unalias()` at the start of `buildContext.makeOp()`. The
alternative of adding a `case` to the switch statement adds unnecessary
recursive calls while `types.Unalias()` is a no-op if not an alias.

## How this was tested

New `rlpgen` unit test with aliases of well-known types that have
special handling—these make their proper handling easy to spot when
inspecting generated code. A recursive alias in the same test also
demonstrates full alias resolution.

---------

Co-authored-by: Arran Schlosberg <me@arranschlosberg.com>
This commit is contained in:
Quentin McGaw 2025-02-27 12:13:11 +01:00 committed by GitHub
parent 9f410ecc7e
commit 739ba847f6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 67 additions and 2 deletions

View file

@ -673,7 +673,7 @@ func (op sliceOp) genDecode(ctx *genContext) (string, string) {
}
func (bctx *buildContext) makeOp(name *types.Named, typ types.Type, tags rlpstruct.Tags) (op, error) {
switch typ := typ.(type) {
switch typ := types.Unalias(typ).(type) {
case *types.Named:
if isBigInt(typ) {
return bigIntOp{}, nil

View file

@ -47,7 +47,7 @@ func init() {
}
}
var tests = []string{"uints", "nil", "rawvalue", "optional", "bigint", "uint256"}
var tests = []string{"uints", "nil", "rawvalue", "optional", "bigint", "uint256", "alias"}
func TestOutput(t *testing.T) {
for _, test := range tests {

22
rlp/rlpgen/testdata/alias.in.txt vendored Normal file
View file

@ -0,0 +1,22 @@
// -*- mode: go -*-
package test
import (
"math/big"
"github.com/holiman/uint256"
)
// Alias types chosen because their originals have special handling that is easy
// to spot when inspecting generated output.
type (
Big = big.Int
// Demonstrate recursive unaliasing
intermediate = uint256.Int
Uint256 = intermediate
)
type Test struct {
BigAlias Big
Uint256Alias Uint256
}

43
rlp/rlpgen/testdata/alias.out.txt vendored Normal file
View file

@ -0,0 +1,43 @@
package test
import "github.com/ava-labs/libevm/rlp"
import "github.com/holiman/uint256"
import "io"
func (obj *Test) EncodeRLP(_w io.Writer) error {
w := rlp.NewEncoderBuffer(_w)
_tmp0 := w.List()
if obj.BigAlias.Sign() == -1 {
return rlp.ErrNegativeBigInt
}
w.WriteBigInt(&obj.BigAlias)
w.WriteUint256(&obj.Uint256Alias)
w.ListEnd(_tmp0)
return w.Flush()
}
func (obj *Test) DecodeRLP(dec *rlp.Stream) error {
var _tmp0 Test
{
if _, err := dec.List(); err != nil {
return err
}
// BigAlias:
_tmp1, err := dec.BigInt()
if err != nil {
return err
}
_tmp0.BigAlias = (*_tmp1)
// Uint256Alias:
var _tmp2 uint256.Int
if err := dec.ReadUint256(&_tmp2); err != nil {
return err
}
_tmp0.Uint256Alias = _tmp2
if err := dec.ListEnd(); err != nil {
return err
}
}
*obj = _tmp0
return nil
}