Skip to content

Model serialization round-trip changes Tuple to List #2652

@cqc-alec

Description

@cqc-alec
import hugr._hugr as rust
from hugr.build import Cfg
from hugr.package import Package
from hugr.tys import Bool

# Construct a `model.Package`:
cfg = Cfg(Bool)
with cfg.add_entry() as entry:
    entry.set_single_succ_outputs(*entry.inputs())
cfg.branch_exit(entry[0])
h = cfg.hugr
pkg = Package(modules=[h], extensions=[])
mdl0 = pkg.to_model()

# Perform a round-trip:
envelope = rust.package_to_bytes(mdl0)
mdl1 = rust.bytes_to_package(envelope)

# Print the two models:
print("mdl0:")
print(mdl0)
print("mdl1:")
print(mdl1)

# Drill down to the problematic term:
print("Compare terms:")
for mdl in [mdl0, mdl1]:
    print(
        mdl.modules[0]
        .root.children[0]
        .regions[0]
        .children[0]
        .regions[0]
        .children[0]
        .regions[0]
        .children[0]
        .operation.operation.args[1]
        .args[3]
    )

Output:

mdl0:
(hugr 0)

(mod)

(define-func private _1 (core.fn [(core.adt [[] []])] [(core.adt [[] []])])
  (meta (core.title "main"))
  (dfg [%1] [%2]
    (signature (core.fn [(core.adt [[] []])] [(core.adt [[] []])]))
    (cfg [%1] [%2]
      (signature (core.fn [(core.adt [[] []])] [(core.adt [[] []])]))
      (meta core.entrypoint)
      (cfg [%3] [%4]
        (signature (core.ctrl [[(core.adt [[] []])]] [[(core.adt [[] []])]]))
        (meta core.entrypoint)
        (block [%3] [%4]
          (signature (core.ctrl [[(core.adt [[] []])]] [[(core.adt [[] []])]]))
          (dfg [%5] [%6 %5]
            (signature
              (core.fn
                [(core.adt [[] []])]
                [(core.adt [[]]) (core.adt [[] []])]))
            ((core.load_const
                (core.adt [[]])
                (core.const.adt [[]] [] 0 (tuple)))
              [] [%6]
              (signature (core.fn [] [(core.adt [[]])])))))))))
mdl1:
(hugr 0)

(mod)

(define-func private _1 (core.fn [(core.adt [[] []])] [(core.adt [[] []])])
  (meta (core.title "main"))
  (dfg [%0] [%1]
    (signature (core.fn [(core.adt [[] []])] [(core.adt [[] []])]))
    (cfg [%0] [%1]
      (signature (core.fn [(core.adt [[] []])] [(core.adt [[] []])]))
      (meta core.entrypoint)
      (cfg [%2] [%3]
        (signature (core.ctrl [[(core.adt [[] []])]] [[(core.adt [[] []])]]))
        (meta core.entrypoint)
        (block [%2] [%3]
          (signature (core.ctrl [[(core.adt [[] []])]] [[(core.adt [[] []])]]))
          (dfg [%4] [%5 %4]
            (signature
              (core.fn
                [(core.adt [[] []])]
                [(core.adt [[]]) (core.adt [[] []])]))
            ((core.load_const (core.adt [[]]) (core.const.adt [[]] [] 0 []))
              [] [%5]
              (signature (core.fn [] [(core.adt [[]])])))))))))

(import core.entrypoint)

(import core.title)

(import core.adt)

(import core.ctrl)

(import core.fn)

(import core.load_const)

(import core.const.adt)
Compare terms:
(tuple)
[]

We see that mdl0 and mdl1 are similar (except for the numbers being shifted by 1, which I think is unimportant), but the core.const.adt terms are subtly different: one has a model.Tuple and the other a model.List in the "values" position. This is expected to be a Tuple, but somehow the round trip is turning it into a List.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions