Skip to content

Conversation

zrho
Copy link
Contributor

@zrho zrho commented Jun 6, 2025

This PR merges the TypeParam and TypeArg types into one Term type in Rust and adds a StaticType variant. The JSON encoding remains unchanged for now by the help of a small compatibility layer, which allows us to leave the Python side alone in this PR.

BREAKING CHANGE: TypeParam and TypeArg are now merged in Rust. Variant names in TypeParam have been suffixed with Type to avoid conflict.

Closes #2295.

Copy link

codecov bot commented Jun 6, 2025

Codecov Report

Attention: Patch coverage is 79.58199% with 127 lines in your changes missing coverage. Please review.

Project coverage is 82.13%. Comparing base (cbaf9bf) to head (7a39de3).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
hugr-core/src/types/type_param.rs 79.09% 46 Missing ⚠️
hugr-core/src/import.rs 51.11% 15 Missing and 7 partials ⚠️
hugr-core/src/export.rs 46.15% 20 Missing and 1 partial ⚠️
hugr-core/src/extension/resolution/types_mut.rs 26.31% 8 Missing and 6 partials ⚠️
hugr-core/src/extension/resolution/types.rs 55.00% 9 Missing ⚠️
hugr-core/src/types/serialize.rs 90.19% 4 Missing and 1 partial ⚠️
hugr-core/src/extension/op_def.rs 69.23% 0 Missing and 4 partials ⚠️
hugr-core/src/types/poly_func.rs 94.87% 0 Missing and 2 partials ⚠️
hugr-core/src/extension/resolution.rs 0.00% 1 Missing ⚠️
hugr-core/src/extension/type_def.rs 92.30% 1 Missing ⚠️
... and 2 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2309      +/-   ##
==========================================
- Coverage   82.15%   82.13%   -0.03%     
==========================================
  Files         241      241              
  Lines       44006    43937      -69     
  Branches    39846    39766      -80     
==========================================
- Hits        36154    36086      -68     
- Misses       5859     5863       +4     
+ Partials     1993     1988       -5     
Flag Coverage Δ
python 85.30% <ø> (-0.21%) ⬇️
rust 81.79% <79.58%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@hugrbot
Copy link
Collaborator

hugrbot commented Jun 6, 2025

This PR contains breaking changes to the public Rust API.

cargo-semver-checks summary

--- failure auto_trait_impl_removed: auto trait no longer implemented ---

Description:
A public type has stopped implementing one or more auto traits. This can break downstream code that depends on the traits being implemented.
      ref: https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits
     impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/auto_trait_impl_removed.ron

Failed in:
type Term is no longer UnwindSafe, in /home/runner/work/hugr/hugr/PR_BRANCH/hugr-core/src/types/type_param.rs:68
type Term is no longer RefUnwindSafe, in /home/runner/work/hugr/hugr/PR_BRANCH/hugr-core/src/types/type_param.rs:68

--- failure enum_missing: pub enum removed or renamed ---

Description:
A publicly-visible enum cannot be imported by its prior path. A `pub use` may have been removed, or the enum itself may have been renamed or removed entirely.
      ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
     impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/enum_missing.ron

Failed in:
enum hugr_core::types::type_param::TypeArgError, previously in file /home/runner/work/hugr/hugr/BASELINE_BRANCH/hugr-core/src/types/type_param.rs:495

--- failure enum_variant_missing: pub enum variant removed or renamed ---

Description:
A publicly-visible enum has at least one variant that is no longer available under its prior name. It may have been renamed or removed entirely.
      ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
     impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/enum_variant_missing.ron

Failed in:
variant Term::Type, previously in file /home/runner/work/hugr/hugr/BASELINE_BRANCH/hugr-core/src/types/type_param.rs:164
variant Term::Type, previously in file /home/runner/work/hugr/hugr/BASELINE_BRANCH/hugr-core/src/types/type_param.rs:164
variant Term::Type, previously in file /home/runner/work/hugr/hugr/BASELINE_BRANCH/hugr-core/src/types/type_param.rs:69

--- failure function_missing: pub fn removed or renamed ---

Description:
A publicly-visible function cannot be imported by its prior path. A `pub use` may have been removed, or the function itself may have been renamed or removed entirely.
      ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
     impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/function_missing.ron

Failed in:
function hugr_core::types::type_param::check_type_arg, previously in file /home/runner/work/hugr/hugr/BASELINE_BRANCH/hugr-core/src/types/type_param.rs:427
function hugr_core::types::type_param::check_type_args, previously in file /home/runner/work/hugr/hugr/BASELINE_BRANCH/hugr-core/src/types/type_param.rs:482

--- failure inherent_method_missing: pub method removed or renamed ---

Description:
A publicly-visible method or associated fn is no longer available under its prior name. It may have been renamed or removed entirely.
      ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
     impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/inherent_method_missing.ron

Failed in:
Term::as_type, previously in file /home/runner/work/hugr/hugr/BASELINE_BRANCH/hugr-core/src/types/type_param.rs:302
Term::as_type, previously in file /home/runner/work/hugr/hugr/BASELINE_BRANCH/hugr-core/src/types/type_param.rs:302
Term::max_nat, previously in file /home/runner/work/hugr/hugr/BASELINE_BRANCH/hugr-core/src/types/type_param.rs:106
Term::bounded_nat, previously in file /home/runner/work/hugr/hugr/BASELINE_BRANCH/hugr-core/src/types/type_param.rs:114

--- failure struct_missing: pub struct removed or renamed ---

Description:
A publicly-visible struct cannot be imported by its prior path. A `pub use` may have been removed, or the struct itself may have been renamed or removed entirely.
      ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
     impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/struct_missing.ron

Failed in:
struct hugr_core::types::type_param::TypeArgVariable, previously in file /home/runner/work/hugr/hugr/BASELINE_BRANCH/hugr-core/src/types/type_param.rs:263

@zrho zrho force-pushed the zrho/core-merge-arg-param branch from 60fd19f to 40a0b95 Compare June 6, 2025 22:29
@acl-cqc
Copy link
Contributor

acl-cqc commented Jun 9, 2025

How about XXXKind for TypeParam? Is that an abuse of the normal notion of kinds?

Not having looked at code but I would think even what you say in the description, should be enough to add some tests that demonstrate "things we can't do now in hugr-core"?

@zrho
Copy link
Contributor Author

zrho commented Jun 9, 2025

The TypeArg and TypeParam aliases are there currently to avoid having to adjust a lot of code. I'm trying to do this as gradually in small incremental steps as possible. The absence of tests specifically for the new space of options has a similar reason; the real applications of this depend on more adjustments to come.

Ah, I now understand your XXXKind suggestion. I think XXXType works fine: StringType is indeed the (static) type of strings. With this change we are in a (heavily restricted) dependent typing regime in which the difference between types and kinds is blurred sufficiently as to make it traditional to not use kind.

