Skip to content

Commit

Permalink
fix(py): Fix array/list value serialization (#1827)
Browse files Browse the repository at this point in the history
The rust-side serialization definition for custom constants is a bit
more complex than what we had written on the python side for array and
list values.

This fixes #1826, and was tested by running the issue's example from
guppy.

- > Why aren't we testing this locally?

  Constant value deserialization is a "best effort" thing.
If we can match the serialized thing with one of the hardcoded
implementors of `CustomConst` (registered in a global var by `typetag`)
then we deserialize into the specific class.
If we cannot deserialize into any specific class, we use
`CustomSerialized` by default.
  
So even if we build a constant from python and `validate` using the rust
checker, the deserialization will succeed and validate correctly.
  
It'd be nice to fail the deserialization if a constant claims to be of
some specific kind but cannot be deserialized into it. I'll open an
issue and look a bit into it.
  • Loading branch information
aborgna-q authored Dec 20, 2024
1 parent b7b2bcd commit 7bf85b9
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 4 deletions.
8 changes: 6 additions & 2 deletions hugr-py/src/hugr/std/collections/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class ArrayVal(val.ExtensionValue):
"""Constant value for a statically sized array of elements."""

v: list[val.Value]
ty: tys.Type
ty: Array

def __init__(self, v: list[val.Value], elem_ty: tys.Type) -> None:
self.v = v
Expand All @@ -71,7 +71,11 @@ def to_value(self) -> val.Extension:
# The value list must be serialized at this point, otherwise the
# `Extension` value would not be serializable.
vs = [v._to_serial_root() for v in self.v]
return val.Extension(name, typ=self.ty, val=vs, extensions=[EXTENSION.name])
element_ty = self.ty.ty._to_serial_root()
serial_val = {"values": vs, "typ": element_ty}
return val.Extension(
name, typ=self.ty, val=serial_val, extensions=[EXTENSION.name]
)

def __str__(self) -> str:
return f"array({comma_sep_str(self.v)})"
8 changes: 6 additions & 2 deletions hugr-py/src/hugr/std/collections/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class ListVal(val.ExtensionValue):
"""Constant value for a list of elements."""

v: list[val.Value]
ty: tys.Type
ty: List

def __init__(self, v: list[val.Value], elem_ty: tys.Type) -> None:
self.v = v
Expand All @@ -50,7 +50,11 @@ def to_value(self) -> val.Extension:
# The value list must be serialized at this point, otherwise the
# `Extension` value would not be serializable.
vs = [v._to_serial_root() for v in self.v]
return val.Extension(name, typ=self.ty, val=vs, extensions=[EXTENSION.name])
element_ty = self.ty.ty._to_serial_root()
serial_val = {"values": vs, "typ": element_ty}
return val.Extension(
name, typ=self.ty, val=serial_val, extensions=[EXTENSION.name]
)

def __str__(self) -> str:
return f"[{comma_sep_str(self.v)}]"

0 comments on commit 7bf85b9

Please sign in to comment.