diff --git a/.github/workflows/ci-rs.yml b/.github/workflows/ci-rs.yml
index 824291a8b..c6814fc60 100644
--- a/.github/workflows/ci-rs.yml
+++ b/.github/workflows/ci-rs.yml
@@ -6,7 +6,7 @@ on:
- main
pull_request:
branches:
- - '**'
+ - "**"
merge_group:
types: [checks_requested]
workflow_dispatch: {}
@@ -25,7 +25,6 @@ env:
LLVM_VERSION: "14.0"
LLVM_FEATURE_NAME: "14-0"
-
jobs:
# Check if changes were made to the relevant files.
# Always returns true if running on the default branch, to ensure all changes are thoroughly checked.
@@ -43,25 +42,25 @@ jobs:
model: ${{ steps.filter.outputs.model == 'true' || steps.override.outputs.out == 'true' }}
llvm: ${{ steps.filter.outputs.llvm == 'true' || steps.override.outputs.out == 'true' }}
steps:
- - uses: actions/checkout@v4
- - name: Override label
- id: override
- run: |
- echo "Label contains run-ci-checks: $OVERRIDE_LABEL"
- if [ "$OVERRIDE_LABEL" == "true" ]; then
- echo "Overriding due to label 'run-ci-checks'"
- echo "out=true" >> $GITHUB_OUTPUT
- elif [ "$DEFAULT_BRANCH" == "true" ]; then
- echo "Overriding due to running on the default branch"
- echo "out=true" >> $GITHUB_OUTPUT
- fi
- env:
- OVERRIDE_LABEL: ${{ github.event_name == 'pull_request' && contains( github.event.pull_request.labels.*.name, 'run-ci-checks') }}
- DEFAULT_BRANCH: ${{ github.ref_name == github.event.repository.default_branch }}
- - uses: dorny/paths-filter@v3
- id: filter
- with:
- filters: .github/change-filters.yml
+ - uses: actions/checkout@v4
+ - name: Override label
+ id: override
+ run: |
+ echo "Label contains run-ci-checks: $OVERRIDE_LABEL"
+ if [ "$OVERRIDE_LABEL" == "true" ]; then
+ echo "Overriding due to label 'run-ci-checks'"
+ echo "out=true" >> $GITHUB_OUTPUT
+ elif [ "$DEFAULT_BRANCH" == "true" ]; then
+ echo "Overriding due to running on the default branch"
+ echo "out=true" >> $GITHUB_OUTPUT
+ fi
+ env:
+ OVERRIDE_LABEL: ${{ github.event_name == 'pull_request' && contains( github.event.pull_request.labels.*.name, 'run-ci-checks') }}
+ DEFAULT_BRANCH: ${{ github.ref_name == github.event.repository.default_branch }}
+ - uses: dorny/paths-filter@v3
+ id: filter
+ with:
+ filters: .github/change-filters.yml
check:
needs: changes
@@ -109,7 +108,7 @@ jobs:
- name: Override criterion with the CodSpeed harness
run: cargo add --dev codspeed-criterion-compat --rename criterion --package hugr
- name: Build benchmarks
- run: cargo codspeed build --profile bench --features extension_inference,declarative,model_unstable,llvm,llvm-test
+ run: cargo codspeed build --profile bench --features declarative,llvm,llvm-test
- name: Run benchmarks
uses: CodSpeedHQ/action@v3
with:
@@ -234,7 +233,7 @@ jobs:
id: toolchain
uses: dtolnay/rust-toolchain@master
with:
- toolchain: "1.75"
+ toolchain: "1.85"
- name: Install nightly toolchain
uses: dtolnay/rust-toolchain@master
with:
@@ -253,12 +252,10 @@ jobs:
cargo binstall cargo-minimal-versions --force
- name: Pin transitive dependencies not compatible with our MSRV
# Add new dependencies as needed if the check fails due to
- # "package `XXX` cannot be built because it requires rustc YYY or newer, while the currently active rustc version is 1.75.0"
+ # "package `XXX` cannot be built because it requires rustc YYY or newer, while the currently active rustc version is 1.85.0"
run: |
- rm Cargo.lock
- cargo add -p hugr half@2.4.1
- cargo add -p hugr litemap@0.7.4
- cargo add -p hugr zerofrom@0.1.5
+ # rm Cargo.lock
+ # cargo add -p hugr half@2.4.1
- name: Build with no features
run: cargo minimal-versions --direct test --verbose --no-default-features --no-run
- name: Tests with no features
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 569ccfec1..b6e481bd5 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -79,7 +79,7 @@ repos:
# built into a binary build (without using `maturin`)
#
# This feature list should be kept in sync with the `hugr-py/pyproject.toml`
- entry: cargo test --workspace --exclude 'hugr-py' --features 'hugr/extension_inference hugr/declarative hugr/model_unstable hugr/llvm hugr/llvm-test hugr/zstd'
+ entry: cargo test --workspace --exclude 'hugr-py' --features 'hugr/declarative hugr/llvm hugr/llvm-test hugr/zstd'
language: system
files: \.rs$
pass_filenames: false
@@ -100,10 +100,7 @@ repos:
- id: py-test
name: pytest
description: Run python tests
- # We need to rebuild `hugr-cli` without the `extension_inference` feature
- # to avoid test errors.
- # TODO: Remove this once the issue is fixed.
- entry: sh -c "cargo build -p hugr-cli && uv run pytest"
+ entry: sh -c "uv run pytest"
language: system
files: \.py$
pass_filenames: false
diff --git a/Cargo.lock b/Cargo.lock
index 7198a4ea5..b05cba1e8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -24,7 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
- "getrandom 0.2.15",
+ "getrandom 0.2.16",
"once_cell",
"serde",
"version_check",
@@ -301,9 +301,9 @@ checksum = "38c99613cb3cd7429889a08dfcf651721ca971c86afa30798461f8eee994de47"
[[package]]
name = "bstr"
-version = "1.11.3"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0"
+checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4"
dependencies = [
"memchr",
"regex-automata",
@@ -351,9 +351,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
-version = "1.2.18"
+version = "1.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c"
+checksum = "04da6a0d40b948dfc4fa8f5bbf402b0fc1a64a28dbf7d12ffd683550f2c1b63a"
dependencies = [
"jobserver",
"libc",
@@ -936,9 +936,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.15"
+version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
"libc",
@@ -1458,9 +1458,9 @@ checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
[[package]]
name = "inkwell"
-version = "0.5.0"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40fb405537710d51f6bdbc8471365ddd4cd6d3a3c3ad6e0c8291691031ba94b2"
+checksum = "e67349bd7578d4afebbe15eaa642a80b884e8623db74b1716611b131feb1deef"
dependencies = [
"either",
"inkwell_internals",
@@ -1472,9 +1472,9 @@ dependencies = [
[[package]]
name = "inkwell_internals"
-version = "0.10.0"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9dd28cfd4cfba665d47d31c08a6ba637eed16770abca2eccbbc3ca831fef1e44"
+checksum = "f365c8de536236cfdebd0ba2130de22acefed18b1fb99c32783b3840aec5fb46"
dependencies = [
"proc-macro2",
"quote",
@@ -1483,14 +1483,12 @@ dependencies = [
[[package]]
name = "insta"
-version = "1.42.2"
+version = "1.43.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50259abbaa67d11d2bcafc7ba1d094ed7a0c70e3ce893f0d0997f73558cb3084"
+checksum = "ab2d11b2f17a45095b8c3603928ba29d7d918d7129d0d0641a36ba73cf07daa6"
dependencies = [
"console",
- "linked-hash-map",
"once_cell",
- "pin-project",
"serde",
"similar",
]
@@ -1622,21 +1620,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
-version = "0.2.171"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
-
-[[package]]
-name = "linked-hash-map"
-version = "0.5.6"
+version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
+checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
[[package]]
name = "linux-raw-sys"
-version = "0.9.3"
+version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413"
+checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
[[package]]
name = "litemap"
@@ -1696,9 +1688,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "miniz_oxide"
-version = "0.8.7"
+version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
+checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
dependencies = [
"adler2",
]
@@ -1937,26 +1929,6 @@ dependencies = [
"serde",
]
-[[package]]
-name = "pin-project"
-version = "1.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
-dependencies = [
- "pin-project-internal",
-]
-
-[[package]]
-name = "pin-project-internal"
-version = "1.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
[[package]]
name = "pin-project-lite"
version = "0.2.16"
@@ -2011,9 +1983,9 @@ checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
[[package]]
name = "portgraph"
-version = "0.14.0"
+version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a9ea69cfb011d5f17af28813ec37a0a9668a063090e14ad75dc5fc07ba01b47"
+checksum = "5fdce52d51ec359351ff3c209fafb6f133562abf52d951ce5821c0184798d979"
dependencies = [
"bitvec",
"delegate",
@@ -2029,7 +2001,7 @@ version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
dependencies = [
- "zerocopy 0.8.24",
+ "zerocopy 0.8.25",
]
[[package]]
@@ -2094,9 +2066,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.94"
+version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
+checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
@@ -2259,7 +2231,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
- "getrandom 0.2.15",
+ "getrandom 0.2.16",
]
[[package]]
@@ -2694,9 +2666,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.100"
+version = "2.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
+checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
dependencies = [
"proc-macro2",
"quote",
@@ -2830,15 +2802,15 @@ dependencies = [
[[package]]
name = "toml_datetime"
-version = "0.6.8"
+version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
+checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3"
[[package]]
name = "toml_edit"
-version = "0.22.24"
+version = "0.22.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
+checksum = "10558ed0bd2a1562e630926a2d1f0b98c827da99fabd3fe20920a59642504485"
dependencies = [
"indexmap",
"toml_datetime",
@@ -3418,9 +3390,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]]
name = "winnow"
-version = "0.7.6"
+version = "0.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10"
+checksum = "6cb8234a863ea0e8cd7284fcdd4f145233eb00fee02bbdd9861aec44e6477bc5"
dependencies = [
"memchr",
]
@@ -3496,11 +3468,11 @@ dependencies = [
[[package]]
name = "zerocopy"
-version = "0.8.24"
+version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
+checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
dependencies = [
- "zerocopy-derive 0.8.24",
+ "zerocopy-derive 0.8.25",
]
[[package]]
@@ -3516,9 +3488,9 @@ dependencies = [
[[package]]
name = "zerocopy-derive"
-version = "0.8.24"
+version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be"
+checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
dependencies = [
"proc-macro2",
"quote",
diff --git a/Cargo.toml b/Cargo.toml
index 3031df1e7..97dad7dea 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -15,7 +15,7 @@ members = [
default-members = ["hugr", "hugr-core", "hugr-passes", "hugr-cli", "hugr-model"]
[workspace.package]
-rust-version = "1.75"
+rust-version = "1.85"
edition = "2021"
homepage = "https://github.com/CQCL/hugr"
repository = "https://github.com/CQCL/hugr"
@@ -58,7 +58,7 @@ regex = "1.10.6"
regex-syntax = "0.8.3"
rstest = "0.24.0"
semver = "1.0.26"
-serde = "1.0.195"
+serde = "1.0.219"
serde_json = "1.0.140"
serde_yaml = "0.9.34"
smol_str = "0.3.1"
@@ -87,8 +87,8 @@ zstd = "0.13.2"
# These public dependencies usually require breaking changes downstream, so we
# try to be as permissive as possible.
pyo3 = ">= 0.23.4, < 0.25"
-portgraph = { version = ">= 0.13.3, < 0.15" }
-petgraph = { version = ">= 0.7.1, < 0.9", default-features = false }
+portgraph = { version = "0.14.1" }
+petgraph = { version = ">= 0.8.1, < 0.9", default-features = false }
[profile.dev.package]
insta.opt-level = 3
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
index 4659f96c7..d9f19ed64 100644
--- a/DEVELOPMENT.md
+++ b/DEVELOPMENT.md
@@ -28,10 +28,10 @@ shell by setting up [direnv](https://devenv.sh/automatic-shell-activation/).
To setup the environment manually you will need:
-- Just: https://just.systems/
-- Rust `>=1.75`: https://www.rust-lang.org/tools/install
-- uv `>=0.3`: docs.astral.sh/uv/getting-started/installation
-- Optional: capnproto `>=1.0`: https://capnproto.org/install.html
+- Just:
+- Rust `>=1.85`:
+- uv `>=0.3`:
+- Optional: capnproto `>=1.0`:
Required when modifying the `hugr-model` serialization schema.
- Optional: llvm `== 14.0`. The "llvm" feature (backed by the sub-crate `hugr-llvm`)
requires LLVM installed. We use the rust bindings
diff --git a/hugr-cli/README.md b/hugr-cli/README.md
index 277628d2b..dba9900e2 100644
--- a/hugr-cli/README.md
+++ b/hugr-cli/README.md
@@ -64,7 +64,7 @@ This project is licensed under Apache License, Version 2.0 ([LICENSE][] or http:
[API documentation here]: https://docs.rs/hugr-cli/
[build_status]: https://github.com/CQCL/hugr/actions/workflows/ci-rs.yml/badge.svg?branch=main
- [msrv]: https://img.shields.io/badge/rust-1.75.0%2B-blue.svg
+ [msrv]: https://img.shields.io/crates/msrv/hugr-cli
[crates]: https://img.shields.io/crates/v/hugr-cli
[codecov]: https://img.shields.io/codecov/c/gh/CQCL/hugr?logo=codecov
[LICENSE]: https://github.com/CQCL/hugr/blob/main/LICENCE
diff --git a/hugr-core/Cargo.toml b/hugr-core/Cargo.toml
index 22e5390fc..8da686ee8 100644
--- a/hugr-core/Cargo.toml
+++ b/hugr-core/Cargo.toml
@@ -17,9 +17,7 @@ categories = ["compilers"]
workspace = true
[features]
-extension_inference = []
declarative = ["serde_yaml"]
-model_unstable = ["hugr-model"]
zstd = ["dep:zstd"]
[lib]
@@ -27,10 +25,9 @@ bench = false
[[test]]
name = "model"
-required-features = ["model_unstable"]
[dependencies]
-hugr-model = { version = "0.19.0", path = "../hugr-model", optional = true }
+hugr-model = { version = "0.19.0", path = "../hugr-model" }
cgmath = { workspace = true, features = ["serde"] }
delegate = { workspace = true }
diff --git a/hugr-core/README.md b/hugr-core/README.md
index 46cafe16f..0e15305f1 100644
--- a/hugr-core/README.md
+++ b/hugr-core/README.md
@@ -1,7 +1,6 @@

-hugr-core
-===============
+# hugr-core
[![build_status][]](https://github.com/CQCL/hugr/actions)
[![crates][]](https://crates.io/crates/hugr-core)
@@ -15,15 +14,8 @@ Please read the [API documentation here][].
## Experimental Features
-- `extension_inference`:
- Experimental feature which allows automatic inference of which extra extensions
- are required at runtime by a HUGR when validating it.
- Not enabled by default.
- `declarative`:
Experimental support for declaring extensions in YAML files, support is limited.
-- `model_unstable`
- Import and export from the representation defined in the `hugr-model` crate.
- Unstable and subject to change. Not enabled by default.
## Recent Changes
@@ -38,10 +30,10 @@ See [DEVELOPMENT.md](https://github.com/CQCL/hugr/blob/main/DEVELOPMENT.md) for
This project is licensed under Apache License, Version 2.0 ([LICENSE][] or http://www.apache.org/licenses/LICENSE-2.0).
- [API documentation here]: https://docs.rs/hugr-core/
- [build_status]: https://github.com/CQCL/hugr/actions/workflows/ci-rs.yml/badge.svg?branch=main
- [msrv]: https://img.shields.io/badge/rust-1.75.0%2B-blue.svg
- [crates]: https://img.shields.io/crates/v/hugr-core
- [codecov]: https://img.shields.io/codecov/c/gh/CQCL/hugr?logo=codecov
- [LICENSE]: https://github.com/CQCL/hugr/blob/main/LICENCE
- [CHANGELOG]: https://github.com/CQCL/hugr/blob/main/hugr-core/CHANGELOG.md
+[API documentation here]: https://docs.rs/hugr-core/
+[build_status]: https://github.com/CQCL/hugr/actions/workflows/ci-rs.yml/badge.svg?branch=main
+[msrv]: https://img.shields.io/crates/msrv/hugr-core
+[crates]: https://img.shields.io/crates/v/hugr-core
+[codecov]: https://img.shields.io/codecov/c/gh/CQCL/hugr?logo=codecov
+[LICENSE]: https://github.com/CQCL/hugr/blob/main/LICENCE
+[CHANGELOG]: https://github.com/CQCL/hugr/blob/main/hugr-core/CHANGELOG.md
diff --git a/hugr-core/src/builder.rs b/hugr-core/src/builder.rs
index 056690e0a..9f7a219a7 100644
--- a/hugr-core/src/builder.rs
+++ b/hugr-core/src/builder.rs
@@ -42,7 +42,7 @@
//! let _dfg_handle = {
//! let mut dfg = module_builder.define_function(
//! "main",
-//! Signature::new_endo(bool_t()).with_extension_delta(logic::EXTENSION_ID),
+//! Signature::new_endo(bool_t()),
//! )?;
//!
//! // Get the wires from the function inputs.
@@ -59,8 +59,7 @@
//! let _circuit_handle = {
//! let mut dfg = module_builder.define_function(
//! "circuit",
-//! Signature::new_endo(vec![bool_t(), bool_t()])
-//! .with_extension_delta(logic::EXTENSION_ID),
+//! Signature::new_endo(vec![bool_t(), bool_t()]),
//! )?;
//! let mut circuit = dfg.as_circuit(dfg.input_wires());
//!
@@ -89,7 +88,7 @@
use thiserror::Error;
use crate::extension::simple_op::OpLoadError;
-use crate::extension::{SignatureError, TO_BE_INFERRED};
+use crate::extension::SignatureError;
use crate::hugr::ValidationError;
use crate::ops::handle::{BasicBlockID, CfgID, ConditionalID, DfgID, FuncID, TailLoopID};
use crate::ops::{NamedOp, OpType};
@@ -123,16 +122,14 @@ pub use conditional::{CaseBuilder, ConditionalBuilder};
mod circuit;
pub use circuit::{CircuitBuildError, CircuitBuilder};
-/// Return a FunctionType with the same input and output types (specified)
-/// whose extension delta, when used in a non-FuncDefn container, will be inferred.
+/// Return a FunctionType with the same input and output types (specified).
pub fn endo_sig(types: impl Into) -> Signature {
- Signature::new_endo(types).with_extension_delta(TO_BE_INFERRED)
+ Signature::new_endo(types)
}
-/// Return a FunctionType with the specified input and output types
-/// whose extension delta, when used in a non-FuncDefn container, will be inferred.
+/// Return a FunctionType with the specified input and output types.
pub fn inout_sig(inputs: impl Into, outputs: impl Into) -> Signature {
- Signature::new(inputs, outputs).with_extension_delta(TO_BE_INFERRED)
+ Signature::new(inputs, outputs)
}
#[derive(Debug, Clone, PartialEq, Error)]
diff --git a/hugr-core/src/builder/build_traits.rs b/hugr-core/src/builder/build_traits.rs
index f1613895d..ba366c117 100644
--- a/hugr-core/src/builder/build_traits.rs
+++ b/hugr-core/src/builder/build_traits.rs
@@ -20,7 +20,7 @@ use crate::{
types::EdgeKind,
};
-use crate::extension::{ExtensionRegistry, ExtensionSet, TO_BE_INFERRED};
+use crate::extension::ExtensionRegistry;
use crate::types::{PolyFuncType, Signature, Type, TypeArg, TypeRow};
use itertools::Itertools;
@@ -119,7 +119,7 @@ pub trait Container {
}
/// Insert a copy of a HUGR as a child of the container.
- fn add_hugr_view(&mut self, child: &impl HugrView) -> InsertionResult {
+ fn add_hugr_view(&mut self, child: &H) -> InsertionResult {
let parent = self.container_node();
self.hugr_mut().insert_from_view(parent, child)
}
@@ -153,7 +153,7 @@ pub trait Container {
where
ExtensionRegistry: Extend,
{
- self.hugr_mut().extensions_mut().extend(registry);
+ self.hugr_mut().use_extensions(registry);
}
}
@@ -319,10 +319,7 @@ pub trait Dataflow: Container {
inputs: impl IntoIterator- ,
) -> Result, BuildError> {
let (types, input_wires): (Vec, Vec) = inputs.into_iter().unzip();
- self.dfg_builder(
- Signature::new_endo(types).with_extension_delta(TO_BE_INFERRED),
- input_wires,
- )
+ self.dfg_builder(Signature::new_endo(types), input_wires)
}
/// Return a builder for a [`crate::ops::CFG`] node,
@@ -330,7 +327,6 @@ pub trait Dataflow: Container {
/// The `inputs` must be an iterable over pairs of the type of the input and
/// the corresponding wire.
/// The `output_types` are the types of the outputs.
- /// The Extension delta will be inferred.
///
/// # Errors
///
@@ -340,27 +336,6 @@ pub trait Dataflow: Container {
&mut self,
inputs: impl IntoIterator
- ,
output_types: TypeRow,
- ) -> Result, BuildError> {
- self.cfg_builder_exts(inputs, output_types, TO_BE_INFERRED)
- }
-
- /// Return a builder for a [`crate::ops::CFG`] node,
- /// i.e. a nested controlflow subgraph.
- /// The `inputs` must be an iterable over pairs of the type of the input and
- /// the corresponding wire.
- /// The `output_types` are the types of the outputs.
- /// `extension_delta` is explicitly specified. Alternatively
- /// [cfg_builder](Self::cfg_builder) may be used to infer it.
- ///
- /// # Errors
- ///
- /// This function will return an error if there is an error when building
- /// the CFG node.
- fn cfg_builder_exts(
- &mut self,
- inputs: impl IntoIterator
- ,
- output_types: TypeRow,
- extension_delta: impl Into,
) -> Result, BuildError> {
let (input_types, input_wires): (Vec, Vec) = inputs.into_iter().unzip();
@@ -369,8 +344,7 @@ pub trait Dataflow: Container {
let (cfg_node, _) = add_node_with_wires(
self,
ops::CFG {
- signature: Signature::new(inputs.clone(), output_types.clone())
- .with_extension_delta(extension_delta),
+ signature: Signature::new(inputs.clone(), output_types.clone()),
},
input_wires,
)?;
@@ -449,7 +423,6 @@ pub trait Dataflow: Container {
/// The `inputs` must be an iterable over pairs of the type of the input and
/// the corresponding wire.
/// The `output_types` are the types of the outputs.
- /// The extension delta will be inferred.
///
/// # Errors
///
@@ -461,27 +434,6 @@ pub trait Dataflow: Container {
just_inputs: impl IntoIterator
- ,
inputs_outputs: impl IntoIterator
- ,
just_out_types: TypeRow,
- ) -> Result, BuildError> {
- self.tail_loop_builder_exts(just_inputs, inputs_outputs, just_out_types, TO_BE_INFERRED)
- }
-
- /// Return a builder for a [`crate::ops::TailLoop`] node.
- /// The `inputs` must be an iterable over pairs of the type of the input and
- /// the corresponding wire.
- /// The `output_types` are the types of the outputs.
- /// `extension_delta` explicitly specified. Alternatively
- /// [tail_loop_builder](Self::tail_loop_builder) may be used to infer it.
- ///
- /// # Errors
- ///
- /// This function will return an error if there is an error when building
- /// the [`ops::TailLoop`] node.
- fn tail_loop_builder_exts(
- &mut self,
- just_inputs: impl IntoIterator
- ,
- inputs_outputs: impl IntoIterator
- ,
- just_out_types: TypeRow,
- extension_delta: impl Into,
) -> Result, BuildError> {
let (input_types, mut input_wires): (Vec, Vec) =
just_inputs.into_iter().unzip();
@@ -493,7 +445,6 @@ pub trait Dataflow: Container {
just_inputs: input_types.into(),
just_outputs: just_out_types,
rest: rest_types.into(),
- extension_delta: extension_delta.into(),
};
// TODO: Make input extensions a parameter
let (loop_node, _) = add_node_with_wires(self, tail_loop.clone(), input_wires)?;
@@ -507,41 +458,17 @@ pub trait Dataflow: Container {
///
/// The `other_inputs` must be an iterable over pairs of the type of the input and
/// the corresponding wire.
- /// The `output_types` are the types of the outputs. Extension delta will be inferred.
- ///
- /// # Errors
- ///
- /// This function will return an error if there is an error when building
- /// the Conditional node.
- fn conditional_builder(
- &mut self,
- sum_input: (impl IntoIterator
- , Wire),
- other_inputs: impl IntoIterator
- ,
- output_types: TypeRow,
- ) -> Result, BuildError> {
- self.conditional_builder_exts(sum_input, other_inputs, output_types, TO_BE_INFERRED)
- }
-
- /// Return a builder for a [`crate::ops::Conditional`] node.
- /// `sum_rows` and `sum_wire` define the type of the Sum
- /// variants and the wire carrying the Sum respectively.
- ///
- /// The `other_inputs` must be an iterable over pairs of the type of the input and
- /// the corresponding wire.
/// The `output_types` are the types of the outputs.
- /// `extension_delta` is explicitly specified. Alternatively
- /// [conditional_builder](Self::conditional_builder) may be used to infer it.
///
/// # Errors
///
/// This function will return an error if there is an error when building
/// the Conditional node.
- fn conditional_builder_exts(
+ fn conditional_builder(
&mut self,
(sum_rows, sum_wire): (impl IntoIterator
- , Wire),
other_inputs: impl IntoIterator
- ,
output_types: TypeRow,
- extension_delta: impl Into,
) -> Result, BuildError> {
let mut input_wires = vec![sum_wire];
let (input_types, rest_input_wires): (Vec, Vec) =
@@ -558,7 +485,6 @@ pub trait Dataflow: Container {
sum_rows,
other_inputs: inputs,
outputs: output_types,
- extension_delta: extension_delta.into(),
},
input_wires,
)?;
diff --git a/hugr-core/src/builder/cfg.rs b/hugr-core/src/builder/cfg.rs
index 81c7d7269..0aadc047b 100644
--- a/hugr-core/src/builder/cfg.rs
+++ b/hugr-core/src/builder/cfg.rs
@@ -5,9 +5,8 @@ use super::{
BasicBlockID, BuildError, CfgID, Container, Dataflow, HugrBuilder, Wire,
};
-use crate::extension::TO_BE_INFERRED;
use crate::ops::{self, handle::NodeHandle, DataflowBlock, DataflowParent, ExitBlock, OpType};
-use crate::{extension::ExtensionSet, types::Signature};
+use crate::types::Signature;
use crate::{hugr::views::HugrView, types::TypeRow};
use crate::Node;
@@ -106,7 +105,6 @@ use crate::{hugr::HugrMut, type_row, Hugr};
/// let hugr = cfg_builder.finish_hugr()?;
/// Ok(hugr)
/// };
-/// #[cfg(not(feature = "extension_inference"))]
/// assert!(make_cfg().is_ok());
/// ```
#[derive(Debug, PartialEq)]
@@ -157,10 +155,7 @@ impl CFGBuilder {
}
impl HugrBuilder for CFGBuilder {
- fn finish_hugr(mut self) -> Result {
- if cfg!(feature = "extension_inference") {
- self.base.infer_extensions(false)?;
- }
+ fn finish_hugr(self) -> Result {
self.base.validate()?;
Ok(self.base)
}
@@ -192,7 +187,7 @@ impl + AsRef> CFGBuilder {
/// Return a builder for a non-entry [`DataflowBlock`] child graph with `inputs`
/// and `outputs` and the variants of the branching Sum value
- /// specified by `sum_rows`. Extension delta will be inferred.
+ /// specified by `sum_rows`.
///
/// # Errors
///
@@ -203,36 +198,12 @@ impl + AsRef> CFGBuilder {
sum_rows: impl IntoIterator
- ,
other_outputs: TypeRow,
) -> Result, BuildError> {
- self.block_builder_exts(inputs, sum_rows, other_outputs, TO_BE_INFERRED)
- }
-
- /// Return a builder for a non-entry [`DataflowBlock`] child graph with `inputs`
- /// and `outputs` and the variants of the branching Sum value
- /// specified by `sum_rows`. Extension delta will be inferred.
- ///
- /// # Errors
- ///
- /// This function will return an error if there is an error adding the node.
- pub fn block_builder_exts(
- &mut self,
- inputs: TypeRow,
- sum_rows: impl IntoIterator
- ,
- other_outputs: TypeRow,
- extension_delta: impl Into,
- ) -> Result, BuildError> {
- self.any_block_builder(
- inputs,
- extension_delta.into(),
- sum_rows,
- other_outputs,
- false,
- )
+ self.any_block_builder(inputs, sum_rows, other_outputs, false)
}
fn any_block_builder(
&mut self,
inputs: TypeRow,
- extension_delta: ExtensionSet,
sum_rows: impl IntoIterator
- ,
other_outputs: TypeRow,
entry: bool,
@@ -242,7 +213,6 @@ impl + AsRef> CFGBuilder {
inputs: inputs.clone(),
other_outputs: other_outputs.clone(),
sum_rows,
- extension_delta,
});
let parent = self.container_node();
let block_n = if entry {
@@ -257,9 +227,9 @@ impl + AsRef> CFGBuilder {
BlockBuilder::create(self.hugr_mut(), block_n)
}
- /// Return a builder for a non-entry [`DataflowBlock`] child graph with `inputs`
- /// and `outputs` and `extension_delta` explicitly specified, plus a UnitSum type
- /// (a Sum of `n_cases` unit types) to select the successor.
+ /// Return a builder for a non-entry [`DataflowBlock`] child graph with
+ /// `inputs` and `outputs` , plus a UnitSum type (a Sum of `n_cases` unit
+ /// types) to select the successor.
///
/// # Errors
///
@@ -269,17 +239,15 @@ impl + AsRef> CFGBuilder {
signature: Signature,
n_cases: usize,
) -> Result, BuildError> {
- self.block_builder_exts(
+ self.block_builder(
signature.input,
vec![type_row![]; n_cases],
signature.output,
- signature.runtime_reqs,
)
}
/// Return a builder for the entry [`DataflowBlock`] child graph with `outputs`
/// and the variants of the branching Sum value specified by `sum_rows`.
- /// Extension delta will be inferred.
///
/// # Errors
///
@@ -288,35 +256,12 @@ impl + AsRef> CFGBuilder {
&mut self,
sum_rows: impl IntoIterator
- ,
other_outputs: TypeRow,
- ) -> Result, BuildError> {
- self.entry_builder_exts(sum_rows, other_outputs, TO_BE_INFERRED)
- }
-
- /// Return a builder for the entry [`DataflowBlock`] child graph with `outputs`,
- /// the variants of the branching Sum value specified by `sum_rows`, and
- /// `extension_delta` explicitly specified. ([entry_builder](Self::entry_builder)
- /// may be used to infer.)
- ///
- /// # Errors
- ///
- /// This function will return an error if an entry block has already been built.
- pub fn entry_builder_exts(
- &mut self,
- sum_rows: impl IntoIterator
- ,
- other_outputs: TypeRow,
- extension_delta: impl Into,
) -> Result, BuildError> {
let inputs = self
.inputs
.take()
.ok_or(BuildError::EntryBuiltError(self.cfg_node))?;
- self.any_block_builder(
- inputs,
- extension_delta.into(),
- sum_rows,
- other_outputs,
- true,
- )
+ self.any_block_builder(inputs, sum_rows, other_outputs, true)
}
/// Return a builder for the entry [`DataflowBlock`] child graph with
@@ -333,22 +278,6 @@ impl + AsRef> CFGBuilder {
self.entry_builder(vec![type_row![]; n_cases], outputs)
}
- /// Return a builder for the entry [`DataflowBlock`] child graph with
- /// `outputs` and a Sum of `n_cases` unit types, and explicit `extension_delta`.
- /// ([simple_entry_builder](Self::simple_entry_builder) may be used to infer.)
- ///
- /// # Errors
- ///
- /// This function will return an error if there is an error adding the node.
- pub fn simple_entry_builder_exts(
- &mut self,
- outputs: TypeRow,
- n_cases: usize,
- extension_delta: impl Into,
- ) -> Result, BuildError> {
- self.entry_builder_exts(vec![type_row![]; n_cases], outputs, extension_delta)
- }
-
/// Returns the exit block of this [`CFGBuilder`].
pub fn exit_block(&self) -> BasicBlockID {
self.exit_node.into()
@@ -412,23 +341,10 @@ impl + AsRef> BlockBuilder {
impl BlockBuilder {
/// Initialize a [`DataflowBlock`] rooted HUGR builder.
- /// Extension delta will be inferred.
pub fn new(
inputs: impl Into,
sum_rows: impl IntoIterator
- ,
other_outputs: impl Into,
- ) -> Result {
- Self::new_exts(inputs, sum_rows, other_outputs, TO_BE_INFERRED)
- }
-
- /// Initialize a [`DataflowBlock`] rooted HUGR builder.
- /// `extension_delta` is explicitly specified; alternatively, [new](Self::new)
- /// may be used to infer it.
- pub fn new_exts(
- inputs: impl Into,
- sum_rows: impl IntoIterator
- ,
- other_outputs: impl Into,
- extension_delta: impl Into,
) -> Result {
let inputs = inputs.into();
let sum_rows: Vec<_> = sum_rows.into_iter().collect();
@@ -437,7 +353,6 @@ impl BlockBuilder {
inputs: inputs.clone(),
other_outputs: other_outputs.clone(),
sum_rows,
- extension_delta: extension_delta.into(),
};
let base = Hugr::new(op);
@@ -507,11 +422,7 @@ pub(crate) mod test {
) -> Result<(), BuildError> {
let usize_row: TypeRow = vec![usize_t()].into();
let sum2_variants = vec![usize_row.clone(), usize_row];
- let mut entry_b = cfg_builder.entry_builder_exts(
- sum2_variants.clone(),
- type_row![],
- ExtensionSet::new(),
- )?;
+ let mut entry_b = cfg_builder.entry_builder(sum2_variants.clone(), type_row![])?;
let entry = {
let [inw] = entry_b.input_wires_arr();
@@ -537,11 +448,7 @@ pub(crate) mod test {
let sum_tuple_const = cfg_builder.add_constant(ops::Value::unary_unit_sum());
let sum_variants = vec![type_row![]];
- let mut entry_b = cfg_builder.entry_builder_exts(
- sum_variants.clone(),
- type_row![],
- ExtensionSet::new(),
- )?;
+ let mut entry_b = cfg_builder.entry_builder(sum_variants.clone(), type_row![])?;
let [inw] = entry_b.input_wires_arr();
let entry = {
let sum = entry_b.load_const(&sum_tuple_const);
diff --git a/hugr-core/src/builder/circuit.rs b/hugr-core/src/builder/circuit.rs
index 01f5e3e45..eb48b4fbc 100644
--- a/hugr-core/src/builder/circuit.rs
+++ b/hugr-core/src/builder/circuit.rs
@@ -245,8 +245,8 @@ mod test {
use crate::builder::{Container, HugrBuilder, ModuleBuilder};
use crate::extension::prelude::{qb_t, usize_t};
- use crate::extension::{ExtensionId, ExtensionSet};
- use crate::std_extensions::arithmetic::float_types::{self, ConstF64};
+ use crate::extension::ExtensionId;
+ use crate::std_extensions::arithmetic::float_types::ConstF64;
use crate::utils::test_quantum_extension::{
self, cx_gate, h_gate, measure, q_alloc, q_discard, rz_f64,
};
@@ -260,10 +260,7 @@ mod test {
#[test]
fn simple_linear() {
let build_res = build_main(
- Signature::new(vec![qb_t(), qb_t()], vec![qb_t(), qb_t()])
- .with_extension_delta(test_quantum_extension::EXTENSION_ID)
- .with_extension_delta(float_types::EXTENSION_ID)
- .into(),
+ Signature::new(vec![qb_t(), qb_t()], vec![qb_t(), qb_t()]).into(),
|mut f_build| {
let wires = f_build.input_wires().map(Some).collect();
@@ -314,11 +311,7 @@ mod test {
Signature::new(
vec![qb_t(), qb_t(), usize_t()],
vec![qb_t(), qb_t(), bool_t()],
- )
- .with_extension_delta(ExtensionSet::from_iter([
- test_quantum_extension::EXTENSION_ID,
- my_ext_name,
- ])),
+ ),
)
.unwrap();
@@ -351,38 +344,33 @@ mod test {
#[test]
fn ancillae() {
- let build_res = build_main(
- Signature::new_endo(qb_t())
- .with_extension_delta(test_quantum_extension::EXTENSION_ID)
- .into(),
- |mut f_build| {
- let mut circ = f_build.as_circuit(f_build.input_wires());
- assert_eq!(circ.n_wires(), 1);
+ let build_res = build_main(Signature::new_endo(qb_t()).into(), |mut f_build| {
+ let mut circ = f_build.as_circuit(f_build.input_wires());
+ assert_eq!(circ.n_wires(), 1);
- let [q0] = circ.tracked_units_arr();
- let [ancilla] = circ.append_with_outputs_arr(q_alloc(), [] as [CircuitUnit; 0])?;
- let ancilla = circ.track_wire(ancilla);
+ let [q0] = circ.tracked_units_arr();
+ let [ancilla] = circ.append_with_outputs_arr(q_alloc(), [] as [CircuitUnit; 0])?;
+ let ancilla = circ.track_wire(ancilla);
- assert_ne!(ancilla, 0);
- assert_eq!(circ.n_wires(), 2);
- assert_eq!(circ.tracked_units_arr(), [q0, ancilla]);
+ assert_ne!(ancilla, 0);
+ assert_eq!(circ.n_wires(), 2);
+ assert_eq!(circ.tracked_units_arr(), [q0, ancilla]);
- circ.append(cx_gate(), [q0, ancilla])?;
- let [_bit] = circ.append_with_outputs_arr(measure(), [q0])?;
+ circ.append(cx_gate(), [q0, ancilla])?;
+ let [_bit] = circ.append_with_outputs_arr(measure(), [q0])?;
- let q0 = circ.untrack_wire(q0)?;
+ let q0 = circ.untrack_wire(q0)?;
- assert_eq!(circ.tracked_units_arr(), [ancilla]);
+ assert_eq!(circ.tracked_units_arr(), [ancilla]);
- circ.append_and_consume(q_discard(), [q0])?;
+ circ.append_and_consume(q_discard(), [q0])?;
- let outs = circ.finish();
+ let outs = circ.finish();
- assert_eq!(outs.len(), 1);
+ assert_eq!(outs.len(), 1);
- f_build.finish_with_outputs(outs)
- },
- );
+ f_build.finish_with_outputs(outs)
+ });
assert_matches!(build_res, Ok(_));
}
diff --git a/hugr-core/src/builder/conditional.rs b/hugr-core/src/builder/conditional.rs
index 0404abaf3..73670526c 100644
--- a/hugr-core/src/builder/conditional.rs
+++ b/hugr-core/src/builder/conditional.rs
@@ -1,6 +1,4 @@
-use crate::extension::TO_BE_INFERRED;
use crate::hugr::views::HugrView;
-use crate::ops::dataflow::DataflowOpTrait;
use crate::types::{Signature, TypeRow};
use crate::ops;
@@ -16,7 +14,7 @@ use super::{
};
use crate::Node;
-use crate::{extension::ExtensionSet, hugr::HugrMut, Hugr};
+use crate::{hugr::HugrMut, Hugr};
use std::collections::HashSet;
@@ -107,7 +105,6 @@ impl + AsRef> ConditionalBuilder {
.clone()
.try_into()
.expect("Parent node does not have Conditional optype.");
- let extension_delta = cond.signature().runtime_reqs.clone();
let inputs = cond
.case_input_row(case)
.ok_or(ConditionalBuildError::NotCase { conditional, case })?;
@@ -118,8 +115,7 @@ impl + AsRef> ConditionalBuilder {
let outputs = cond.outputs;
let case_op = ops::Case {
- signature: Signature::new(inputs.clone(), outputs.clone())
- .with_extension_delta(extension_delta.clone()),
+ signature: Signature::new(inputs.clone(), outputs.clone()),
};
let case_node =
// add case before any existing subsequent cases
@@ -134,7 +130,7 @@ impl + AsRef> ConditionalBuilder {
let dfg_builder = DFGBuilder::create_with_io(
self.hugr_mut(),
case_node,
- Signature::new(inputs, outputs).with_extension_delta(extension_delta),
+ Signature::new(inputs, outputs),
)?;
Ok(CaseBuilder::from_dfg_builder(dfg_builder))
@@ -142,33 +138,18 @@ impl + AsRef> ConditionalBuilder {
}
impl HugrBuilder for ConditionalBuilder {
- fn finish_hugr(mut self) -> Result {
- if cfg!(feature = "extension_inference") {
- self.base.infer_extensions(false)?;
- }
+ fn finish_hugr(self) -> Result {
self.base.validate()?;
Ok(self.base)
}
}
impl ConditionalBuilder {
- /// Initialize a Conditional rooted HUGR builder, extension delta will be inferred.
+ /// Initialize a Conditional rooted HUGR builder.
pub fn new(
sum_rows: impl IntoIterator
- ,
other_inputs: impl Into,
outputs: impl Into,
- ) -> Result {
- Self::new_exts(sum_rows, other_inputs, outputs, TO_BE_INFERRED)
- }
-
- /// Initialize a Conditional rooted HUGR builder,
- /// `extension_delta` explicitly specified. Alternatively,
- /// [new](Self::new) may be used to infer it.
- pub fn new_exts(
- sum_rows: impl IntoIterator
- ,
- other_inputs: impl Into,
- outputs: impl Into,
- extension_delta: impl Into,
) -> Result {
let sum_rows: Vec<_> = sum_rows.into_iter().collect();
let other_inputs = other_inputs.into();
@@ -181,7 +162,6 @@ impl ConditionalBuilder {
sum_rows,
other_inputs,
outputs,
- extension_delta: extension_delta.into(),
};
let base = Hugr::new(op);
let conditional_node = base.root();
@@ -225,12 +205,8 @@ mod test {
#[test]
fn basic_conditional() -> Result<(), BuildError> {
- let mut conditional_b = ConditionalBuilder::new_exts(
- [type_row![], type_row![]],
- vec![usize_t()],
- vec![usize_t()],
- ExtensionSet::new(),
- )?;
+ let mut conditional_b =
+ ConditionalBuilder::new([type_row![], type_row![]], vec![usize_t()], vec![usize_t()])?;
n_identity(conditional_b.case_builder(1)?)?;
n_identity(conditional_b.case_builder(0)?)?;
diff --git a/hugr-core/src/builder/dataflow.rs b/hugr-core/src/builder/dataflow.rs
index ebad52085..4e66f857f 100644
--- a/hugr-core/src/builder/dataflow.rs
+++ b/hugr-core/src/builder/dataflow.rs
@@ -82,10 +82,7 @@ impl DFGBuilder {
}
impl HugrBuilder for DFGBuilder {
- fn finish_hugr(mut self) -> Result {
- if cfg!(feature = "extension_inference") {
- self.base.infer_extensions(false)?;
- }
+ fn finish_hugr(self) -> Result {
self.base.validate()?;
Ok(self.base)
}
@@ -174,9 +171,7 @@ impl FunctionBuilder {
// Update the inner input node
let types = new_optype.signature.body().input.clone();
- self.hugr_mut()
- .replace_op(inp_node, Input { types })
- .unwrap();
+ self.hugr_mut().replace_op(inp_node, Input { types });
let mut new_port = self.hugr_mut().add_ports(inp_node, Direction::Outgoing, 1);
let new_port = new_port.next().unwrap();
@@ -211,9 +206,7 @@ impl FunctionBuilder {
// Update the inner input node
let types = new_optype.signature.body().output.clone();
- self.hugr_mut()
- .replace_op(out_node, Output { types })
- .unwrap();
+ self.hugr_mut().replace_op(out_node, Output { types });
let mut new_port = self.hugr_mut().add_ports(out_node, Direction::Incoming, 1);
let new_port = new_port.next().unwrap();
@@ -250,15 +243,13 @@ impl FunctionBuilder {
.expect("FunctionBuilder node must be a FuncDefn");
let signature = old_optype.inner_signature().into_owned();
let name = old_optype.name.clone();
- self.hugr_mut()
- .replace_op(
- parent,
- ops::FuncDefn {
- signature: f(signature).into(),
- name,
- },
- )
- .expect("Could not replace FunctionBuilder operation");
+ self.hugr_mut().replace_op(
+ parent,
+ ops::FuncDefn {
+ signature: f(signature).into(),
+ name,
+ },
+ );
self.hugr().get_optype(parent).as_func_defn().unwrap()
}
@@ -424,19 +415,15 @@ pub(crate) mod test {
#[test]
fn simple_inter_graph_edge() {
let builder = || -> Result {
- let mut f_build = FunctionBuilder::new(
- "main",
- Signature::new(vec![bool_t()], vec![bool_t()]).with_prelude(),
- )?;
+ let mut f_build =
+ FunctionBuilder::new("main", Signature::new(vec![bool_t()], vec![bool_t()]))?;
let [i1] = f_build.input_wires_arr();
let noop = f_build.add_dataflow_op(Noop(bool_t()), [i1])?;
let i1 = noop.out_wire(0);
- let mut nested = f_build.dfg_builder(
- Signature::new(type_row![], vec![bool_t()]).with_prelude(),
- [],
- )?;
+ let mut nested =
+ f_build.dfg_builder(Signature::new(type_row![], vec![bool_t()]), [])?;
let id = nested.add_dataflow_op(Noop(bool_t()), [i1])?;
@@ -451,10 +438,8 @@ pub(crate) mod test {
#[test]
fn add_inputs_outputs() {
let builder = || -> Result<(Hugr, Node), BuildError> {
- let mut f_build = FunctionBuilder::new(
- "main",
- Signature::new(vec![bool_t()], vec![bool_t()]).with_prelude(),
- )?;
+ let mut f_build =
+ FunctionBuilder::new("main", Signature::new(vec![bool_t()], vec![bool_t()]))?;
let f_node = f_build.container_node();
let [i0] = f_build.input_wires_arr();
@@ -512,8 +497,8 @@ pub(crate) mod test {
#[rstest]
fn dfg_hugr(simple_dfg_hugr: Hugr) {
- assert_eq!(simple_dfg_hugr.node_count(), 3);
- assert_matches!(simple_dfg_hugr.root_type().tag(), OpTag::Dfg);
+ assert_eq!(simple_dfg_hugr.num_nodes(), 3);
+ assert_matches!(simple_dfg_hugr.root_optype().tag(), OpTag::Dfg);
}
#[test]
@@ -539,7 +524,7 @@ pub(crate) mod test {
};
let hugr = module_builder.finish_hugr()?;
- assert_eq!(hugr.node_count(), 7);
+ assert_eq!(hugr.num_nodes(), 7);
assert_eq!(hugr.get_metadata(hugr.root(), "x"), None);
assert_eq!(hugr.get_metadata(dfg_node, "x").cloned(), Some(json!(42)));
diff --git a/hugr-core/src/builder/module.rs b/hugr-core/src/builder/module.rs
index 18390926e..a77f01e5f 100644
--- a/hugr-core/src/builder/module.rs
+++ b/hugr-core/src/builder/module.rs
@@ -50,10 +50,7 @@ impl Default for ModuleBuilder {
}
impl HugrBuilder for ModuleBuilder {
- fn finish_hugr(mut self) -> Result {
- if cfg!(feature = "extension_inference") {
- self.0.infer_extensions(false)?;
- }
+ fn finish_hugr(self) -> Result {
self.0.validate()?;
Ok(self.0)
}
@@ -83,8 +80,7 @@ impl + AsRef> ModuleBuilder {
.clone();
let body = signature.body().clone();
self.hugr_mut()
- .replace_op(f_node, ops::FuncDefn { name, signature })
- .expect("Replacing a FuncDecl node with a FuncDefn should always be valid");
+ .replace_op(f_node, ops::FuncDefn { name, signature });
let db = DFGBuilder::create_with_io(self.hugr_mut(), f_node, body)?;
Ok(FunctionBuilder::from_dfg_builder(db))
diff --git a/hugr-core/src/builder/tail_loop.rs b/hugr-core/src/builder/tail_loop.rs
index fd6fb03b8..2baa0bcd5 100644
--- a/hugr-core/src/builder/tail_loop.rs
+++ b/hugr-core/src/builder/tail_loop.rs
@@ -1,4 +1,3 @@
-use crate::extension::{ExtensionSet, TO_BE_INFERRED};
use crate::ops::{self, DataflowOpTrait};
use crate::hugr::views::HugrView;
@@ -72,29 +71,15 @@ impl + AsRef> TailLoopBuilder {
impl TailLoopBuilder {
/// Initialize new builder for a [`ops::TailLoop`] rooted HUGR.
- /// Extension delta will be inferred.
pub fn new(
just_inputs: impl Into,
inputs_outputs: impl Into,
just_outputs: impl Into,
- ) -> Result {
- Self::new_exts(just_inputs, inputs_outputs, just_outputs, TO_BE_INFERRED)
- }
-
- /// Initialize new builder for a [`ops::TailLoop`] rooted HUGR.
- /// `extension_delta` is explicitly specified; alternatively, [new](Self::new)
- /// may be used to infer it.
- pub fn new_exts(
- just_inputs: impl Into,
- inputs_outputs: impl Into,
- just_outputs: impl Into,
- extension_delta: impl Into,
) -> Result {
let tail_loop = ops::TailLoop {
just_inputs: just_inputs.into(),
just_outputs: just_outputs.into(),
rest: inputs_outputs.into(),
- extension_delta: extension_delta.into(),
};
let base = Hugr::new(tail_loop.clone());
let root = base.root();
@@ -109,7 +94,7 @@ mod test {
use crate::extension::prelude::bool_t;
use crate::{
builder::{DataflowSubContainer, HugrBuilder, ModuleBuilder, SubContainer},
- extension::prelude::{usize_t, ConstUsize, PRELUDE_ID},
+ extension::prelude::{usize_t, ConstUsize},
hugr::ValidationError,
ops::Value,
type_row,
@@ -120,8 +105,7 @@ mod test {
#[test]
fn basic_loop() -> Result<(), BuildError> {
let build_result: Result = {
- let mut loop_b =
- TailLoopBuilder::new_exts(vec![], vec![bool_t()], vec![usize_t()], PRELUDE_ID)?;
+ let mut loop_b = TailLoopBuilder::new(vec![], vec![bool_t()], vec![usize_t()])?;
let [i1] = loop_b.input_wires_arr();
let const_wire = loop_b.add_load_value(ConstUsize::new(1));
@@ -138,10 +122,8 @@ mod test {
fn loop_with_conditional() -> Result<(), BuildError> {
let build_result = {
let mut module_builder = ModuleBuilder::new();
- let mut fbuild = module_builder.define_function(
- "main",
- Signature::new(vec![bool_t()], vec![usize_t()]).with_prelude(),
- )?;
+ let mut fbuild = module_builder
+ .define_function("main", Signature::new(vec![bool_t()], vec![usize_t()]))?;
let _fdef = {
let [b1] = fbuild.input_wires_arr();
let loop_id = {
diff --git a/hugr-core/src/core.rs b/hugr-core/src/core.rs
index 03e009bef..cc9da77ab 100644
--- a/hugr-core/src/core.rs
+++ b/hugr-core/src/core.rs
@@ -83,7 +83,7 @@ pub struct Wire(N, OutgoingPort);
impl Node {
/// Returns the node as a portgraph `NodeIndex`.
#[inline]
- pub(crate) fn pg_index(self) -> portgraph::NodeIndex {
+ pub(crate) fn into_portgraph(self) -> portgraph::NodeIndex {
self.index
}
}
diff --git a/hugr-core/src/envelope.rs b/hugr-core/src/envelope.rs
index 35ea9c85f..24c348b78 100644
--- a/hugr-core/src/envelope.rs
+++ b/hugr-core/src/envelope.rs
@@ -55,7 +55,6 @@ use std::io::Write;
#[allow(unused_imports)]
use itertools::Itertools as _;
-#[cfg(feature = "model_unstable")]
use crate::import::ImportError;
/// Read a HUGR envelope from a reader.
@@ -197,19 +196,16 @@ pub enum EnvelopeError {
source: PackageEncodingError,
},
/// Error importing a HUGR from a hugr-model payload.
- #[cfg(feature = "model_unstable")]
ModelImport {
/// The source error.
source: ImportError,
},
/// Error reading a HUGR model payload.
- #[cfg(feature = "model_unstable")]
ModelRead {
/// The source error.
source: hugr_model::v0::binary::ReadError,
},
/// Error writing a HUGR model payload.
- #[cfg(feature = "model_unstable")]
ModelWrite {
/// The source error.
source: hugr_model::v0::binary::WriteError,
@@ -225,17 +221,9 @@ fn read_impl(
match header.format {
#[allow(deprecated)]
EnvelopeFormat::PackageJson => Ok(Package::from_json_reader(payload, registry)?),
- #[cfg(feature = "model_unstable")]
EnvelopeFormat::Model | EnvelopeFormat::ModelWithExtensions => {
decode_model(payload, registry, header.format)
}
- #[cfg(not(feature = "model_unstable"))]
- EnvelopeFormat::Model | EnvelopeFormat::ModelWithExtensions => {
- Err(EnvelopeError::FormatUnsupported {
- format: header.format,
- feature: Some("model_unstable"),
- })
- }
}
}
@@ -246,7 +234,6 @@ fn read_impl(
/// - `extension_registry`: An extension registry with additional extensions to use when
/// decoding the HUGR, if they are not already included in the package.
/// - `format`: The format of the payload.
-#[cfg(feature = "model_unstable")]
fn decode_model(
mut stream: impl BufRead,
extension_registry: &ExtensionRegistry,
@@ -286,22 +273,13 @@ fn write_impl(
match config.format {
#[allow(deprecated)]
EnvelopeFormat::PackageJson => package.to_json_writer(writer)?,
- #[cfg(feature = "model_unstable")]
EnvelopeFormat::Model | EnvelopeFormat::ModelWithExtensions => {
encode_model(writer, package, config.format)?
}
- #[cfg(not(feature = "model_unstable"))]
- EnvelopeFormat::Model | EnvelopeFormat::ModelWithExtensions => {
- return Err(EnvelopeError::FormatUnsupported {
- format: config.format,
- feature: Some("model_unstable"),
- })
- }
}
Ok(())
}
-#[cfg(feature = "model_unstable")]
fn encode_model(
mut writer: impl Write,
package: &Package,
@@ -391,7 +369,6 @@ mod tests {
//#[case::empty(Package::default())] // Not currently supported
#[case::simple(simple_package())]
//#[case::multi(multi_module_package())] // Not currently supported
- #[cfg(feature = "model_unstable")]
fn module_exts_roundtrip(#[case] package: Package) {
let mut buffer = Vec::new();
let config = EnvelopeConfig {
@@ -417,15 +394,7 @@ mod tests {
format: EnvelopeFormat::Model,
zstd: None,
};
- let res = package.store(&mut buffer, config);
-
- match cfg!(feature = "model_unstable") {
- true => res.unwrap(),
- false => {
- assert_matches!(res, Err(EnvelopeError::FormatUnsupported { .. }));
- return;
- }
- }
+ package.store(&mut buffer, config).unwrap();
let (decoded_config, new_package) =
read_envelope(BufReader::new(buffer.as_slice()), &PRELUDE_REGISTRY).unwrap();
diff --git a/hugr-core/src/export.rs b/hugr-core/src/export.rs
index 09ccf944c..42e04629b 100644
--- a/hugr-core/src/export.rs
+++ b/hugr-core/src/export.rs
@@ -1,4 +1,5 @@
//! Exporting HUGR graphs to their `hugr-model` representation.
+use crate::hugr::internal::HugrInternals;
use crate::{
extension::{ExtensionId, OpDef, SignatureFunc},
hugr::IdentList,
@@ -94,7 +95,7 @@ struct Context<'a> {
impl<'a> Context<'a> {
pub fn new(hugr: &'a Hugr, bump: &'a Bump) -> Self {
let mut module = table::Module::default();
- module.nodes.reserve(hugr.node_count());
+ module.nodes.reserve(hugr.num_nodes());
let links = Links::new(hugr);
Self {
@@ -831,7 +832,6 @@ impl<'a> Context<'a> {
);
self.make_term(table::Term::List(parts))
}
- TypeArg::Extensions { .. } => self.make_term_apply("compat.ext_set", &[]),
TypeArg::Variable { v } => self.export_type_arg_var(v),
}
}
@@ -938,7 +938,6 @@ impl<'a> Context<'a> {
let types = self.make_term(table::Term::List(parts));
self.make_term_apply(model::CORE_TUPLE_TYPE, &[types])
}
- TypeParam::Extensions => self.make_term_apply("compat.ext_set_type", &[]),
}
}
@@ -999,7 +998,7 @@ impl<'a> Context<'a> {
let outer_hugr = std::mem::replace(&mut self.hugr, hugr);
let outer_node_to_id = std::mem::take(&mut self.node_to_id);
- let region = match hugr.root_type() {
+ let region = match hugr.root_optype() {
OpType::DFG(_) => self.export_dfg(hugr.root(), model::ScopeClosure::Closed),
_ => panic!("Value::Function root must be a DFG"),
};
@@ -1031,7 +1030,7 @@ impl<'a> Context<'a> {
}
pub fn export_node_metadata(&mut self, node: Node) -> &'a [table::TermId] {
- let metadata_map = self.hugr.get_node_metadata(node);
+ let metadata_map = self.hugr.node_metadata_map(node);
let has_order_edges = {
fn is_relevant_node(hugr: &Hugr, node: Node) -> bool {
@@ -1049,13 +1048,11 @@ impl<'a> Context<'a> {
.any(|(other, _)| is_relevant_node(self.hugr, other))
};
- let meta_capacity = metadata_map.map_or(0, |map| map.len()) + has_order_edges as usize;
+ let meta_capacity = metadata_map.len() + has_order_edges as usize;
let mut meta = BumpVec::with_capacity_in(meta_capacity, self.bump);
- if let Some(metadata_map) = metadata_map {
- for (name, value) in metadata_map {
- meta.push(self.export_json_meta(name, value));
- }
+ for (name, value) in metadata_map {
+ meta.push(self.export_json_meta(name, value));
}
if has_order_edges {
@@ -1176,19 +1173,15 @@ mod test {
use crate::{
builder::{Dataflow, DataflowSubContainer},
extension::prelude::qb_t,
- std_extensions::arithmetic::float_types,
types::Signature,
- utils::test_quantum_extension::{self, cx_gate, h_gate},
+ utils::test_quantum_extension::{cx_gate, h_gate},
Hugr,
};
#[fixture]
fn test_simple_circuit() -> Hugr {
crate::builder::test::build_main(
- Signature::new_endo(vec![qb_t(), qb_t()])
- .with_extension_delta(test_quantum_extension::EXTENSION_ID)
- .with_extension_delta(float_types::EXTENSION_ID)
- .into(),
+ Signature::new_endo(vec![qb_t(), qb_t()]).into(),
|mut f_build| {
let wires: Vec<_> = f_build.input_wires().collect();
let mut linear = f_build.as_circuit(wires);
diff --git a/hugr-core/src/extension.rs b/hugr-core/src/extension.rs
index 408c88e15..4300c74ad 100644
--- a/hugr-core/src/extension.rs
+++ b/hugr-core/src/extension.rs
@@ -19,12 +19,11 @@ use derive_more::Display;
use thiserror::Error;
use crate::hugr::IdentList;
-use crate::ops::constant::{ValueName, ValueNameRef};
use crate::ops::custom::{ExtensionOp, OpaqueOp};
-use crate::ops::{self, OpName, OpNameRef};
+use crate::ops::{OpName, OpNameRef};
use crate::types::type_param::{TypeArg, TypeArgError, TypeParam};
use crate::types::RowVariable;
-use crate::types::{check_typevar_decl, CustomType, Substitution, TypeBound, TypeName};
+use crate::types::{CustomType, TypeBound, TypeName};
use crate::types::{Signature, TypeNameRef};
mod const_fold;
@@ -378,6 +377,7 @@ pub static EMPTY_REG: ExtensionRegistry = ExtensionRegistry {
/// TODO: decide on failure modes
#[derive(Debug, Clone, Error, PartialEq, Eq)]
#[allow(missing_docs)]
+#[non_exhaustive]
pub enum SignatureError {
/// Name mismatch
#[error("Definition name ({0}) and instantiation name ({1}) do not match.")]
@@ -496,37 +496,6 @@ impl CustomConcrete for CustomType {
}
}
-/// A constant value provided by a extension.
-/// Must be an instance of a type available to the extension.
-#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
-pub struct ExtensionValue {
- extension: ExtensionId,
- name: ValueName,
- typed_value: ops::Value,
-}
-
-impl ExtensionValue {
- /// Returns a reference to the typed value of this [`ExtensionValue`].
- pub fn typed_value(&self) -> &ops::Value {
- &self.typed_value
- }
-
- /// Returns a mutable reference to the typed value of this [`ExtensionValue`].
- pub(super) fn typed_value_mut(&mut self) -> &mut ops::Value {
- &mut self.typed_value
- }
-
- /// Returns a reference to the name of this [`ExtensionValue`].
- pub fn name(&self) -> &str {
- self.name.as_str()
- }
-
- /// Returns a reference to the extension this [`ExtensionValue`] belongs to.
- pub fn extension(&self) -> &ExtensionId {
- &self.extension
- }
-}
-
/// A unique identifier for a extension.
///
/// The actual [`Extension`] is stored externally.
@@ -578,12 +547,8 @@ pub struct Extension {
pub version: Version,
/// Unique identifier for the extension.
pub name: ExtensionId,
- /// Runtime dependencies this extension has on other extensions.
- pub runtime_reqs: ExtensionSet,
/// Types defined by this extension.
types: BTreeMap,
- /// Static values defined by this extension.
- values: BTreeMap,
/// Operation declarations with serializable definitions.
// Note: serde will serialize this because we configure with `features=["rc"]`.
// That will clone anything that has multiple references, but each
@@ -605,9 +570,7 @@ impl Extension {
Self {
name,
version,
- runtime_reqs: Default::default(),
types: Default::default(),
- values: Default::default(),
operations: Default::default(),
}
}
@@ -663,12 +626,6 @@ impl Extension {
}
}
- /// Extend the runtime requirements of this extension with another set of extensions.
- pub fn add_requirements(&mut self, runtime_reqs: impl Into) {
- let reqs = mem::take(&mut self.runtime_reqs);
- self.runtime_reqs = reqs.union(runtime_reqs.into());
- }
-
/// Allows read-only access to the operations in this Extension
pub fn get_op(&self, name: &OpNameRef) -> Option<&Arc> {
self.operations.get(name)
@@ -679,11 +636,6 @@ impl Extension {
self.types.get(type_name)
}
- /// Allows read-only access to the values in this Extension
- pub fn get_value(&self, value_name: &ValueNameRef) -> Option<&ExtensionValue> {
- self.values.get(value_name)
- }
-
/// Returns the name of the extension.
pub fn name(&self) -> &ExtensionId {
&self.name
@@ -704,25 +656,6 @@ impl Extension {
self.types.iter()
}
- /// Add a named static value to the extension.
- pub fn add_value(
- &mut self,
- name: impl Into,
- typed_value: ops::Value,
- ) -> Result<&mut ExtensionValue, ExtensionBuildError> {
- let extension_value = ExtensionValue {
- extension: self.name.clone(),
- name: name.into(),
- typed_value,
- };
- match self.values.entry(extension_value.name.clone()) {
- btree_map::Entry::Occupied(_) => {
- Err(ExtensionBuildError::ValueExists(extension_value.name))
- }
- btree_map::Entry::Vacant(ve) => Ok(ve.insert(extension_value)),
- }
- }
-
/// Instantiate an [`ExtensionOp`] which references an [`OpDef`] in this extension.
pub fn instantiate_extension_op(
&self,
@@ -783,9 +716,6 @@ pub enum ExtensionBuildError {
/// Existing [`TypeDef`]
#[error("Extension already has an type called {0}.")]
TypeDefExists(TypeName),
- /// Existing [`ExtensionValue`]
- #[error("Extension already has an extension value called {0}.")]
- ValueExists(ValueName),
}
/// A set of extensions identified by their unique [`ExtensionId`].
@@ -795,14 +725,6 @@ pub enum ExtensionBuildError {
#[display("[{}]", _0.iter().join(", "))]
pub struct ExtensionSet(BTreeSet);
-/// A special ExtensionId which indicates that the delta of a non-Function
-/// container node should be computed by extension inference.
-///
-/// See [`infer_extensions`] which lists the container nodes to which this can be applied.
-///
-/// [`infer_extensions`]: crate::hugr::Hugr::infer_extensions
-pub const TO_BE_INFERRED: ExtensionId = ExtensionId::new_unchecked(".TO_BE_INFERRED");
-
impl ExtensionSet {
/// Creates a new empty extension set.
pub const fn new() -> Self {
@@ -814,14 +736,6 @@ impl ExtensionSet {
self.0.insert(extension.clone());
}
- /// Adds a type var (which must have been declared as a [TypeParam::Extensions]) to this set
- pub fn insert_type_var(&mut self, idx: usize) {
- // Represent type vars as string representation of variable index.
- // This is not a legal IdentList or ExtensionId so should not conflict.
- self.0
- .insert(ExtensionId::new_unchecked(idx.to_string().as_str()));
- }
-
/// Returns `true` if the set contains the given extension.
pub fn contains(&self, extension: &ExtensionId) -> bool {
self.0.contains(extension)
@@ -844,14 +758,6 @@ impl ExtensionSet {
set
}
- /// An ExtensionSet containing a single type variable
- /// (which must have been declared as a [TypeParam::Extensions])
- pub fn type_var(idx: usize) -> Self {
- let mut set = Self::new();
- set.insert_type_var(idx);
- set
- }
-
/// Returns the union of two extension sets.
pub fn union(mut self, other: Self) -> Self {
self.0.extend(other.0);
@@ -882,22 +788,6 @@ impl ExtensionSet {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
-
- pub(crate) fn validate(&self, params: &[TypeParam]) -> Result<(), SignatureError> {
- self.iter()
- .filter_map(as_typevar)
- .try_for_each(|var_idx| check_typevar_decl(params, var_idx, &TypeParam::Extensions))
- }
-
- pub(crate) fn substitute(&self, t: &Substitution) -> Self {
- Self::from_iter(self.0.iter().flat_map(|e| match as_typevar(e) {
- None => vec![e.clone()],
- Some(i) => match t.apply_var(i, &TypeParam::Extensions) {
- TypeArg::Extensions{es} => es.iter().cloned().collect::>(),
- _ => panic!("value for type var was not extension set - type scheme should be validated first"),
- },
- }))
- }
}
impl From for ExtensionSet {
@@ -924,16 +814,6 @@ impl<'a> IntoIterator for &'a ExtensionSet {
}
}
-fn as_typevar(e: &ExtensionId) -> Option {
- // Type variables are represented as radix-10 numbers, which are illegal
- // as standard ExtensionIds. Hence if an ExtensionId starts with a digit,
- // we assume it must be a type variable, and fail fast if it isn't.
- match e.chars().next() {
- Some(c) if c.is_ascii_digit() => Some(str::parse(e).unwrap()),
- _ => None,
- }
-}
-
impl FromIterator for ExtensionSet {
fn from_iter>(iter: I) -> Self {
Self(BTreeSet::from_iter(iter))
@@ -1028,16 +908,8 @@ pub mod test {
type Strategy = BoxedStrategy;
fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
- (
- hash_set(0..10usize, 0..3),
- hash_set(any::(), 0..3),
- )
- .prop_map(|(vars, extensions)| {
- ExtensionSet::union_over(
- std::iter::once(extensions.into_iter().collect::())
- .chain(vars.into_iter().map(ExtensionSet::type_var)),
- )
- })
+ hash_set(any::(), 0..3)
+ .prop_map(|extensions| extensions.into_iter().collect::())
.boxed()
}
}
diff --git a/hugr-core/src/extension/declarative.rs b/hugr-core/src/extension/declarative.rs
index 64092981f..14995db27 100644
--- a/hugr-core/src/extension/declarative.rs
+++ b/hugr-core/src/extension/declarative.rs
@@ -149,9 +149,14 @@ impl ExtensionDeclaration {
/// Create an [`Extension`] from this declaration.
pub fn make_extension(
&self,
- imports: &ExtensionSet,
+ _imports: &ExtensionSet,
ctx: DeclarationContext<'_>,
) -> Result, ExtensionDeclarationError> {
+ // TODO: The imports were previously used as runtime extension
+ // requirements for the constructed extension. Now that runtime
+ // extension requirements are removed, they are no longer recorded
+ // anywhere in the `Extension`.
+
Extension::try_new_arc(
self.name.clone(),
// TODO: Get the version as a parameter.
@@ -164,7 +169,6 @@ impl ExtensionDeclaration {
for o in &self.operations {
o.register(ext, ctx, extension_ref)?;
}
- ext.add_requirements(imports.clone());
Ok(())
},
diff --git a/hugr-core/src/extension/declarative/signature.rs b/hugr-core/src/extension/declarative/signature.rs
index b84d56853..e2300956b 100644
--- a/hugr-core/src/extension/declarative/signature.rs
+++ b/hugr-core/src/extension/declarative/signature.rs
@@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize};
use smol_str::SmolStr;
use crate::extension::prelude::PRELUDE_ID;
-use crate::extension::{ExtensionSet, SignatureFunc, TypeDef};
+use crate::extension::{SignatureFunc, TypeDef};
use crate::types::type_param::TypeParam;
use crate::types::{CustomType, FuncValueType, PolyFuncTypeRV, Type, TypeRowRV};
use crate::Extension;
@@ -26,10 +26,6 @@ pub(super) struct SignatureDeclaration {
inputs: Vec,
/// The outputs of the operation.
outputs: Vec,
- /// A set of extensions invoked while running this operation.
- #[serde(default)]
- #[serde(skip_serializing_if = "crate::utils::is_default")]
- extensions: ExtensionSet,
}
impl SignatureDeclaration {
@@ -53,7 +49,6 @@ impl SignatureDeclaration {
let body = FuncValueType {
input: make_type_row(&self.inputs)?,
output: make_type_row(&self.outputs)?,
- runtime_reqs: self.extensions.clone(),
};
let poly_func = PolyFuncTypeRV::new(op_params, body);
diff --git a/hugr-core/src/extension/op_def.rs b/hugr-core/src/extension/op_def.rs
index d5c9a5b5d..48eef663f 100644
--- a/hugr-core/src/extension/op_def.rs
+++ b/hugr-core/src/extension/op_def.rs
@@ -244,11 +244,7 @@ impl SignatureFunc {
// TODO raise warning: https://github.com/CQCL/hugr/issues/1432
SignatureFunc::MissingValidateFunc(ts) => (ts, args),
};
- let mut res = pf.instantiate(args)?;
-
- // Automatically add the extensions where the operation is defined to
- // the runtime requirements of the op.
- res.runtime_reqs.insert(def.extension.clone());
+ let res = pf.instantiate(args)?;
// If there are any row variables left, this will fail with an error:
res.try_into()
@@ -722,8 +718,7 @@ pub(super) mod test {
Ok(Signature::new(
vec![usize_t(); 3],
vec![Type::new_tuple(vec![usize_t(); 3])]
- )
- .with_extension_delta(EXT_ID))
+ ))
);
assert_eq!(def.validate_args(&args, &[]), Ok(()));
@@ -733,10 +728,10 @@ pub(super) mod test {
let args = [TypeArg::BoundedNat { n: 3 }, tyvar.clone().into()];
assert_eq!(
def.compute_signature(&args),
- Ok(
- Signature::new(tyvars.clone(), vec![Type::new_tuple(tyvars)])
- .with_extension_delta(EXT_ID)
- )
+ Ok(Signature::new(
+ tyvars.clone(),
+ vec![Type::new_tuple(tyvars)]
+ ))
);
def.validate_args(&args, &[TypeBound::Copyable.into()])
.unwrap();
@@ -787,14 +782,11 @@ pub(super) mod test {
),
extension_ref,
)?;
- let tv = Type::new_var_use(1, TypeBound::Copyable);
+ let tv = Type::new_var_use(0, TypeBound::Copyable);
let args = [TypeArg::Type { ty: tv.clone() }];
- let decls = [TypeParam::Extensions, TypeBound::Copyable.into()];
+ let decls = [TypeBound::Copyable.into()];
def.validate_args(&args, &decls).unwrap();
- assert_eq!(
- def.compute_signature(&args),
- Ok(Signature::new_endo(tv).with_extension_delta(EXT_ID))
- );
+ assert_eq!(def.compute_signature(&args), Ok(Signature::new_endo(tv)));
// But not with an external row variable
let arg: TypeArg = TypeRV::new_row_var_use(0, TypeBound::Copyable).into();
assert_eq!(
@@ -811,36 +803,6 @@ pub(super) mod test {
Ok(())
}
- #[test]
- fn instantiate_extension_delta() -> Result<(), Box> {
- use crate::extension::prelude::bool_t;
-
- let _ext = Extension::try_new_test_arc(EXT_ID, |ext, extension_ref| {
- let params: Vec = vec![TypeParam::Extensions];
- let db_set = ExtensionSet::type_var(0);
- let fun_ty = Signature::new_endo(bool_t()).with_extension_delta(db_set);
-
- let def = ext.add_op(
- "SimpleOp".into(),
- "".into(),
- PolyFuncTypeRV::new(params.clone(), fun_ty),
- extension_ref,
- )?;
-
- // Concrete extension set
- let es = ExtensionSet::singleton(EXT_ID);
- let exp_fun_ty = Signature::new_endo(bool_t()).with_extension_delta(es.clone());
- let args = [TypeArg::Extensions { es }];
-
- def.validate_args(&args, ¶ms).unwrap();
- assert_eq!(def.compute_signature(&args), Ok(exp_fun_ty));
-
- Ok(())
- })?;
-
- Ok(())
- }
-
mod proptest {
use std::sync::Weak;
diff --git a/hugr-core/src/extension/prelude.rs b/hugr-core/src/extension/prelude.rs
index f88a84a0d..b1e78baf8 100644
--- a/hugr-core/src/extension/prelude.rs
+++ b/hugr-core/src/extension/prelude.rs
@@ -11,7 +11,7 @@ use crate::extension::simple_op::{
try_from_name, MakeExtensionOp, MakeOpDef, MakeRegisteredOp, OpLoadError,
};
use crate::extension::{
- ConstFold, ExtensionId, ExtensionSet, OpDef, SignatureError, SignatureFunc, TypeDefBound,
+ ConstFold, ExtensionId, OpDef, SignatureError, SignatureFunc, TypeDefBound,
};
use crate::ops::constant::{CustomCheckFailure, CustomConst, ValueName};
use crate::ops::OpName;
@@ -245,10 +245,6 @@ impl CustomConst for ConstString {
crate::ops::constant::downcast_equal_consts(self, other)
}
- fn extension_reqs(&self) -> ExtensionSet {
- ExtensionSet::singleton(PRELUDE_ID)
- }
-
fn get_type(&self) -> Type {
string_type()
}
@@ -438,10 +434,6 @@ impl CustomConst for ConstUsize {
crate::ops::constant::downcast_equal_consts(self, other)
}
- fn extension_reqs(&self) -> ExtensionSet {
- ExtensionSet::singleton(PRELUDE_ID)
- }
-
fn get_type(&self) -> Type {
usize_t()
}
@@ -495,9 +487,6 @@ impl CustomConst for ConstError {
crate::ops::constant::downcast_equal_consts(self, other)
}
- fn extension_reqs(&self) -> ExtensionSet {
- ExtensionSet::singleton(PRELUDE_ID)
- }
fn get_type(&self) -> Type {
error_type()
}
@@ -555,9 +544,6 @@ impl CustomConst for ConstExternalSymbol {
crate::ops::constant::downcast_equal_consts(self, other)
}
- fn extension_reqs(&self) -> ExtensionSet {
- ExtensionSet::singleton(PRELUDE_ID)
- }
fn get_type(&self) -> Type {
self.typ.clone()
}
@@ -1068,7 +1054,7 @@ mod test {
let optype: OpType = op.clone().into();
assert_eq!(
optype.dataflow_signature().unwrap().as_ref(),
- &Signature::new_endo(type_row![Type::UNIT]).with_prelude()
+ &Signature::new_endo(type_row![Type::UNIT])
);
let new_op = Barrier::from_extension_op(optype.as_extension_op().unwrap()).unwrap();
@@ -1121,10 +1107,6 @@ mod test {
assert!(error_val.validate().is_ok());
- assert_eq!(
- error_val.extension_reqs(),
- ExtensionSet::singleton(PRELUDE_ID)
- );
assert!(error_val.equal_consts(&ConstError::new(2, "my message")));
assert!(!error_val.equal_consts(&ConstError::new(3, "my message")));
@@ -1181,10 +1163,6 @@ mod test {
let string_const: ConstString = ConstString::new("Lorem ipsum".into());
assert_eq!(string_const.name(), "ConstString(\"Lorem ipsum\")");
assert!(string_const.validate().is_ok());
- assert_eq!(
- string_const.extension_reqs(),
- ExtensionSet::singleton(PRELUDE_ID)
- );
assert!(string_const.equal_consts(&ConstString::new("Lorem ipsum".into())));
assert!(!string_const.equal_consts(&ConstString::new("Lorem ispum".into())));
}
@@ -1206,10 +1184,6 @@ mod test {
assert_eq!(subject.get_type(), Type::UNIT);
assert_eq!(subject.name(), "@foo");
assert!(subject.validate().is_ok());
- assert_eq!(
- subject.extension_reqs(),
- ExtensionSet::singleton(PRELUDE_ID)
- );
assert!(subject.equal_consts(&ConstExternalSymbol::new("foo", Type::UNIT, false)));
assert!(!subject.equal_consts(&ConstExternalSymbol::new("bar", Type::UNIT, false)));
assert!(!subject.equal_consts(&ConstExternalSymbol::new("foo", string_type(), false)));
diff --git a/hugr-core/src/extension/prelude/unwrap_builder.rs b/hugr-core/src/extension/prelude/unwrap_builder.rs
index 06b4e3939..3817d65c8 100644
--- a/hugr-core/src/extension/prelude/unwrap_builder.rs
+++ b/hugr-core/src/extension/prelude/unwrap_builder.rs
@@ -111,10 +111,8 @@ mod tests {
#[test]
fn test_build_unwrap() {
- let mut builder = DFGBuilder::new(
- Signature::new(Type::from(option_type(bool_t())), bool_t()).with_prelude(),
- )
- .unwrap();
+ let mut builder =
+ DFGBuilder::new(Signature::new(Type::from(option_type(bool_t())), bool_t())).unwrap();
let [opt] = builder.input_wires_arr();
diff --git a/hugr-core/src/extension/resolution.rs b/hugr-core/src/extension/resolution.rs
index 90eae9422..a08cbfb38 100644
--- a/hugr-core/src/extension/resolution.rs
+++ b/hugr-core/src/extension/resolution.rs
@@ -9,10 +9,6 @@
//! HUGR nodes and wire types. This is computed from the union of all extension
//! required across the HUGR.
//!
-//! This is distinct from _runtime_ extension requirements, which are defined
-//! more granularly in each function signature by the `runtime_reqs`
-//! field. See the `extension_inference` feature and related modules for that.
-//!
//! Note: These procedures are only temporary until `hugr-model` is stabilized.
//! Once that happens, hugrs will no longer be directly deserialized using serde
//! but instead will be created by the methods in `crate::import`. As these
diff --git a/hugr-core/src/extension/resolution/extension.rs b/hugr-core/src/extension/resolution/extension.rs
index 61adc1dea..05c0faf69 100644
--- a/hugr-core/src/extension/resolution/extension.rs
+++ b/hugr-core/src/extension/resolution/extension.rs
@@ -9,7 +9,7 @@ use std::sync::Arc;
use crate::extension::{Extension, ExtensionId, ExtensionRegistry, OpDef, SignatureFunc, TypeDef};
-use super::types_mut::{resolve_signature_exts, resolve_value_exts};
+use super::types_mut::resolve_signature_exts;
use super::{ExtensionResolutionError, WeakExtensionRegistry};
impl ExtensionRegistry {
@@ -59,14 +59,7 @@ impl Extension {
for type_def in self.types.values_mut() {
resolve_typedef_exts(&self.name, type_def, extensions, &mut used_extensions)?;
}
- for val in self.values.values_mut() {
- resolve_value_exts(
- None,
- val.typed_value_mut(),
- extensions,
- &mut used_extensions,
- )?;
- }
+
let ops = mem::take(&mut self.operations);
for (op_id, mut op_def) in ops {
// TODO: We should be able to clone the definition if needed by using `make_mut`,
diff --git a/hugr-core/src/extension/resolution/test.rs b/hugr-core/src/extension/resolution/test.rs
index 19373b04c..f3ae229ec 100644
--- a/hugr-core/src/extension/resolution/test.rs
+++ b/hugr-core/src/extension/resolution/test.rs
@@ -11,7 +11,7 @@ use crate::builder::{
Container, DFGBuilder, Dataflow, DataflowHugr, DataflowSubContainer, FunctionBuilder,
HugrBuilder, ModuleBuilder,
};
-use crate::extension::prelude::{bool_t, usize_custom_t, usize_t, ConstUsize, PRELUDE_ID};
+use crate::extension::prelude::{bool_t, usize_custom_t, usize_t, ConstUsize};
use crate::extension::resolution::WeakExtensionRegistry;
use crate::extension::resolution::{
resolve_op_extensions, resolve_op_types_extensions, ExtensionCollectionError,
@@ -28,7 +28,7 @@ use crate::std_extensions::arithmetic::int_types::{self, int_type};
use crate::std_extensions::collections::list::ListValue;
use crate::types::type_param::TypeParam;
use crate::types::{PolyFuncType, Signature, Type, TypeArg, TypeBound};
-use crate::{std_extensions, type_row, Extension, Hugr, HugrView};
+use crate::{type_row, Extension, Hugr, HugrView};
#[rstest]
#[case::empty(Input { types: type_row![]}, ExtensionRegistry::default())]
@@ -158,17 +158,7 @@ fn check_extension_resolution(mut hugr: Hugr) {
/// Build a small hugr using the float types extension and check that the extensions are resolved.
#[rstest]
fn resolve_hugr_extensions_simple() {
- let mut build = DFGBuilder::new(
- Signature::new(vec![], vec![float64_type()]).with_extension_delta(
- [
- PRELUDE_ID.to_owned(),
- std_extensions::arithmetic::float_types::EXTENSION_ID.to_owned(),
- ]
- .into_iter()
- .collect::(),
- ),
- )
- .unwrap();
+ let mut build = DFGBuilder::new(Signature::new(vec![], vec![float64_type()])).unwrap();
// A constant op using a non-prelude extension.
let f_const = build.add_load_const(Value::extension(ConstF64::new(f64::consts::PI)));
@@ -218,7 +208,7 @@ fn resolve_hugr_extensions() {
let (ext_b, op_b) = make_extension("dummy.b", "op_b");
let (ext_c, op_c) = make_extension("dummy.c", "op_c");
let (ext_d, op_d) = make_extension("dummy.d", "op_d");
- let (ext_e, op_e) = make_extension("dummy.e", "op_e");
+ let (_ext_e, op_e) = make_extension("dummy.e", "op_e");
let mut module = ModuleBuilder::new();
@@ -234,18 +224,7 @@ fn resolve_hugr_extensions() {
let mut func = module
.define_function(
"dummy_fn",
- Signature::new(vec![float64_type(), bool_t()], vec![]).with_extension_delta(
- [
- ext_a.name(),
- ext_b.name(),
- ext_c.name(),
- ext_d.name(),
- ext_e.name(),
- ]
- .into_iter()
- .cloned()
- .collect::(),
- ),
+ Signature::new(vec![float64_type(), bool_t()], vec![]),
)
.unwrap();
let [func_i0, func_i1] = func.input_wires_arr();
@@ -368,11 +347,7 @@ fn resolve_call() {
let dummy_fn = module.declare("called_fn", dummy_fn_sig).unwrap();
let mut func = module
- .define_function(
- "caller_fn",
- Signature::new(vec![], vec![bool_t()])
- .with_extension_delta(ExtensionSet::from_iter(expected_exts.clone())),
- )
+ .define_function("caller_fn", Signature::new(vec![], vec![bool_t()]))
.unwrap();
let _load_func = func.load_func(&dummy_fn, &[generic_type_1]).unwrap();
let call = func.call(&dummy_fn, &[generic_type_2], vec![]).unwrap();
@@ -390,15 +365,10 @@ fn resolve_call() {
/// Fail when collecting extensions but the weak pointers are not resolved.
#[rstest]
fn dropped_weak_extensions() {
- let (ext_a, op_a) = make_extension("dummy.a", "op_a");
+ let (_ext_a, op_a) = make_extension("dummy.a", "op_a");
let mut func = FunctionBuilder::new(
"dummy_fn",
- Signature::new(vec![float64_type(), bool_t()], vec![]).with_extension_delta(
- [ext_a.name()]
- .into_iter()
- .cloned()
- .collect::(),
- ),
+ Signature::new(vec![float64_type(), bool_t()], vec![]),
)
.unwrap();
let [_func_i0, func_i1] = func.input_wires_arr();
diff --git a/hugr-core/src/extension/resolution/types.rs b/hugr-core/src/extension/resolution/types.rs
index 6094f0aee..28bd6a12b 100644
--- a/hugr-core/src/extension/resolution/types.rs
+++ b/hugr-core/src/extension/resolution/types.rs
@@ -131,8 +131,6 @@ pub(crate) fn collect_signature_exts(
used_extensions: &mut WeakExtensionRegistry,
missing_extensions: &mut ExtensionSet,
) {
- // Note that we do not include the signature's `runtime_reqs` here, as those refer
- // to _runtime_ requirements that we do not be require to be defined.
collect_type_row_exts(&signature.input, used_extensions, missing_extensions);
collect_type_row_exts(&signature.output, used_extensions, missing_extensions);
}
diff --git a/hugr-core/src/extension/resolution/types_mut.rs b/hugr-core/src/extension/resolution/types_mut.rs
index d70d6b861..af5803eff 100644
--- a/hugr-core/src/extension/resolution/types_mut.rs
+++ b/hugr-core/src/extension/resolution/types_mut.rs
@@ -124,8 +124,6 @@ pub(super) fn resolve_signature_exts(
extensions: &WeakExtensionRegistry,
used_extensions: &mut WeakExtensionRegistry,
) -> Result<(), ExtensionResolutionError> {
- // Note that we do not include the signature's `runtime_reqs` here, as those refer
- // to _runtime_ requirements that may not be currently present.
resolve_type_row_exts(node, &mut signature.input, extensions, used_extensions)?;
resolve_type_row_exts(node, &mut signature.output, extensions, used_extensions)?;
Ok(())
diff --git a/hugr-core/src/hugr.rs b/hugr-core/src/hugr.rs
index 2789ae056..16152b298 100644
--- a/hugr-core/src/hugr.rs
+++ b/hugr-core/src/hugr.rs
@@ -4,7 +4,7 @@ pub mod hugrmut;
pub(crate) mod ident;
pub mod internal;
-pub mod rewrite;
+pub mod patch;
pub mod serialize;
pub mod validate;
pub mod views;
@@ -17,20 +17,20 @@ pub(crate) use self::hugrmut::HugrMut;
pub use self::validate::ValidationError;
pub use ident::{IdentList, InvalidIdentifier};
-pub use rewrite::{Rewrite, SimpleReplacement, SimpleReplacementError};
+pub use patch::{Patch, SimpleReplacement, SimpleReplacementError};
use portgraph::multiportgraph::MultiPortGraph;
use portgraph::{Hierarchy, PortMut, PortView, UnmanagedDenseMap};
use thiserror::Error;
-pub use self::views::{HugrView, RootTagged};
+pub use self::views::HugrView;
use crate::core::NodeIndex;
use crate::extension::resolution::{
resolve_op_extensions, resolve_op_types_extensions, ExtensionResolutionError,
WeakExtensionRegistry,
};
-use crate::extension::{ExtensionRegistry, ExtensionSet, TO_BE_INFERRED};
-use crate::ops::{OpTag, OpTrait};
+use crate::extension::{ExtensionRegistry, ExtensionSet};
+use crate::ops::OpTag;
pub use crate::ops::{OpType, DEFAULT_OPTYPE};
use crate::{Direction, Node};
@@ -89,13 +89,29 @@ impl Hugr {
Self::with_capacity(root_node.into(), 0, 0)
}
+ /// Create a new Hugr, with a single root node and preallocated capacity.
+ pub fn with_capacity(root_node: OpType, nodes: usize, ports: usize) -> Self {
+ let mut graph = MultiPortGraph::with_capacity(nodes, ports);
+ let hierarchy = Hierarchy::new();
+ let mut op_types = UnmanagedDenseMap::with_capacity(nodes);
+ let root = graph.add_node(root_node.input_count(), root_node.output_count());
+ let extensions = root_node.used_extensions();
+ op_types[root] = root_node;
+
+ Self {
+ graph,
+ hierarchy,
+ root,
+ op_types,
+ metadata: UnmanagedDenseMap::with_capacity(nodes),
+ extensions: extensions.unwrap_or_default(),
+ }
+ }
+
/// Load a Hugr from a json reader.
///
/// Validates the Hugr against the provided extension registry, ensuring all
/// operations are resolved.
- ///
- /// If the feature `extension_inference` is enabled, we will ensure every function
- /// correctly specifies the extensions required by its contained ops.
pub fn load_json(
reader: impl Read,
extension_registry: &ExtensionRegistry,
@@ -103,87 +119,11 @@ impl Hugr {
let mut hugr: Hugr = serde_json::from_reader(reader)?;
hugr.resolve_extension_defs(extension_registry)?;
- hugr.validate_no_extensions()?;
-
- if cfg!(feature = "extension_inference") {
- hugr.infer_extensions(false)?;
- hugr.validate_extensions()?;
- }
+ hugr.validate()?;
Ok(hugr)
}
- /// Infers an extension-delta for any non-function container node
- /// whose current [extension_delta] contains [TO_BE_INFERRED]. The inferred delta
- /// will be the smallest delta compatible with its children and that includes any
- /// other [ExtensionId]s in the current delta.
- ///
- /// If `remove` is true, for such container nodes *without* [TO_BE_INFERRED],
- /// ExtensionIds are removed from the delta if they are *not* used by any child node.
- ///
- /// The non-function container nodes are:
- /// [Case], [CFG], [Conditional], [DataflowBlock], [DFG], [TailLoop]
- ///
- /// [Case]: crate::ops::Case
- /// [CFG]: crate::ops::CFG
- /// [Conditional]: crate::ops::Conditional
- /// [DataflowBlock]: crate::ops::DataflowBlock
- /// [DFG]: crate::ops::DFG
- /// [TailLoop]: crate::ops::TailLoop
- /// [extension_delta]: crate::ops::OpType::extension_delta
- /// [ExtensionId]: crate::extension::ExtensionId
- pub fn infer_extensions(&mut self, remove: bool) -> Result<(), ExtensionError> {
- fn delta_mut(optype: &mut OpType) -> Option<&mut ExtensionSet> {
- match optype {
- OpType::DFG(dfg) => Some(&mut dfg.signature.runtime_reqs),
- OpType::DataflowBlock(dfb) => Some(&mut dfb.extension_delta),
- OpType::TailLoop(tl) => Some(&mut tl.extension_delta),
- OpType::CFG(cfg) => Some(&mut cfg.signature.runtime_reqs),
- OpType::Conditional(c) => Some(&mut c.extension_delta),
- OpType::Case(c) => Some(&mut c.signature.runtime_reqs),
- //OpType::Lift(_) // Not ATM: only a single element, and we expect Lift to be removed
- //OpType::FuncDefn(_) // Not at present due to the possibility of recursion
- _ => None,
- }
- }
- fn infer(h: &mut Hugr, node: Node, remove: bool) -> Result {
- let mut child_sets = h
- .children(node)
- .collect::>() // Avoid borrowing h over recursive call
- .into_iter()
- .map(|ch| Ok((ch, infer(h, ch, remove)?)))
- .collect::, _>>()?;
-
- let Some(es) = delta_mut(h.op_types.get_mut(node.pg_index())) else {
- return Ok(h.get_optype(node).extension_delta());
- };
- if es.contains(&TO_BE_INFERRED) {
- // Do not remove anything from current delta - any other elements are a lower bound
- child_sets.push((node, es.clone())); // "child_sets" now misnamed but we discard fst
- } else if remove {
- child_sets.iter().try_for_each(|(ch, ch_exts)| {
- if !es.is_superset(ch_exts) {
- return Err(ExtensionError {
- parent: node,
- parent_extensions: es.clone(),
- child: *ch,
- child_extensions: ch_exts.clone(),
- });
- }
- Ok(())
- })?;
- } else {
- return Ok(es.clone()); // Can't neither add nor remove, so nothing to do
- }
- let merged = ExtensionSet::union_over(child_sets.into_iter().map(|(_, e)| e));
- *es = ExtensionSet::singleton(TO_BE_INFERRED).missing_from(&merged);
-
- Ok(es.clone())
- }
- infer(self, self.root(), remove)?;
- Ok(())
- }
-
/// Given a Hugr that has been deserialized, collect all extensions used to
/// define the HUGR while resolving all [`OpType::OpaqueOp`] operations into
/// [`OpType::ExtensionOp`]s and updating the extension pointer in all
@@ -195,11 +135,6 @@ impl Hugr {
/// to define the HUGR nodes and wire types. This is computed from the union
/// of all extension required across the HUGR.
///
- /// This is distinct from _runtime_ extension requirements computed in
- /// [`Hugr::infer_extensions`], which are computed more granularly in each
- /// function signature by the `runtime_reqs` field and define the set
- /// of capabilities required by the runtime to execute each function.
- ///
/// Updates the internal extension registry with the extensions used in the
/// definition.
///
@@ -260,31 +195,6 @@ impl Hugr {
/// Internal API for HUGRs, not intended for use by users.
impl Hugr {
- /// Create a new Hugr, with a single root node and preallocated capacity.
- pub(crate) fn with_capacity(root_node: OpType, nodes: usize, ports: usize) -> Self {
- let mut graph = MultiPortGraph::with_capacity(nodes, ports);
- let hierarchy = Hierarchy::new();
- let mut op_types = UnmanagedDenseMap::with_capacity(nodes);
- let root = graph.add_node(root_node.input_count(), root_node.output_count());
- let extensions = root_node.used_extensions();
- op_types[root] = root_node;
-
- Self {
- graph,
- hierarchy,
- root,
- op_types,
- metadata: UnmanagedDenseMap::with_capacity(nodes),
- extensions: extensions.unwrap_or_default(),
- }
- }
-
- /// Set the root node of the hugr.
- pub(crate) fn set_root(&mut self, root: Node) {
- self.hierarchy.detach(self.root);
- self.root = root.pg_index();
- }
-
/// Add a node to the graph.
pub(crate) fn add_node(&mut self, nodetype: OpType) -> Node {
let node = self
@@ -322,7 +232,7 @@ impl Hugr {
/// preserve the indices.
pub fn canonicalize_nodes(&mut self, mut rekey: impl FnMut(Node, Node)) {
// Generate the ordered list of nodes
- let mut ordered = Vec::with_capacity(self.node_count());
+ let mut ordered = Vec::with_capacity(self.num_nodes());
let root = self.root();
ordered.extend(self.as_mut().canonical_order(root));
@@ -339,8 +249,8 @@ impl Hugr {
let target: Node = portgraph::NodeIndex::new(position).into();
if target != source {
- let pg_target = target.pg_index();
- let pg_source = source.pg_index();
+ let pg_target = target.into_portgraph();
+ let pg_source = source.into_portgraph();
self.graph.swap_nodes(pg_target, pg_source);
self.op_types.swap(pg_target, pg_source);
self.hierarchy.swap_nodes(pg_target, pg_source);
@@ -367,13 +277,10 @@ pub struct ExtensionError {
}
/// Errors that can occur while manipulating a Hugr.
-///
-/// TODO: Better descriptions, not just re-exporting portgraph errors.
#[derive(Debug, Clone, PartialEq, Eq, Error)]
#[non_exhaustive]
pub enum HugrError {
/// The node was not of the required [OpTag]
- /// (e.g. to conform to the [RootTagged::RootHandle] of a [HugrView])
#[error("Invalid tag: required a tag in {required} but found {actual}")]
#[allow(missing_docs)]
InvalidTag { required: OpTag, actual: OpTag },
@@ -402,73 +309,13 @@ pub enum LoadHugrError {
#[cfg(test)]
mod test {
- use std::sync::Arc;
use std::{fs::File, io::BufReader};
- use super::internal::HugrMutInternals;
- #[cfg(feature = "extension_inference")]
- use super::ValidationError;
- use super::{ExtensionError, Hugr, HugrMut, HugrView, Node};
- use crate::extension::{ExtensionId, ExtensionSet, PRELUDE_REGISTRY, TO_BE_INFERRED};
- use crate::ops::{ExtensionOp, OpName};
- use crate::types::type_param::TypeParam;
- use crate::types::{
- FuncValueType, PolyFuncTypeRV, Signature, Type, TypeArg, TypeBound, TypeRV, TypeRow,
- };
-
- use crate::{const_extension_ids, ops, test_file, type_row, Extension};
- use cool_asserts::assert_matches;
- use lazy_static::lazy_static;
- use rstest::rstest;
-
- const_extension_ids! {
- pub(crate) const LIFT_EXT_ID: ExtensionId = "LIFT_EXT_ID";
- }
- lazy_static! {
- /// Tests only extension holding an Op that can add arbitrary extensions to a row.
- pub(crate) static ref LIFT_EXT: Arc = {
- Extension::new_arc(
- LIFT_EXT_ID,
- hugr::extension::Version::new(0, 0, 0),
- |ext, extension_ref| {
- ext.add_op(
- OpName::new_inline("Lift"),
- "".into(),
- PolyFuncTypeRV::new(
- vec![TypeParam::Extensions, TypeParam::new_list(TypeBound::Any)],
- FuncValueType::new_endo(TypeRV::new_row_var_use(1, TypeBound::Any))
- .with_extension_delta(ExtensionSet::type_var(0)),
- ),
- extension_ref,
- )
- .unwrap();
- },
- )
- };
- }
+ use super::{Hugr, HugrView};
+ use crate::extension::PRELUDE_REGISTRY;
- pub(crate) fn lift_op(
- type_row: impl Into,
- extensions: impl Into,
- ) -> ExtensionOp {
- LIFT_EXT
- .instantiate_extension_op(
- "Lift",
- [
- TypeArg::Extensions {
- es: extensions.into(),
- },
- TypeArg::Sequence {
- elems: type_row
- .into()
- .iter()
- .map(|t| TypeArg::Type { ty: t.clone() })
- .collect(),
- },
- ],
- )
- .unwrap()
- }
+ use crate::test_file;
+ use cool_asserts::assert_matches;
#[test]
fn impls_send_and_sync() {
@@ -531,164 +378,4 @@ mod test {
);
assert_matches!(&hugr, Ok(_));
}
-
- const_extension_ids! {
- const XA: ExtensionId = "EXT_A";
- const XB: ExtensionId = "EXT_B";
- }
-
- #[rstest]
- #[case([], XA.into())]
- #[case([XA], XA.into())]
- #[case([XB], ExtensionSet::from_iter([XA, XB]))]
-
- fn infer_single_delta(
- #[case] parent: impl IntoIterator
- ,
- #[values(true, false)] remove: bool, // makes no difference when inferring
- #[case] result: ExtensionSet,
- ) {
- let parent = ExtensionSet::from_iter(parent).union(TO_BE_INFERRED.into());
- let (mut h, _) = build_ext_dfg(parent);
- h.infer_extensions(remove).unwrap();
- assert_eq!(h, build_ext_dfg(result.union(LIFT_EXT_ID.into())).0);
- }
-
- #[test]
- fn infer_removes_from_delta() {
- let parent = ExtensionSet::from_iter([XA, XB, LIFT_EXT_ID]);
- let mut h = build_ext_dfg(parent.clone()).0;
- let backup = h.clone();
- h.infer_extensions(false).unwrap();
- assert_eq!(h, backup); // did nothing
- h.infer_extensions(true).unwrap();
- assert_eq!(
- h,
- build_ext_dfg(ExtensionSet::from_iter([XA, LIFT_EXT_ID])).0
- );
- }
-
- #[test]
- fn infer_bad_remove() {
- let (mut h, mid) = build_ext_dfg(XB.into());
- let backup = h.clone();
- h.infer_extensions(false).unwrap();
- assert_eq!(h, backup); // did nothing
- let val_res = h.validate();
- let expected_err = ExtensionError {
- parent: h.root(),
- parent_extensions: XB.into(),
- child: mid,
- child_extensions: ExtensionSet::from_iter([XA, LIFT_EXT_ID]),
- };
- #[cfg(feature = "extension_inference")]
- assert_eq!(
- val_res,
- Err(ValidationError::ExtensionError(expected_err.clone()))
- );
- #[cfg(not(feature = "extension_inference"))]
- assert!(val_res.is_ok());
-
- let inf_res = h.infer_extensions(true);
- assert_eq!(inf_res, Err(expected_err));
- }
-
- fn build_ext_dfg(parent: ExtensionSet) -> (Hugr, Node) {
- let ty = Type::new_function(Signature::new_endo(type_row![]));
- let mut h = Hugr::new(ops::DFG {
- signature: Signature::new_endo(ty.clone()).with_extension_delta(parent.clone()),
- });
- let root = h.root();
- let mid = add_inliftout(&mut h, root, ty);
- (h, mid)
- }
-
- fn add_inliftout(h: &mut Hugr, p: Node, ty: Type) -> Node {
- let inp = h.add_node_with_parent(
- p,
- ops::Input {
- types: ty.clone().into(),
- },
- );
- let out = h.add_node_with_parent(
- p,
- ops::Output {
- types: ty.clone().into(),
- },
- );
- let mid = h.add_node_with_parent(p, lift_op(ty, XA));
- h.connect(inp, 0, mid, 0);
- h.connect(mid, 0, out, 0);
- mid
- }
-
- #[rstest]
- // Base case success: delta inferred for parent equals grandparent.
- #[case([XA], [TO_BE_INFERRED], true, [XA])]
- // Success: delta inferred for parent is subset of grandparent
- #[case([XA, XB], [TO_BE_INFERRED], true, [XA])]
- // Base case failure: infers [XA] for parent but grandparent has disjoint set
- #[case([XB], [TO_BE_INFERRED], false, [XA])]
- // Failure: as previous, but extra "lower bound" on parent that has no effect
- #[case([XB], [XA, TO_BE_INFERRED], false, [XA])]
- // Failure: grandparent ok wrt. child but parent specifies extra lower-bound XB
- #[case([XA], [XB, TO_BE_INFERRED], false, [XA, XB])]
- // Success: grandparent includes extra XB required for parent's "lower bound"
- #[case([XA, XB], [XB, TO_BE_INFERRED], true, [XA, XB])]
- // Success: grandparent is also inferred so can include 'extra' XB from parent
- #[case([TO_BE_INFERRED], [TO_BE_INFERRED, XB], true, [XA, XB])]
- // No inference: extraneous XB in parent is removed so all become [XA].
- #[case([XA], [XA, XB], true, [XA])]
- fn infer_three_generations(
- #[case] grandparent: impl IntoIterator
- ,
- #[case] parent: impl IntoIterator
- ,
- #[case] success: bool,
- #[case] result: impl IntoIterator
- ,
- ) {
- let ty = Type::new_function(Signature::new_endo(type_row![]));
- let grandparent = ExtensionSet::from_iter(grandparent).union(LIFT_EXT_ID.into());
- let parent = ExtensionSet::from_iter(parent).union(LIFT_EXT_ID.into());
- let result = ExtensionSet::from_iter(result).union(LIFT_EXT_ID.into());
- let root_ty = ops::Conditional {
- sum_rows: vec![type_row![]],
- other_inputs: ty.clone().into(),
- outputs: ty.clone().into(),
- extension_delta: grandparent.clone(),
- };
- let mut h = Hugr::new(root_ty.clone());
- let p = h.add_node_with_parent(
- h.root(),
- ops::Case {
- signature: Signature::new_endo(ty.clone()).with_extension_delta(parent),
- },
- );
- add_inliftout(&mut h, p, ty.clone());
- assert!(h.validate_extensions().is_err());
- let backup = h.clone();
- let inf_res = h.infer_extensions(true);
- if success {
- assert!(inf_res.is_ok());
- let expected_p = ops::Case {
- signature: Signature::new_endo(ty).with_extension_delta(result.clone()),
- };
- let mut expected = backup;
- expected.replace_op(p, expected_p).unwrap();
- let expected_gp = ops::Conditional {
- extension_delta: result,
- ..root_ty
- };
- expected.replace_op(h.root(), expected_gp).unwrap();
-
- assert_eq!(h, expected);
- } else {
- assert_eq!(
- inf_res,
- Err(ExtensionError {
- parent: h.root(),
- parent_extensions: grandparent,
- child: p,
- child_extensions: result
- })
- );
- }
- }
}
diff --git a/hugr-core/src/hugr/hugrmut.rs b/hugr-core/src/hugr/hugrmut.rs
index f3ef094be..7805d3c67 100644
--- a/hugr-core/src/hugr/hugrmut.rs
+++ b/hugr-core/src/hugr/hugrmut.rs
@@ -1,22 +1,24 @@
//! Low-level interface for modifying a HUGR.
use core::panic;
-use std::collections::{BTreeMap, HashMap};
+use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
use std::sync::Arc;
use portgraph::view::{NodeFilter, NodeFiltered};
use portgraph::{LinkMut, PortMut, PortView, SecondaryMap};
+use crate::core::HugrNode;
use crate::extension::ExtensionRegistry;
+use crate::hugr::internal::HugrInternals;
use crate::hugr::views::SiblingSubgraph;
-use crate::hugr::{HugrView, Node, OpType, RootTagged};
-use crate::hugr::{NodeMetadata, Rewrite};
+use crate::hugr::{HugrView, Node, OpType};
+use crate::hugr::{NodeMetadata, Patch};
use crate::ops::OpTrait;
use crate::types::Substitution;
use crate::{Extension, Hugr, IncomingPort, OutgoingPort, Port, PortIndex};
use super::internal::HugrMutInternals;
-use super::NodeMetadataMap;
+use super::views::{panic_invalid_node, panic_invalid_non_root, panic_invalid_port};
/// Functions for low-level building of a HUGR.
pub trait HugrMut: HugrMutInternals {
@@ -25,17 +27,7 @@ pub trait HugrMut: HugrMutInternals {
/// # Panics
///
/// If the node is not in the graph.
- fn get_metadata_mut(&mut self, node: Node, key: impl AsRef) -> &mut NodeMetadata {
- panic_invalid_node(self, node);
- let node_meta = self
- .hugr_mut()
- .metadata
- .get_mut(node.pg_index())
- .get_or_insert_with(Default::default);
- node_meta
- .entry(key.as_ref())
- .or_insert(serde_json::Value::Null)
- }
+ fn get_metadata_mut(&mut self, node: Self::Node, key: impl AsRef) -> &mut NodeMetadata;
/// Sets a metadata value associated with a node.
///
@@ -44,44 +36,17 @@ pub trait HugrMut: HugrMutInternals {
/// If the node is not in the graph.
fn set_metadata(
&mut self,
- node: Node,
+ node: Self::Node,
key: impl AsRef,
metadata: impl Into,
- ) {
- let entry = self.get_metadata_mut(node, key);
- *entry = metadata.into();
- }
+ );
/// Remove a metadata entry associated with a node.
///
/// # Panics
///
/// If the node is not in the graph.
- fn remove_metadata(&mut self, node: Node, key: impl AsRef) {
- panic_invalid_node(self, node);
- let node_meta = self.hugr_mut().metadata.get_mut(node.pg_index());
- if let Some(node_meta) = node_meta {
- node_meta.remove(key.as_ref());
- }
- }
-
- /// Retrieve the complete metadata map for a node.
- fn take_node_metadata(&mut self, node: Self::Node) -> Option {
- if !self.valid_node(node) {
- return None;
- }
- self.hugr_mut().metadata.take(node.pg_index())
- }
-
- /// Overwrite the complete metadata map for a node.
- ///
- /// # Panics
- ///
- /// If the node is not in the graph.
- fn overwrite_node_metadata(&mut self, node: Node, metadata: Option) {
- panic_invalid_node(self, node);
- self.hugr_mut().metadata.set(node.pg_index(), metadata);
- }
+ fn remove_metadata(&mut self, node: Self::Node, key: impl AsRef);
/// Add a node to the graph with a parent in the hierarchy.
///
@@ -90,11 +55,7 @@ pub trait HugrMut: HugrMutInternals {
/// # Panics
///
/// If the parent is not in the graph.
- #[inline]
- fn add_node_with_parent(&mut self, parent: Node, op: impl Into) -> Node {
- panic_invalid_node(self, parent);
- self.hugr_mut().add_node_with_parent(parent, op)
- }
+ fn add_node_with_parent(&mut self, parent: Self::Node, op: impl Into) -> Self::Node;
/// Add a node to the graph as the previous sibling of another node.
///
@@ -103,11 +64,7 @@ pub trait HugrMut: HugrMutInternals {
/// # Panics
///
/// If the sibling is not in the graph, or if the sibling is the root node.
- #[inline]
- fn add_node_before(&mut self, sibling: Node, nodetype: impl Into) -> Node {
- panic_invalid_non_root(self, sibling);
- self.hugr_mut().add_node_before(sibling, nodetype)
- }
+ fn add_node_before(&mut self, sibling: Self::Node, nodetype: impl Into) -> Self::Node;
/// Add a node to the graph as the next sibling of another node.
///
@@ -116,11 +73,7 @@ pub trait HugrMut: HugrMutInternals {
/// # Panics
///
/// If the sibling is not in the graph, or if the sibling is the root node.
- #[inline]
- fn add_node_after(&mut self, sibling: Node, op: impl Into) -> Node {
- panic_invalid_non_root(self, sibling);
- self.hugr_mut().add_node_after(sibling, op)
- }
+ fn add_node_after(&mut self, sibling: Self::Node, op: impl Into) -> Self::Node;
/// Remove a node from the graph and return the node weight.
/// Note that if the node has children, they are not removed; this leaves
@@ -129,24 +82,14 @@ pub trait HugrMut: HugrMutInternals {
/// # Panics
///
/// If the node is not in the graph, or if the node is the root node.
- #[inline]
- fn remove_node(&mut self, node: Node) -> OpType {
- panic_invalid_non_root(self, node);
- self.hugr_mut().remove_node(node)
- }
+ fn remove_node(&mut self, node: Self::Node) -> OpType;
/// Remove a node from the graph, along with all its descendants in the hierarchy.
///
/// # Panics
///
/// If the node is not in the graph, or is the root (this would leave an empty Hugr).
- fn remove_subtree(&mut self, node: Node) {
- panic_invalid_non_root(self, node);
- while let Some(ch) = self.first_child(node) {
- self.remove_subtree(ch)
- }
- self.hugr_mut().remove_node(node);
- }
+ fn remove_subtree(&mut self, node: Self::Node);
/// Copies the strict descendants of `root` to under the `new_parent`, optionally applying a
/// [Substitution] to the [OpType]s of the copied nodes.
@@ -162,32 +105,23 @@ pub trait HugrMut: HugrMutInternals {
/// correspondingly for `Dom` edges)
fn copy_descendants(
&mut self,
- root: Node,
- new_parent: Node,
+ root: Self::Node,
+ new_parent: Self::Node,
subst: Option,
- ) -> BTreeMap {
- panic_invalid_node(self, root);
- panic_invalid_node(self, new_parent);
- self.hugr_mut().copy_descendants(root, new_parent, subst)
- }
+ ) -> BTreeMap;
/// Connect two nodes at the given ports.
///
/// # Panics
///
/// If either node is not in the graph or if the ports are invalid.
- #[inline]
fn connect(
&mut self,
- src: Node,
+ src: Self::Node,
src_port: impl Into,
- dst: Node,
+ dst: Self::Node,
dst_port: impl Into,
- ) {
- panic_invalid_node(self, src);
- panic_invalid_node(self, dst);
- self.hugr_mut().connect(src, src_port, dst, dst_port);
- }
+ );
/// Disconnects all edges from the given port.
///
@@ -196,11 +130,7 @@ pub trait HugrMut: HugrMutInternals {
/// # Panics
///
/// If the node is not in the graph, or if the port is invalid.
- #[inline]
- fn disconnect(&mut self, node: Node, port: impl Into) {
- panic_invalid_node(self, node);
- self.hugr_mut().disconnect(node, port);
- }
+ fn disconnect(&mut self, node: Self::Node, port: impl Into);
/// Adds a non-dataflow edge between two nodes. The kind is given by the
/// operation's [`OpTrait::other_input`] or [`OpTrait::other_output`].
@@ -213,35 +143,27 @@ pub trait HugrMut: HugrMutInternals {
/// # Panics
///
/// If the node is not in the graph, or if the port is invalid.
- fn add_other_edge(&mut self, src: Node, dst: Node) -> (OutgoingPort, IncomingPort) {
- panic_invalid_node(self, src);
- panic_invalid_node(self, dst);
- self.hugr_mut().add_other_edge(src, dst)
- }
+ fn add_other_edge(&mut self, src: Self::Node, dst: Self::Node) -> (OutgoingPort, IncomingPort);
- /// Insert another hugr into this one, under a given root node.
+ /// Insert another hugr into this one, under a given parent node.
///
/// # Panics
///
/// If the root node is not in the graph.
- #[inline]
- fn insert_hugr(&mut self, root: Node, other: Hugr) -> InsertionResult {
- panic_invalid_node(self, root);
- self.hugr_mut().insert_hugr(root, other)
- }
+ fn insert_hugr(&mut self, root: Self::Node, other: Hugr) -> InsertionResult;
- /// Copy another hugr into this one, under a given root node.
+ /// Copy another hugr into this one, under a given parent node.
///
/// # Panics
///
/// If the root node is not in the graph.
- #[inline]
- fn insert_from_view(&mut self, root: Node, other: &impl HugrView) -> InsertionResult {
- panic_invalid_node(self, root);
- self.hugr_mut().insert_from_view(root, other)
- }
+ fn insert_from_view(
+ &mut self,
+ root: Self::Node,
+ other: &H,
+ ) -> InsertionResult;
- /// Copy a subgraph from another hugr into this one, under a given root node.
+ /// Copy a subgraph from another hugr into this one, under a given parent node.
///
/// Sibling order is not preserved.
///
@@ -255,18 +177,15 @@ pub trait HugrMut: HugrMutInternals {
// TODO: Try to preserve the order when possible? We cannot always ensure
// it, since the subgraph may have arbitrary nodes without including their
// parent.
- fn insert_subgraph(
+ fn insert_subgraph(
&mut self,
- root: Node,
- other: &impl HugrView,
- subgraph: &SiblingSubgraph,
- ) -> HashMap {
- panic_invalid_node(self, root);
- self.hugr_mut().insert_subgraph(root, other, subgraph)
- }
+ root: Self::Node,
+ other: &H,
+ subgraph: &SiblingSubgraph,
+ ) -> HashMap;
- /// Applies a rewrite to the graph.
- fn apply_rewrite(&mut self, rw: impl Rewrite) -> Result
+ /// Applies a patch to the graph.
+ fn apply_patch(&mut self, rw: impl Patch) -> Result
where
Self: Sized,
{
@@ -279,9 +198,7 @@ pub trait HugrMut: HugrMutInternals {
/// These can be queried using [`HugrView::extensions`].
///
/// See [`ExtensionRegistry::register_updated`] for more information.
- fn use_extension(&mut self, extension: impl Into>) {
- self.hugr_mut().extensions.register_updated(extension);
- }
+ fn use_extension(&mut self, extension: impl Into>);
/// Extend the set of extensions used by the hugr with the extensions in the
/// registry.
@@ -294,69 +211,103 @@ pub trait HugrMut: HugrMutInternals {
/// See [`ExtensionRegistry::register_updated`] for more information.
fn use_extensions(&mut self, registry: impl IntoIterator
- )
where
- ExtensionRegistry: Extend,
- {
- self.hugr_mut().extensions.extend(registry);
- }
-
- /// Returns a mutable reference to the extension registry for this hugr.
- fn extensions_mut(&mut self) -> &mut ExtensionRegistry {
- &mut self.hugr_mut().extensions
- }
+ ExtensionRegistry: Extend;
}
/// Records the result of inserting a Hugr or view
/// via [HugrMut::insert_hugr] or [HugrMut::insert_from_view].
-pub struct InsertionResult {
+///
+/// Contains a map from the nodes in the source HUGR to the nodes in the
+/// target HUGR, using their respective `Node` types.
+pub struct InsertionResult {
/// The node, after insertion, that was the root of the inserted Hugr.
///
/// That is, the value in [InsertionResult::node_map] under the key that was the [HugrView::root]
- pub new_root: Node,
+ pub new_root: TargetN,
/// Map from nodes in the Hugr/view that was inserted, to their new
/// positions in the Hugr into which said was inserted.
- pub node_map: HashMap,
+ pub node_map: HashMap,
}
-fn translate_indices(
+/// Translate a portgraph node index map into a map from nodes in the source
+/// HUGR to nodes in the target HUGR.
+///
+/// This is as a helper in `insert_hugr` and `insert_subgraph`, where the source
+/// HUGR may be an arbitrary `HugrView` with generic node types.
+fn translate_indices(
+ mut source_node: impl FnMut(portgraph::NodeIndex) -> N,
+ mut target_node: impl FnMut(portgraph::NodeIndex) -> Node,
node_map: HashMap,
-) -> impl Iterator
- {
- node_map.into_iter().map(|(k, v)| (k.into(), v.into()))
+) -> impl Iterator
- {
+ node_map
+ .into_iter()
+ .map(move |(k, v)| (source_node(k), target_node(v)))
}
/// Impl for non-wrapped Hugrs. Overwrites the recursive default-impls to directly use the hugr.
-impl + AsMut> HugrMut for T {
+impl HugrMut for Hugr {
+ fn get_metadata_mut(&mut self, node: Self::Node, key: impl AsRef) -> &mut NodeMetadata {
+ panic_invalid_node(self, node);
+ self.node_metadata_map_mut(node)
+ .entry(key.as_ref())
+ .or_insert(serde_json::Value::Null)
+ }
+
+ fn set_metadata(
+ &mut self,
+ node: Self::Node,
+ key: impl AsRef,
+ metadata: impl Into,
+ ) {
+ let entry = self.get_metadata_mut(node, key);
+ *entry = metadata.into();
+ }
+
+ fn remove_metadata(&mut self, node: Self::Node, key: impl AsRef) {
+ panic_invalid_node(self, node);
+ let node_meta = self.node_metadata_map_mut(node);
+ node_meta.remove(key.as_ref());
+ }
+
fn add_node_with_parent(&mut self, parent: Node, node: impl Into) -> Node {
let node = self.as_mut().add_node(node.into());
- self.as_mut()
- .hierarchy
- .push_child(node.pg_index(), parent.pg_index())
+ self.hierarchy
+ .push_child(node.into_portgraph(), parent.into_portgraph())
.expect("Inserting a newly-created node into the hierarchy should never fail.");
node
}
fn add_node_before(&mut self, sibling: Node, nodetype: impl Into) -> Node {
let node = self.as_mut().add_node(nodetype.into());
- self.as_mut()
- .hierarchy
- .insert_before(node.pg_index(), sibling.pg_index())
+ self.hierarchy
+ .insert_before(node.into_portgraph(), sibling.into_portgraph())
.expect("Inserting a newly-created node into the hierarchy should never fail.");
node
}
fn add_node_after(&mut self, sibling: Node, op: impl Into) -> Node {
let node = self.as_mut().add_node(op.into());
- self.as_mut()
- .hierarchy
- .insert_after(node.pg_index(), sibling.pg_index())
+ self.hierarchy
+ .insert_after(node.into_portgraph(), sibling.into_portgraph())
.expect("Inserting a newly-created node into the hierarchy should never fail.");
node
}
fn remove_node(&mut self, node: Node) -> OpType {
panic_invalid_non_root(self, node);
- self.as_mut().hierarchy.remove(node.pg_index());
- self.as_mut().graph.remove_node(node.pg_index());
- self.as_mut().op_types.take(node.pg_index())
+ self.hierarchy.remove(node.into_portgraph());
+ self.graph.remove_node(node.into_portgraph());
+ self.op_types.take(node.into_portgraph())
+ }
+
+ fn remove_subtree(&mut self, node: Node) {
+ panic_invalid_non_root(self, node);
+ let mut queue = VecDeque::new();
+ queue.push_back(node);
+ while let Some(n) = queue.pop_front() {
+ queue.extend(self.children(n));
+ self.remove_node(n);
+ }
}
fn connect(
@@ -370,12 +321,11 @@ impl + AsMut> HugrMut for T
let dst_port = dst_port.into();
panic_invalid_port(self, src, src_port);
panic_invalid_port(self, dst, dst_port);
- self.as_mut()
- .graph
+ self.graph
.link_nodes(
- src.pg_index(),
+ src.into_portgraph(),
src_port.index(),
- dst.pg_index(),
+ dst.into_portgraph(),
dst_port.index(),
)
.expect("The ports should exist at this point.");
@@ -386,11 +336,10 @@ impl + AsMut> HugrMut for T
let offset = port.pg_offset();
panic_invalid_port(self, node, port);
let port = self
- .as_mut()
.graph
- .port_index(node.pg_index(), offset)
+ .port_index(node.into_portgraph(), offset)
.expect("The port should exist at this point.");
- self.as_mut().graph.unlink_port(port);
+ self.graph.unlink_port(port);
}
fn add_other_edge(&mut self, src: Node, dst: Node) -> (OutgoingPort, IncomingPort) {
@@ -406,90 +355,127 @@ impl + AsMut> HugrMut for T
(src_port, dst_port)
}
- fn insert_hugr(&mut self, root: Node, mut other: Hugr) -> InsertionResult {
- let (new_root, node_map) = insert_hugr_internal(self.as_mut(), root, &other);
+ fn insert_hugr(
+ &mut self,
+ root: Self::Node,
+ mut other: Hugr,
+ ) -> InsertionResult {
+ let (new_root, node_map) = insert_hugr_internal(self, root, &other);
// Update the optypes and metadata, taking them from the other graph.
//
// No need to compute each node's extensions here, as we merge `other.extensions` directly.
for (&node, &new_node) in node_map.iter() {
let optype = other.op_types.take(node);
- self.as_mut().op_types.set(new_node, optype);
+ self.op_types.set(new_node, optype);
let meta = other.metadata.take(node);
- self.as_mut().metadata.set(new_node, meta);
+ self.metadata.set(new_node, meta);
}
debug_assert_eq!(
- Some(&new_root.pg_index()),
- node_map.get(&other.root().pg_index())
+ Some(&new_root.into_portgraph()),
+ node_map.get(&other.root().into_portgraph())
);
InsertionResult {
new_root,
- node_map: translate_indices(node_map).collect(),
+ node_map: translate_indices(
+ |n| other.from_portgraph_node(n),
+ |n| self.from_portgraph_node(n),
+ node_map,
+ )
+ .collect(),
}
}
- fn insert_from_view(&mut self, root: Node, other: &impl HugrView) -> InsertionResult {
- let (new_root, node_map) = insert_hugr_internal(self.as_mut(), root, other);
+ fn insert_from_view(
+ &mut self,
+ root: Self::Node,
+ other: &H,
+ ) -> InsertionResult {
+ let (new_root, node_map) = insert_hugr_internal(self, root, other);
// Update the optypes and metadata, copying them from the other graph.
//
// No need to compute each node's extensions here, as we merge `other.extensions` directly.
for (&node, &new_node) in node_map.iter() {
- let nodetype = other.get_optype(other.get_node(node));
- self.as_mut().op_types.set(new_node, nodetype.clone());
- let meta = other.base_hugr().metadata.get(node);
- self.as_mut().metadata.set(new_node, meta.clone());
+ let node = other.from_portgraph_node(node);
+ let nodetype = other.get_optype(node);
+ self.op_types.set(new_node, nodetype.clone());
+ let meta = other.node_metadata_map(node);
+ if !meta.is_empty() {
+ self.metadata.set(new_node, Some(meta.clone()));
+ }
}
debug_assert_eq!(
- Some(&new_root.pg_index()),
- node_map.get(&other.get_pg_index(other.root()))
+ Some(&new_root.into_portgraph()),
+ node_map.get(&other.to_portgraph_node(other.root()))
);
InsertionResult {
new_root,
- node_map: translate_indices(node_map).collect(),
+ node_map: translate_indices(
+ |n| other.from_portgraph_node(n),
+ |n| self.from_portgraph_node(n),
+ node_map,
+ )
+ .collect(),
}
}
- fn insert_subgraph(
+ fn insert_subgraph(
&mut self,
- root: Node,
- other: &impl HugrView,
- subgraph: &SiblingSubgraph,
- ) -> HashMap {
+ root: Self::Node,
+ other: &H,
+ subgraph: &SiblingSubgraph,
+ ) -> HashMap {
// Create a portgraph view with the explicit list of nodes defined by the subgraph.
- let portgraph: NodeFiltered<_, NodeFilter<&[Node]>, &[Node]> =
+ let context: HashSet = subgraph
+ .nodes()
+ .iter()
+ .map(|&n| other.to_portgraph_node(n))
+ .collect();
+ let portgraph: NodeFiltered<_, NodeFilter>, _> =
NodeFiltered::new_node_filtered(
other.portgraph(),
- |node, ctx| ctx.contains(&node.into()),
- subgraph.nodes(),
+ |node, ctx| ctx.contains(&node),
+ context,
);
- let node_map = insert_subgraph_internal(self.as_mut(), root, other, &portgraph);
+ let node_map = insert_subgraph_internal(self, root, other, &portgraph);
// Update the optypes and metadata, copying them from the other graph.
for (&node, &new_node) in node_map.iter() {
- let nodetype = other.get_optype(other.get_node(node));
- self.as_mut().op_types.set(new_node, nodetype.clone());
- let meta = other.base_hugr().metadata.get(node);
- self.as_mut().metadata.set(new_node, meta.clone());
+ let node = other.from_portgraph_node(node);
+ let nodetype = other.get_optype(node);
+ self.op_types.set(new_node, nodetype.clone());
+ let meta = other.node_metadata_map(node);
+ if !meta.is_empty() {
+ self.metadata.set(new_node, Some(meta.clone()));
+ }
// Add the required extensions to the registry.
if let Ok(exts) = nodetype.used_extensions() {
self.use_extensions(exts);
}
}
- translate_indices(node_map).collect()
+ translate_indices(
+ |n| other.from_portgraph_node(n),
+ |n| self.from_portgraph_node(n),
+ node_map,
+ )
+ .collect()
}
fn copy_descendants(
&mut self,
- root: Node,
- new_parent: Node,
+ root: Self::Node,
+ new_parent: Self::Node,
subst: Option