@zrho zrho marked this pull request as ready for review June 9, 2025 13:54
@zrho zrho requested a review from a team as a code owner June 9, 2025 13:54
@zrho zrho requested review from lmondada and acl-cqc June 9, 2025 13:54
@zrho zrho force-pushed the zrho/core-merge-arg-param branch 3 times, most recently from 005e07e to f9bb1dc Compare June 13, 2025 13:43
Copy link
Contributor

@acl-cqc acl-cqc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Lukas! Yes, good move - I wondered a bit whether merging Type and TypeArg would be better to do first but I think you are right.

  • I think we need to add some validation code somewhere that checks that Terms playing the role of TypeParams (e.g., parameters declared by an OpDef/TypeDef) are indeed the XXXType variants, and you can't declare a parameter of type e.g. Term::String("foo"). Or did I miss this? There is interaction here with contains which also needs better-defining.

  • Those TypeParam = Term aliases. Presumably (surely!) they are gonna go away. So I realize this is not a PR to nitpick details but some part of me feels you should make sure that git diff origin/main HEAD | egrep '^\+.*Type(Arg|Param) shows no hits, i.e. we are heading in the right direction. At least don't add any TypeParam::XXXType!

  • On the type/runtimetype/kind naming. Just to outline a few possibilities for variants of enum Term

    • RuntimeType(Type), RuntimeTypeType(TypeBound) most consistent but a PITA
    • Runtime(Type), RuntimeType(TypeBound) consistent within Term but not consistent with anything outside it :-(
    • Might abbreviation be a way forward? I haven't got anything great atm but e.g. Runtype(Type), RuntypeType(TypeBound). Runty? ;-p
    • Or, change all Type to Kind. So: StaticKind, StringKind, TypeKind(TypeBound), Type(Type) (leaving the runtime implicit) or indeed RuntimeTypeKind(TypeBound), RuntimeType(Type), ...
    • Or use prefix Some rather than suffix Type. So SomeString, String(&'static str), SomeRuntimeType(TypeBound), RuntimeType(Type), SomeStaticType. I admit its kinda hideous but maybe we just need to think a bit out of the box....
    • Or abandon consistency altogether....TypeArg::BoundedNat was always misnamed as it has no knowledge of its bound; that should just be Term::Nat. Then the kind of those is Term::BoundedNat(Option<UpperBound>)....
  • Single-field structs. I suspect if we don't do it now, we never will, and I really think we should (since you've done the hard work with TermSer!). So how about doing that here?

  • Any nice "demo" test of an extension op/type that this lets us define that we couldn't before? :)

}
}

fn contains(&self, other: &Term) -> bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC the use of this was "can a type variable of kind other be used as argument where self is expected?" - TypeParam vs TypeParam, not TypeParam vs TypeArg, so subset, rather than set membership. (Thus, arguably misnamed - and since TypeParam is now becoming much bigger, this is the time to fix.)

  • Are you now using this in a more general sense? I think you are not
    *Can we really have things like an op parametrized by a variable of type 3.141f? We should have ruled that out before we get here IIUC.

=> I think you should probably narrow down what this does and how it is used - rename it to "is_superset", "is_element", "var_fits_within_type" or something.

(The proptest that "any Term contains itself" may well not apply now - only for StaticType | RuntimeType(_) | StringType | XXXType !)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, so this is the subtyping relationship. Ideally we should get rid of the subtyping, but I've adjusted it to reflect it's intended purpose.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've changed list and tuple, right that makes more sense.

Ok, so let's at least comment what it's for, but preferably rename contains.

I also think we could panic in many of the cases (e.g. type being a Term::Type) - one could have a method Term::is_static_type(&self) -> bool that is true for RuntimeType, ListType, StaticType, etc., but false for Type, String, Bytes, etc.; and that is required to be true when a Term is used as the type of a static parameter. We could then check this in PolyFuncTypeBase::validate (on each thing in self.params). Then this contains (rename to check_var_fits_in_param or something perhaps) can if !type.is_static_type() {panic!(...)};

Copy link
Contributor Author

@zrho zrho Jun 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll rename it to is_supertype later.

I wouldn't go for a is_static_type method. There are a bunch of other things to be checked, especially with custom constructors. This needs a proper validation system, especially if constraints come into play as well. But that's out of scope of this PR.

Also definitely no panic! In my view a panic is always a bug and shouldn't be reachable by passing invalid input to the compiler. There are currently a bunch of exposed panics throughout the codebase; I consider all of them bugs.

(Term::BytesType, Term::BytesType) => true,
(Term::FloatType, Term::FloatType) => true,
(Term::Type { ty: t1 }, Term::Type { ty: t2 }) => t1 == t2,
(Term::BoundedNat { value: n1 }, Term::BoundedNat { value: n2 }) => n1 == n2,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

n1 >= n2 ? Or is this actually just equality (if we have no covariance/contravariance then it would be that, except that you then have list membership below!)

pub struct TypeArgVariable {
idx: usize,
cached_decl: TypeParam,
cached_decl: Box<TypeParam>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Box? Really?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To break the cycle. Before it wasn't necessary since TypeArgVariable was contained in a TypeArg and referred to a TypeParam. Now it is contained in a Term and refers to a Term.

If you mean to ask why not Arc, there's a later PR that Arcs a lot of things.

/// A [`Term`] that is the argument to an operation or constructor.
pub type TypeArg = Term;

/// A [`Term`] that is the static type of an operation or constructor parameter.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do still wonder whether we could use "kind" rather than type here - not because type is wrong, it's completely right (in the static language), but because the runtime types (i.e. struct Type) is called what it is, whereas the consistent thing would be to call it "Runtime" (!)

///
/// [`PolyFuncType`]: super::PolyFuncType
/// [`PolyFuncTypeRV`]: super::PolyFuncTypeRV
/// A [`Term`] that is the argument to an operation or constructor.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// A [`Term`] that is the argument to an operation or constructor.
/// A [`Term`] that is the static argument to an operation or constructor.

or (static), if you prefer

// Mismatched TypeBound (Copyable vs Any)
let decl = TypeParam::List {
param: Box::new(TP_ANY),
let decl = TypeParam::ListType {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use new_list_type

assert_eq!(
INT_TYPES[i as usize],
int_type(TypeArg::BoundedNat { n: u64::from(i) })
int_type(TypeArg::BoundedNat {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't already have fn new_nat(value: impl Into<u64>) -> Self (in Term) then we certainly should ;)

.map_err(|err| error_context!(err, "item type of list type"))?,
);
return Ok(TypeParam::List { param });
return Ok(TypeParam::ListType { item_type });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use new_list_type to avoid box...


if let Some([item_type]) = self.match_symbol(term_id, model::CORE_LIST_TYPE)? {
// At present `hugr-model` has no way to express that the item
// type of a list must be copyable. Therefore we import it as `Any`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We must have an issue for this, can we link to it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's #2304. I'll add a link.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant the Copyable constraint! But I think the issue would just be, for a more general constraint language, which may not exist yet - if not then never mind.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. Yeah, the issue would be for constraints. Definitely on the roadmap, along with validation, but I'd like to get a lot of #2291 done before attacking that.

_,
) if param.contains(cached_decl) => Ok(()),
(TypeArg::Type { ty }, TypeParam::Type { b: bound })
) if type_.contains(cached_decl) => Ok(()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re. contains this is the only significant external call I'm aware of (there are some asserts), but we should rename to clarify purpose.

@zrho
Copy link
Contributor Author

zrho commented Jun 13, 2025

  • Regarding RuntimeType etc: Ideally in a future PR we merge Type and Term as well. I didn't want to do it here yet to keep the size of the change relatively small. At that point Term::Type goes away, which helps with clearing things up.
  • I am also in favour of single field tuple variants (e.g. Term::String(value) instead of Term::String { value }). I thought the usage of the named fields indicated an implicit preference for that style, but it's probably only for the JSON. So I'll change it.

@zrho zrho force-pushed the zrho/core-merge-arg-param branch from 9496e82 to e69748d Compare June 13, 2025 16:54
@lmondada lmondada removed their request for review June 16, 2025 09:08
@zrho zrho force-pushed the zrho/core-merge-arg-param branch from 199bbe7 to 8c26340 Compare June 16, 2025 12:41
Copy link
Contributor

@acl-cqc acl-cqc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok thanks Lukas! Nearly there I think. The switch to tuple types is good - I think there is a strong preference for structs when there is >1 field, but yours are all 1 field only, and you've been selective there in only doing cases where the field is basically the variant name (as opposed to e.g. "bound" in RuntimeType) - good call.

My suggestion of "kind" was not really that I thought it was better (as you say, type/kind are sufficiently combined for that not to be the case), but just to avoid confusion with Term::Type. I think given your plan to remove Term::Type then we should not change anything else to be consistent with Term::Type but we could still consider renaming. I won't insist but how about Term::Runtime (for deconstructing, as typically you'd construct by myType.into() - or Term::from(myType)) ?

contains is taking shape :) but I think the main/remaining thing is to validate that we don't have inappropriate Terms as variable types, see comment below.

Term::Float(value) => self.make_term(model::Literal::Float(*value).into()),
Term::Bytes(value) => self.make_term(model::Literal::Bytes(value.clone()).into()),
Term::List(elems) => {
// For now we assume that the sequence is meant to be a list.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than what? (Clearly the answer is not "a Tuple")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a leftover from before Sequence was split into List and Tuple. Will remove the comment.


if let Some([item_type]) = self.match_symbol(term_id, model::CORE_LIST_TYPE)? {
// At present `hugr-model` has no way to express that the item
// type of a list must be copyable. Therefore we import it as `Any`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant the Copyable constraint! But I think the issue would just be, for a more general constraint language, which may not exist yet - if not then never mind.

Self::BoundedNatType(UpperBound(Some(upper_bound)))
}

/// Create s a new [`Term::List`] given a sequence of its items.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super-nit: typo s

(Term::Tuple { elems: e1 }, Term::Tuple { elems: e2 }) if e1 == e2 => true,
(Term::Tuple { elems }, other) => elems.iter().any(|elem| elem.contains(other)),
(Term::Type(t1), Term::Type(t2)) => t1 == t2,
(Term::BoundedNat(n1), Term::BoundedNat(n2)) => n1 >= n2,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I think this is wrong (I know I made you change it!) - here we are saying, can a parameter of type BoundedNat(7) (i.e., the number 7, not BoundedNatType(7) i.e. any number <7) be instantiated by a variable of type BoundedNat(6).

So this is a silly question to ask; we can't prevent that at Rust-compile-time anymore, so

  • If we really have to give an answer, it should be no (require n1 == n2)....
  • but it really would be better not to answer at all, rather to panic or return an error

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes, for BoundedNat it should be ==, for BoundedNatType it should be an inequality.

Ultimately I'd like to get rid of the subtyping altogether but for now it makes sense to have the relation be a partial order on Terms - and in particular have it be reflexive.

}
}

fn contains(&self, other: &Term) -> bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've changed list and tuple, right that makes more sense.

Ok, so let's at least comment what it's for, but preferably rename contains.

I also think we could panic in many of the cases (e.g. type being a Term::Type) - one could have a method Term::is_static_type(&self) -> bool that is true for RuntimeType, ListType, StaticType, etc., but false for Type, String, Bytes, etc.; and that is required to be true when a Term is used as the type of a static parameter. We could then check this in PolyFuncTypeBase::validate (on each thing in self.params). Then this contains (rename to check_var_fits_in_param or something perhaps) can if !type.is_static_type() {panic!(...)};

@zrho zrho force-pushed the zrho/core-merge-arg-param branch from b322c2e to c401c30 Compare June 17, 2025 16:42
Copy link
Contributor

@acl-cqc acl-cqc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for changes @zrho, there's a lot of good work here and I am sorry to be the one dragging. However I would really love to have some checks against footguns where people declare parameters of type 5, not realizing how stupid that is, but I understand the argument that this is difficult to do well or (especially) in a way that generalizes to future Terms. I am going to hope that we can work out something in #2345...

checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
dependencies = [
"getrandom 0.3.2",
"getrandom",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to check this out from main unless there is some relation that I've not spotted to the rest of this PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main branch has a Cargo.lock file with a missing version for a dependency. The LSP corrects this automatically, but that leaves the git workspace dirty, so you can't switch the branch. Resetting the file doesn't help as long as the editor is running since it will immediately fix the lock file again.

es1.len() == es2.len() && es1.iter().zip(es2).all(|(e1, e2)| e1.contains(e2))
(Term::BytesType, Term::BytesType) => true,
(Term::FloatType, Term::FloatType) => true,
(Term::Runtime(t1), Term::Runtime(t2)) => t1 == t2,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok add a comment before here:

The following are not types and do not admit values. However, we include these cases for consistency: it is useful
for the supertype relation to be reflexive. This can perhaps be justified in the sense that "supertype" can be
understood as "admits a superset of values" and even the empty set is the superset of itself, although here
we distinguish between these non-types and, strictly speaking, since these are not types, it does not even
make sense to talk about the set of values they admit or whether it is empty. (Contrast a type like the Rust `enum Foo {}`
that admits the empty set of values.)

Feel free to paraphrase, in particular that word "admit", but I think the contrast with the Rust example is a good one to make, and I would make the point is that this is done for reflexivity (nice behaviour) rather than because it makes sense.

(Term::Float(_), Term::FloatType) => Ok(()),

// Static types
(Term::StaticType, Term::StaticType) => Ok(()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add (Term::RuntimeType(_), Term::StaticType) => Ok(()) here

@zrho zrho added this pull request to the merge queue Jun 17, 2025
Merged via the queue into main with commit ebfc98e Jun 17, 2025
27 checks passed
@zrho zrho deleted the zrho/core-merge-arg-param branch June 17, 2025 17:42
@hugrbot hugrbot mentioned this pull request Jun 17, 2025
github-merge-queue bot pushed a commit that referenced this pull request Jul 8, 2025
fixes #2401
* Update generate_schema.py to add an entry to the generated schema
describing what members of `#/$defs` the actual value (i.e. root) should
conform to.
* Add a test that schema validation fails when expected (by
adding/removing fields).
* Some changes to `check_schemas` and related (crate) methods to expose
errors etc.

* Fix various failures in proptests stemming from
* #2309 (the `Arbitrary` instance can generate "TypeArg"s where
"TypeParam"s are expected or vice versa, and these do not confirm to the
JSON schema).
* #2360 - I'm not clear what *well-typed* ArrayOrTermSer::Term can fit
the JSON schema, but our `Arbitrary`s generate plenty that are not
well-typed.
...I've "fixed" the proptests by filtering out non-schema-compliant
instances using `prop_filter`, this is not great, the new situation is
detailed in #2415 for further cleaning up.
lmondada pushed a commit that referenced this pull request Jul 9, 2025
fixes #2401
* Update generate_schema.py to add an entry to the generated schema
describing what members of `#/$defs` the actual value (i.e. root) should
conform to.
* Add a test that schema validation fails when expected (by
adding/removing fields).
* Some changes to `check_schemas` and related (crate) methods to expose
errors etc.

* Fix various failures in proptests stemming from
* #2309 (the `Arbitrary` instance can generate "TypeArg"s where
"TypeParam"s are expected or vice versa, and these do not confirm to the
JSON schema).
* #2360 - I'm not clear what *well-typed* ArrayOrTermSer::Term can fit
the JSON schema, but our `Arbitrary`s generate plenty that are not
well-typed.
...I've "fixed" the proptests by filtering out non-schema-compliant
instances using `prop_filter`, this is not great, the new situation is
detailed in #2415 for further cleaning up.
github-merge-queue bot pushed a commit that referenced this pull request Jul 10, 2025
This release includes a long list of changes:

- The HUGR model serialization format is now stable, and should be
preferred over the old JSON format.
- Type parameters and type arguments are now unified into a single
`Term` type.
- Function definitions can no longer be nested inside dataflow regions.
Now they must be defined at the top level module.
- Function definitions and declarations now have a `Visibility` field,
which define whether they are visible in the public API of the module.
- And many more fixes and improvements.

---

## 🤖 New release

* `hugr-model`: 0.20.2 -> 0.21.0 (⚠ API breaking changes)
* `hugr-core`: 0.20.2 -> 0.21.0 (⚠ API breaking changes)
* `hugr-llvm`: 0.20.2 -> 0.21.0 (⚠ API breaking changes)
* `hugr-passes`: 0.20.2 -> 0.21.0 (✓ API compatible changes)
* `hugr`: 0.20.2 -> 0.21.0 (✓ API compatible changes)
* `hugr-cli`: 0.20.2 -> 0.21.0 (⚠ API breaking changes)

### ⚠ `hugr-model` breaking changes

```text
--- failure constructible_struct_adds_field: externally-constructible struct adds field ---

Description:
A pub struct constructible with a struct literal has a new pub field. Existing struct literals must be updated to include the new field.
        ref: https://doc.rust-lang.org/reference/expressions/struct-expr.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/constructible_struct_adds_field.ron

Failed in:
  field Symbol.visibility in /tmp/.tmpEqPTGR/hugr/hugr-model/src/v0/ast/mod.rs:198
  field Symbol.visibility in /tmp/.tmpEqPTGR/hugr/hugr-model/src/v0/table/mod.rs:307

--- failure pub_module_level_const_missing: pub module-level const is missing ---

Description:
A public const is missing or renamed
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/pub_module_level_const_missing.ron

Failed in:
  CORE_CTRL_TYPE in file /tmp/.tmp1p6e1v/hugr-model/src/v0/mod.rs:175

--- failure struct_with_no_pub_fields_changed_type: public API struct with no public fields is no longer a struct ---

Description:
A struct without pub fields became an enum or union, breaking pattern matching.
        ref: https://internals.rust-lang.org/t/rest-patterns-foo-should-match-non-struct-types/21607
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/struct_with_no_pub_fields_changed_type.ron

Failed in:
  struct hugr_model::v0::scope::UnknownVarError became enum in file /tmp/.tmpEqPTGR/hugr/hugr-model/src/v0/scope/vars.rs:147
```

### ⚠ `hugr-core` breaking changes

```text
--- failure auto_trait_impl_removed: auto trait no longer implemented ---

Description:
A public type has stopped implementing one or more auto traits. This can break downstream code that depends on the traits being implemented.
        ref: https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/auto_trait_impl_removed.ron

Failed in:
  type Term is no longer UnwindSafe, in /tmp/.tmpEqPTGR/hugr/hugr-core/src/types/type_param.rs:70
  type Term is no longer RefUnwindSafe, in /tmp/.tmpEqPTGR/hugr/hugr-core/src/types/type_param.rs:70

--- failure enum_missing: pub enum removed or renamed ---

Description:
A publicly-visible enum cannot be imported by its prior path. A `pub use` may have been removed, or the enum itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/enum_missing.ron

Failed in:
  enum hugr_core::types::type_param::TypeArgError, previously in file /tmp/.tmp1p6e1v/hugr-core/src/types/type_param.rs:450
  enum hugr_core::hugr::persistent::walker::PinNodeError, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/persistent/walker.rs:333
  enum hugr_core::hugr::persistent::serial::SerialCommitData, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/persistent/state_space/serial.rs:11
  enum hugr_core::import::ImportError, previously in file /tmp/.tmp1p6e1v/hugr-core/src/import.rs:39
  enum hugr_core::import::OrderHintError, previously in file /tmp/.tmp1p6e1v/hugr-core/src/import.rs:82
  enum hugr_core::hugr::persistent::InvalidCommit, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/persistent/state_space.rs:474

--- failure enum_no_repr_variant_discriminant_changed: enum variant had its discriminant change value ---

Description:
The enum's variant had its discriminant value change. This breaks downstream code that used its value via a numeric cast like `as isize`.
        ref: https://doc.rust-lang.org/reference/items/enumerations.html#assigning-discriminant-values
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/enum_no_repr_variant_discriminant_changed.ron

Failed in:
  variant InterGraphEdgeError::NonCFGAncestor 2 -> 1 in /tmp/.tmpEqPTGR/hugr/hugr-core/src/hugr/validate.rs:795
  variant InterGraphEdgeError::MissingOrderEdge 3 -> 2 in /tmp/.tmpEqPTGR/hugr/hugr-core/src/hugr/validate.rs:806
  variant InterGraphEdgeError::NoRelation 4 -> 3 in /tmp/.tmpEqPTGR/hugr/hugr-core/src/hugr/validate.rs:817
  variant InterGraphEdgeError::NonDominatedAncestor 5 -> 4 in /tmp/.tmpEqPTGR/hugr/hugr-core/src/hugr/validate.rs:827

--- failure enum_variant_added: enum variant added on exhaustive enum ---

Description:
A publicly-visible enum without #[non_exhaustive] has a new variant.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#enum-variant-new
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/enum_variant_added.ron

Failed in:
  variant TypeBound:Linear in /tmp/.tmpEqPTGR/hugr/hugr-core/src/types.rs:138

--- failure enum_variant_missing: pub enum variant removed or renamed ---

Description:
A publicly-visible enum has at least one variant that is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/enum_variant_missing.ron

Failed in:
  variant PackageEncodingError::RuntimeExtensionResolution, previously in file /tmp/.tmp1p6e1v/hugr-core/src/envelope/package_json.rs:77
  variant Term::Type, previously in file /tmp/.tmp1p6e1v/hugr-core/src/types/type_param.rs:67
  variant Term::Type, previously in file /tmp/.tmp1p6e1v/hugr-core/src/types/type_param.rs:158
  variant Term::Sequence, previously in file /tmp/.tmp1p6e1v/hugr-core/src/types/type_param.rs:180
  variant Term::Type, previously in file /tmp/.tmp1p6e1v/hugr-core/src/types/type_param.rs:158
  variant Term::Sequence, previously in file /tmp/.tmp1p6e1v/hugr-core/src/types/type_param.rs:180
  variant TypeBound::Any, previously in file /tmp/.tmp1p6e1v/hugr-core/src/types.rs:136
  variant InterGraphEdgeError::ValueEdgeIntoFunc, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/validate.rs:766
  variant ValidationError::ExtensionError, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/validate.rs:714
  variant ValidationError::ExtensionError, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/validate.rs:714

--- failure function_missing: pub fn removed or renamed ---

Description:
A publicly-visible function cannot be imported by its prior path. A `pub use` may have been removed, or the function itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/function_missing.ron

Failed in:
  function hugr_core::types::type_param::check_type_arg, previously in file /tmp/.tmp1p6e1v/hugr-core/src/types/type_param.rs:384
  function hugr_core::types::type_param::check_type_args, previously in file /tmp/.tmp1p6e1v/hugr-core/src/types/type_param.rs:437

--- failure inherent_method_missing: pub method removed or renamed ---

Description:
A publicly-visible method or associated fn is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/inherent_method_missing.ron

Failed in:
  Term::max_nat, previously in file /tmp/.tmp1p6e1v/hugr-core/src/types/type_param.rs:100
  Term::bounded_nat, previously in file /tmp/.tmp1p6e1v/hugr-core/src/types/type_param.rs:108
  Term::as_type, previously in file /tmp/.tmp1p6e1v/hugr-core/src/types/type_param.rs:275
  Term::as_type, previously in file /tmp/.tmp1p6e1v/hugr-core/src/types/type_param.rs:275

--- failure method_parameter_count_changed: pub method parameter count changed ---

Description:
A publicly-visible method now takes a different number of parameters.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#fn-change-arity
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/method_parameter_count_changed.ron

Failed in:
  hugr_core::hugr::patch::simple_replace::SimpleReplacement::linked_replacement_output now takes 4 parameters instead of 3, in /tmp/.tmpEqPTGR/hugr/hugr-core/src/hugr/patch/simple_replace.rs:134
  hugr_core::hugr::patch::simple_replace::SimpleReplacement::linked_replacement_inputs now takes 4 parameters instead of 3, in /tmp/.tmpEqPTGR/hugr/hugr-core/src/hugr/patch/simple_replace.rs:221
  hugr_core::hugr::patch::SimpleReplacement::linked_replacement_output now takes 4 parameters instead of 3, in /tmp/.tmpEqPTGR/hugr/hugr-core/src/hugr/patch/simple_replace.rs:134
  hugr_core::hugr::patch::SimpleReplacement::linked_replacement_inputs now takes 4 parameters instead of 3, in /tmp/.tmpEqPTGR/hugr/hugr-core/src/hugr/patch/simple_replace.rs:221
  hugr_core::hugr::SimpleReplacement::linked_replacement_output now takes 4 parameters instead of 3, in /tmp/.tmpEqPTGR/hugr/hugr-core/src/hugr/patch/simple_replace.rs:134
  hugr_core::hugr::SimpleReplacement::linked_replacement_inputs now takes 4 parameters instead of 3, in /tmp/.tmpEqPTGR/hugr/hugr-core/src/hugr/patch/simple_replace.rs:221
  hugr_core::SimpleReplacement::linked_replacement_output now takes 4 parameters instead of 3, in /tmp/.tmpEqPTGR/hugr/hugr-core/src/hugr/patch/simple_replace.rs:134
  hugr_core::SimpleReplacement::linked_replacement_inputs now takes 4 parameters instead of 3, in /tmp/.tmpEqPTGR/hugr/hugr-core/src/hugr/patch/simple_replace.rs:221

--- failure module_missing: pub module removed or renamed ---

Description:
A publicly-visible module cannot be imported by its prior path. A `pub use` may have been removed, or the module may have been renamed, removed, or made non-public.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/module_missing.ron

Failed in:
  mod hugr_core::hugr::persistent, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/persistent.rs:1
  mod hugr_core::hugr::persistent::walker, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/persistent/walker.rs:1
  mod hugr_core::hugr::persistent::serial, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/persistent.rs:769

--- failure struct_missing: pub struct removed or renamed ---

Description:
A publicly-visible struct cannot be imported by its prior path. A `pub use` may have been removed, or the struct itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/struct_missing.ron

Failed in:
  struct hugr_core::hugr::persistent::PatchNode, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/persistent/state_space.rs:28
  struct hugr_core::hugr::persistent::walker::PinnedWire, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/persistent/walker/pinned.rs:30
  struct hugr_core::hugr::persistent::PinnedWire, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/persistent/walker/pinned.rs:30
  struct hugr_core::hugr::persistent::PersistentHugr, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/persistent.rs:274
  struct hugr_core::hugr::persistent::serial::SerialCommitStateSpace, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/persistent/state_space/serial.rs:54
  struct hugr_core::types::type_param::TypeArgVariable, previously in file /tmp/.tmp1p6e1v/hugr-core/src/types/type_param.rs:236
  struct hugr_core::hugr::persistent::walker::Walker, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/persistent/walker.rs:87
  struct hugr_core::hugr::persistent::Walker, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/persistent/walker.rs:87
  struct hugr_core::hugr::persistent::PointerEqResolver, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/persistent/resolver.rs:11
  struct hugr_core::hugr::persistent::CommitStateSpace, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/persistent/state_space.rs:64
  struct hugr_core::hugr::persistent::Commit, previously in file /tmp/.tmp1p6e1v/hugr-core/src/hugr/persistent.rs:108

--- failure trait_method_missing: pub trait method removed or renamed ---

Description:
A trait method is no longer callable, and may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#major-any-change-to-trait-item-signatures
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/trait_method_missing.ron

Failed in:
  method define_function of trait Container, previously in file /tmp/.tmp1p6e1v/hugr-core/src/builder/build_traits.rs:92
```

### ⚠ `hugr-llvm` breaking changes

```text
--- failure trait_method_requires_different_generic_type_params: trait method now requires a different number of generic type parameters ---

Description:
A trait method now requires a different number of generic type parameters than it used to. Calls or implementations of this trait method using the previous number of generic types will be broken.
        ref: https://doc.rust-lang.org/reference/items/generics.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/trait_method_requires_different_generic_type_params.ron

Failed in:
  FatExt::fat_root (1 -> 0 generic types) in /tmp/.tmpEqPTGR/hugr/hugr-llvm/src/utils/fat.rs:376
```

### ⚠ `hugr-cli` breaking changes

```text
--- failure inherent_method_missing: pub method removed or renamed ---

Description:
A publicly-visible method or associated fn is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/inherent_method_missing.ron

Failed in:
  ValArgs::verbosity, previously in file /tmp/.tmp1p6e1v/hugr-cli/src/validate.rs:53
  MermaidArgs::verbosity, previously in file /tmp/.tmp1p6e1v/hugr-cli/src/mermaid.rs:78

--- failure struct_pub_field_missing: pub struct's pub field removed or renamed ---

Description:
A publicly-visible struct has at least one public field that is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/struct_pub_field_missing.ron

Failed in:
  field other_args of struct ValArgs, previously in file /tmp/.tmp1p6e1v/hugr-cli/src/validate.rs:24
  field other_args of struct MermaidArgs, previously in file /tmp/.tmp1p6e1v/hugr-cli/src/mermaid.rs:36

--- warning enum_missing: pub enum removed or renamed ---

Description:
A publicly-visible enum cannot be imported by its prior path. A `pub use` may have been removed, or the enum itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/enum_missing.ron

Failed in:
  enum hugr_cli::CliArgs, previously in file /tmp/.tmp1p6e1v/hugr-cli/src/lib.rs:78

--- warning struct_missing: pub struct removed or renamed ---

Description:
A publicly-visible struct cannot be imported by its prior path. A `pub use` may have been removed, or the struct itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/struct_missing.ron

Failed in:
  struct hugr_cli::OtherArgs, previously in file /tmp/.tmp1p6e1v/hugr-cli/src/lib.rs:122
```

<details><summary><i><b>Changelog</b></i></summary><p>

## `hugr-model`

<blockquote>

##
[0.21.0](hugr-model-v0.20.2...hugr-model-v0.21.0)
- 2025-07-09

### Bug Fixes

- Model import should perform extension resolution
([#2326](#2326))
- [**breaking**] Fixed bugs in model CFG handling and improved CFG
signatures ([#2334](#2334))
- [**breaking**] Fix panic in model resolver when variable is used
outside of symbol. ([#2362](#2362))
- Order hints on input and output nodes.
([#2422](#2422))

### New Features

- [**breaking**] Added float and bytes literal to core and python
bindings. ([#2289](#2289))
- better errors using metadata from generator
([#2368](#2368))
- [**breaking**] Add Visibility to FuncDefn/FuncDecl.
([#2143](#2143))
- [**breaking**] hugr-model use explicit Option<Visibility>, with
::Unspecified in capnp ([#2424](#2424))
</blockquote>

## `hugr-core`

<blockquote>

##
[0.21.0](hugr-core-v0.20.2...hugr-core-v0.21.0)
- 2025-07-09

### Bug Fixes

- Fixed two bugs in import/export of function operations
([#2324](#2324))
- Model import should perform extension resolution
([#2326](#2326))
- [**breaking**] Fixed bugs in model CFG handling and improved CFG
signatures ([#2334](#2334))
- Use List instead of Tuple in conversions for TypeArg/TypeRow
([#2378](#2378))
- Do extension resolution on loaded extensions from the model format
([#2389](#2389))
- Make JSON Schema checks actually work again
([#2412](#2412))
- Order hints on input and output nodes.
([#2422](#2422))

### New Features

- [**breaking**] No nested FuncDefns (or AliasDefns)
([#2256](#2256))
- Add serial data types for SimpleReplacement and PersistentHugr
([#2300](#2300))
- [**breaking**] Split `TypeArg::Sequence` into tuples and lists.
([#2140](#2140))
- [**breaking**] Added float and bytes literal to core and python
bindings. ([#2289](#2289))
- [**breaking**] More helpful error messages in model import
([#2272](#2272))
- Add MermaidFormatter to replace RenderConfig
([#2275](#2275))
- [**breaking**] Better error reporting in `hugr-cli`.
([#2318](#2318))
- *(core)* builder pattern for EnvelopeConfig
([#2330](#2330))
- *(core, llvm)* add array unpack operations
([#2339](#2339))
- [**breaking**] Merge `TypeParam` and `TypeArg` into one `Term` type in
Rust ([#2309](#2309))
- *(persistent)* Add serialisation for CommitStateSpace
([#2344](#2344))
- Deprecate invalidation_set, add invalidated_nodes and
SimpleReplacement::invalidation_set
([#2358](#2358))
- Rewrite for peeling a TailLoop
([#2290](#2290))
- Create Module/FunctionBuilders from existing Hugrs
([#2359](#2359))
- add TryFrom impls for TypeArg/TypeRow
([#2366](#2366))
- better errors using metadata from generator
([#2368](#2368))
- use `core.` prefixes for generator metadata keys
([#2371](#2371))
- Add `MakeError` op ([#2377](#2377))
- Open lists and tuples in `Term`
([#2360](#2360))
- Call `FunctionBuilder::add_{in,out}put` for any AsMut<Hugr>
([#2376](#2376))
- Add Root checked methods to DataflowParentID
([#2382](#2382))
- Add PersistentWire type
([#2361](#2361))
- Add `BorrowArray` extension
([#2395](#2395))
- [**breaking**] Rename 'Any' type bound to 'Linear'
([#2421](#2421))
- [**breaking**] Add Visibility to FuncDefn/FuncDecl.
([#2143](#2143))
- *(per)* [**breaking**] Support empty wires in commits
([#2349](#2349))
- [**breaking**] hugr-model use explicit Option<Visibility>, with
::Unspecified in capnp ([#2424](#2424))

### Refactor

- [**breaking**] move PersistentHugr into separate crate
([#2277](#2277))
- *(types.rs)* rm incorrect comment and unnecessary allow-unused
([#2340](#2340))
- [**breaking**] remove deprecated runtime extension errors
([#2369](#2369))
- [**breaking**] Reduce error type sizes
([#2420](#2420))

### Testing

- Check hugr json serializations against the schema (again)
([#2216](#2216))
</blockquote>

## `hugr-llvm`

<blockquote>

##
[0.21.0](hugr-llvm-v0.20.2...hugr-llvm-v0.21.0)
- 2025-07-09

### New Features

- [**breaking**] No nested FuncDefns (or AliasDefns)
([#2256](#2256))
- [**breaking**] Split `TypeArg::Sequence` into tuples and lists.
([#2140](#2140))
- [**breaking**] More helpful error messages in model import
([#2272](#2272))
- *(core, llvm)* add array unpack operations
([#2339](#2339))
- [**breaking**] Merge `TypeParam` and `TypeArg` into one `Term` type in
Rust ([#2309](#2309))
- Add `MakeError` op ([#2377](#2377))

### Refactor

- *(llvm)* replace HashMap with BTreeMap
([#2313](#2313))
</blockquote>

## `hugr-passes`

<blockquote>

##
[0.21.0](hugr-passes-v0.20.2...hugr-passes-v0.21.0)
- 2025-07-09

### Bug Fixes

- update CallGraph and remove_dead_funcs for module-only FuncDefns
([#2336](#2336))
- DeadFuncElimPass+CallGraph w/ non-module-child entrypoint
([#2390](#2390))

### New Features

- [**breaking**] No nested FuncDefns (or AliasDefns)
([#2256](#2256))
- [**breaking**] Split `TypeArg::Sequence` into tuples and lists.
([#2140](#2140))
- [**breaking**] Merge `TypeParam` and `TypeArg` into one `Term` type in
Rust ([#2309](#2309))
- [**breaking**] Rename 'Any' type bound to 'Linear'
([#2421](#2421))

### Refactor

- [**breaking**] Reduce error type sizes
([#2420](#2420))
</blockquote>

## `hugr`

<blockquote>

##
[0.21.0](hugr-v0.20.2...hugr-v0.21.0)
- 2025-07-09

### Bug Fixes

- update CallGraph and remove_dead_funcs for module-only FuncDefns
([#2336](#2336))
- DeadFuncElimPass+CallGraph w/ non-module-child entrypoint
([#2390](#2390))
- Fixed two bugs in import/export of function operations
([#2324](#2324))
- Model import should perform extension resolution
([#2326](#2326))
- [**breaking**] Fixed bugs in model CFG handling and improved CFG
signatures ([#2334](#2334))
- Use List instead of Tuple in conversions for TypeArg/TypeRow
([#2378](#2378))
- Do extension resolution on loaded extensions from the model format
([#2389](#2389))
- Make JSON Schema checks actually work again
([#2412](#2412))
- Order hints on input and output nodes.
([#2422](#2422))

### Documentation

- Hide hugr-persistent docs
([#2357](#2357))

### New Features

- Add serial data types for SimpleReplacement and PersistentHugr
([#2300](#2300))
- [**breaking**] Split `TypeArg::Sequence` into tuples and lists.
([#2140](#2140))
- [**breaking**] Added float and bytes literal to core and python
bindings. ([#2289](#2289))
- [**breaking**] More helpful error messages in model import
([#2272](#2272))
- Add MermaidFormatter to replace RenderConfig
([#2275](#2275))
- [**breaking**] Better error reporting in `hugr-cli`.
([#2318](#2318))
- *(core, llvm)* add array unpack operations
([#2339](#2339))
- [**breaking**] Merge `TypeParam` and `TypeArg` into one `Term` type in
Rust ([#2309](#2309))
- *(persistent)* Add serialisation for CommitStateSpace
([#2344](#2344))
- Deprecate invalidation_set, add invalidated_nodes and
SimpleReplacement::invalidation_set
([#2358](#2358))
- Rewrite for peeling a TailLoop
([#2290](#2290))
- Create Module/FunctionBuilders from existing Hugrs
([#2359](#2359))
- add TryFrom impls for TypeArg/TypeRow
([#2366](#2366))
- better errors using metadata from generator
([#2368](#2368))
- use `core.` prefixes for generator metadata keys
([#2371](#2371))
- Add `MakeError` op ([#2377](#2377))
- Open lists and tuples in `Term`
([#2360](#2360))
- Call `FunctionBuilder::add_{in,out}put` for any AsMut<Hugr>
([#2376](#2376))
- Add Root checked methods to DataflowParentID
([#2382](#2382))
- Add PersistentWire type
([#2361](#2361))
- Add `BorrowArray` extension
([#2395](#2395))
- [**breaking**] Add Visibility to FuncDefn/FuncDecl.
([#2143](#2143))
- *(per)* [**breaking**] Support empty wires in commits
([#2349](#2349))
- [**breaking**] hugr-model use explicit Option<Visibility>, with
::Unspecified in capnp ([#2424](#2424))
- [**breaking**] No nested FuncDefns (or AliasDefns)
([#2256](#2256))
- *(core)* builder pattern for EnvelopeConfig
([#2330](#2330))
- [**breaking**] Rename 'Any' type bound to 'Linear'
([#2421](#2421))

### Refactor

- *(types.rs)* rm incorrect comment and unnecessary allow-unused
([#2340](#2340))
- [**breaking**] remove deprecated runtime extension errors
([#2369](#2369))
- [**breaking**] Reduce error type sizes
([#2420](#2420))
- [**breaking**] move PersistentHugr into separate crate
([#2277](#2277))

### Testing

- Check hugr json serializations against the schema (again)
([#2216](#2216))
</blockquote>

## `hugr-cli`

<blockquote>

##
[0.21.0](hugr-cli-v0.20.2...hugr-cli-v0.21.0)
- 2025-07-09

### New Features

- [**breaking**] Better error reporting in `hugr-cli`.
([#2318](#2318))
- *(cli)* convert sub-command for converting envelope formats
([#2331](#2331))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).

---------

Co-authored-by: Agustín Borgna <[email protected]>
@hugrbot hugrbot mentioned this pull request Jul 16, 2025
This was referenced Jul 24, 2025
github-merge-queue bot pushed a commit that referenced this pull request Jul 24, 2025
This release fixes multiple inconsistencies between the serialization
formats
and improves the error messages when loading unsupported envelopes.

We now also support nodes with up to `2^32` connections to the same port
(up from `2^16`).

---

## 🤖 New release

* `hugr-model`: 0.21.0 -> 0.22.0 (✓ API compatible changes)
* `hugr-core`: 0.21.0 -> 0.22.0 (✓ API compatible changes)
* `hugr-llvm`: 0.21.0 -> 0.22.0 (✓ API compatible changes)
* `hugr-passes`: 0.21.0 -> 0.22.0 (✓ API compatible changes)
* `hugr-persistent`: 0.1.0 -> 0.2.0 (✓ API compatible changes)
* `hugr`: 0.21.0 -> 0.22.0 (✓ API compatible changes)
* `hugr-cli`: 0.21.0 -> 0.22.0 (✓ API compatible changes)

<details><summary><i><b>Changelog</b></i></summary><p>

## `hugr-model`

<blockquote>

##
[0.22.0](hugr-model-v0.21.0...hugr-model-v0.22.0)
- 2025-07-24

### New Features

- Names of private functions become `core.title` metadata.
([#2448](#2448))
- include generator metatada in model import and cli validate errors
([#2452](#2452))
- Version number in hugr binary format.
([#2468](#2468))
- Use semver crate for -model version, and include in docs
([#2471](#2471))
</blockquote>

## `hugr-core`

<blockquote>

##
[0.22.0](hugr-core-v0.21.0...hugr-core-v0.22.0)
- 2025-07-24

### Bug Fixes

- Ensure SumTypes have the same json encoding in -rs and -py
([#2465](#2465))

### New Features

- Export entrypoint metadata in Python and fix bug in import
([#2434](#2434))
- Names of private functions become `core.title` metadata.
([#2448](#2448))
- [**breaking**] Use binary envelopes for operation lower_func encoding
([#2447](#2447))
- [**breaking**] Update portgraph dependency to 0.15
([#2455](#2455))
- Detect and fail on unrecognised envelope flags
([#2453](#2453))
- include generator metatada in model import and cli validate errors
([#2452](#2452))
- [**breaking**] Add `insert_region` to HugrMut
([#2463](#2463))
- Non-region entrypoints in `hugr-model`.
([#2467](#2467))
</blockquote>

## `hugr-llvm`

<blockquote>

##
[0.21.0](hugr-llvm-v0.20.2...hugr-llvm-v0.21.0)
- 2025-07-09

### New Features

- [**breaking**] No nested FuncDefns (or AliasDefns)
([#2256](#2256))
- [**breaking**] Split `TypeArg::Sequence` into tuples and lists.
([#2140](#2140))
- [**breaking**] More helpful error messages in model import
([#2272](#2272))
- [**breaking**] Merge `TypeParam` and `TypeArg` into one `Term` type in
Rust ([#2309](#2309))
- Add `MakeError` op ([#2377](#2377))
</blockquote>

## `hugr-passes`

<blockquote>

##
[0.22.0](hugr-passes-v0.21.0...hugr-passes-v0.22.0)
- 2025-07-24

### New Features

- ReplaceTypes allows linearizing inside Op replacements
([#2435](#2435))
- Add pass for DFG inlining
([#2460](#2460))
</blockquote>

## `hugr-persistent`

<blockquote>

##
[0.2.0](hugr-persistent-v0.1.0...hugr-persistent-v0.2.0)
- 2025-07-24

### New Features

- [**breaking**] Update portgraph dependency to 0.15
([#2455](#2455))
</blockquote>

## `hugr`

<blockquote>

##
[0.22.0](hugr-v0.21.0...hugr-v0.22.0)
- 2025-07-24

### Bug Fixes

- Ensure SumTypes have the same json encoding in -rs and -py
([#2465](#2465))

### New Features

- ReplaceTypes allows linearizing inside Op replacements
([#2435](#2435))
- Add pass for DFG inlining
([#2460](#2460))
- Export entrypoint metadata in Python and fix bug in import
([#2434](#2434))
- Names of private functions become `core.title` metadata.
([#2448](#2448))
- [**breaking**] Use binary envelopes for operation lower_func encoding
([#2447](#2447))
- [**breaking**] Update portgraph dependency to 0.15
([#2455](#2455))
- Detect and fail on unrecognised envelope flags
([#2453](#2453))
- include generator metatada in model import and cli validate errors
([#2452](#2452))
- [**breaking**] Add `insert_region` to HugrMut
([#2463](#2463))
- Non-region entrypoints in `hugr-model`.
([#2467](#2467))
</blockquote>

## `hugr-cli`

<blockquote>

##
[0.22.0](hugr-cli-v0.21.0...hugr-cli-v0.22.0)
- 2025-07-24

### New Features

- include generator metatada in model import and cli validate errors
([#2452](#2452))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).

---------

Co-authored-by: Agustín Borgna <[email protected]>
@hugrbot hugrbot mentioned this pull request Jul 28, 2025
github-merge-queue bot pushed a commit that referenced this pull request Jul 28, 2025
## 🤖 New release

* `hugr-model`: 0.22.0 -> 0.22.1
* `hugr-core`: 0.22.0 -> 0.22.1
* `hugr-llvm`: 0.22.0 -> 0.22.1
* `hugr-passes`: 0.22.0 -> 0.22.1 (✓ API compatible changes)
* `hugr`: 0.22.0 -> 0.22.1 (✓ API compatible changes)
* `hugr-cli`: 0.22.0 -> 0.22.1
* `hugr-persistent`: 0.2.0 -> 0.2.1

<details><summary><i><b>Changelog</b></i></summary><p>

## `hugr-model`

<blockquote>

##
[0.22.0](hugr-model-v0.21.0...hugr-model-v0.22.0)
- 2025-07-24

### New Features

- Names of private functions become `core.title` metadata.
([#2448](#2448))
- include generator metatada in model import and cli validate errors
([#2452](#2452))
- Version number in hugr binary format.
([#2468](#2468))
- Use semver crate for -model version, and include in docs
([#2471](#2471))
</blockquote>

## `hugr-core`

<blockquote>

##
[0.22.0](hugr-core-v0.21.0...hugr-core-v0.22.0)
- 2025-07-24

### Bug Fixes

- Ensure SumTypes have the same json encoding in -rs and -py
([#2465](#2465))

### New Features

- Export entrypoint metadata in Python and fix bug in import
([#2434](#2434))
- Names of private functions become `core.title` metadata.
([#2448](#2448))
- [**breaking**] Use binary envelopes for operation lower_func encoding
([#2447](#2447))
- [**breaking**] Update portgraph dependency to 0.15
([#2455](#2455))
- Detect and fail on unrecognised envelope flags
([#2453](#2453))
- include generator metatada in model import and cli validate errors
([#2452](#2452))
- [**breaking**] Add `insert_region` to HugrMut
([#2463](#2463))
- Non-region entrypoints in `hugr-model`.
([#2467](#2467))
</blockquote>

## `hugr-llvm`

<blockquote>

##
[0.21.0](hugr-llvm-v0.20.2...hugr-llvm-v0.21.0)
- 2025-07-09

### New Features

- [**breaking**] No nested FuncDefns (or AliasDefns)
([#2256](#2256))
- [**breaking**] Split `TypeArg::Sequence` into tuples and lists.
([#2140](#2140))
- [**breaking**] More helpful error messages in model import
([#2272](#2272))
- [**breaking**] Merge `TypeParam` and `TypeArg` into one `Term` type in
Rust ([#2309](#2309))
- Add `MakeError` op ([#2377](#2377))
</blockquote>

## `hugr-passes`

<blockquote>

##
[0.22.1](hugr-passes-v0.22.0...hugr-passes-v0.22.1)
- 2025-07-28

### New Features

- Include copy_discard_array in DelegatingLinearizer::default
([#2479](#2479))
- Inline calls to functions not on cycles in the call graph
([#2450](#2450))
</blockquote>

## `hugr`

<blockquote>

##
[0.22.1](hugr-v0.22.0...hugr-v0.22.1)
- 2025-07-28

### New Features

- Include copy_discard_array in DelegatingLinearizer::default
([#2479](#2479))
- Inline calls to functions not on cycles in the call graph
([#2450](#2450))
</blockquote>

## `hugr-cli`

<blockquote>

##
[0.22.0](hugr-cli-v0.21.0...hugr-cli-v0.22.0)
- 2025-07-24

### New Features

- include generator metatada in model import and cli validate errors
([#2452](#2452))
</blockquote>

## `hugr-persistent`

<blockquote>

##
[0.2.0](hugr-persistent-v0.1.0...hugr-persistent-v0.2.0)
- 2025-07-24

### New Features

- [**breaking**] Update portgraph dependency to 0.15
([#2455](#2455))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).
This was referenced Jul 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow TypeParams in TypeArgs.
3 participants