Skip to content

feat: Introduce new enum for constant folding; deprecate Value::Function #2060

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 18 commits into
base: acl/insert_hugr_defns
Choose a base branch
from

Conversation

acl-cqc
Copy link
Contributor

@acl-cqc acl-cqc commented Apr 4, 2025

We've been using ops::Value for constant-folding, which is a bit of a shortcut but leads to significant problems: the result of LoadFunction cannot fit into a Value (you'd need to copy all other external functions used by the loaded one inside it, or something - not really practical, and you've lost the understanding that you were calling another function in the same Hugr, too). #2059 solved this inside dataflow analysis, but this extends the approach to constant folding, by allowing to feeding "function pointers" (from LoadFunction) into constant-folding.

The "solution" of extending Value to allow a reference to a node in the containing Hugr was considered in #1856 and was roundly rejected. Instead, this PR adds a separate enum FoldVal that looks quite similar to Value but adds those references/function-pointers.

I've taken the liberty of not including nested Hugrs in FoldVal, but rather deprecating Value::Function in favour of getting front-ends to lift these into their own FuncDefn's in the Hugr. I could be persuaded not to, and add a nested-Hugr variant to FoldVal, if we really want, but it does seem like probably more effort than it's worth - does anyone really have a good use case for Value::Function ?

I've also deprecated the old ConstantFolder trait; deprecating a method in a trait only triggers a warning when you call it, not when you implement it, and we'd want people to move to implementing the new method.

However, currently stuck on:

  • FoldVal's need to be able to report their type to convert themselves into Values (for SumType). I think a better scheme here would be to use Sum<T> from dataflow, and to remove the SumType from that, but that migration doesn't look very graceful :-(
  • Custom constants like ListValue cause trouble as they contain Value - so, no lists of function pointers. This'll be somewhat messy too.
  • So maybe it's better to wait for hugr-model's improved constants...

closes: #2087, #1856

Base automatically changed from acl/dataflow_call_indirect to release-rs-v0.16.0 April 16, 2025 10:11
Copy link

codecov bot commented Apr 23, 2025

Codecov Report

Attention: Patch coverage is 85.44304% with 46 lines in your changes missing coverage. Please review.

Project coverage is 82.36%. Comparing base (23f784f) to head (9474c8b).
Report is 14 commits behind head on acl/insert_hugr_defns.

Files with missing lines Patch % Lines
...e/src/std_extensions/collections/list/list_fold.rs 78.08% 14 Missing and 2 partials ⚠️
hugr-core/src/extension/op_def.rs 25.00% 12 Missing ⚠️
hugr-core/src/extension/const_fold.rs 91.95% 6 Missing and 1 partial ⚠️
hugr-passes/src/const_fold/value_handle.rs 73.68% 5 Missing ⚠️
hugr-core/src/extension/prelude.rs 0.00% 2 Missing ⚠️
hugr-core/src/extension/prelude/generic.rs 87.50% 0 Missing and 1 partial ⚠️
hugr-core/src/std_extensions/logic.rs 96.66% 1 Missing ⚠️
hugr-passes/src/const_fold.rs 96.42% 1 Missing ⚠️
hugr-passes/src/replace_types/handlers.rs 97.67% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@                    Coverage Diff                    @@
##           acl/insert_hugr_defns    #2060      +/-   ##
=========================================================
+ Coverage                  82.18%   82.36%   +0.18%     
=========================================================
  Files                        239      240       +1     
  Lines                      43081    43770     +689     
  Branches                   38991    39680     +689     
=========================================================
+ Hits                       35405    36052     +647     
- Misses                      5708     5753      +45     
+ Partials                    1968     1965       -3     
Flag Coverage Δ
python 85.40% <ø> (ø)
rust 82.05% <85.44%> (+0.20%) ⬆️

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

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

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

@aborgna-q aborgna-q force-pushed the release-rs-v0.16.0 branch from 56c110c to 9cd24ff Compare May 7, 2025 10:54
Base automatically changed from release-rs-v0.16.0 to main May 7, 2025 11:02
@acl-cqc acl-cqc force-pushed the acl/foldval2 branch 2 times, most recently from eaaa3c6 to d0571af Compare June 3, 2025 17:59
@acl-cqc acl-cqc changed the base branch from main to acl/insert_hugr_defns June 3, 2025 17:59
Copy link

codspeed-hq bot commented Jun 3, 2025

CodSpeed Performance Report

Merging #2060 will not alter performance

Comparing acl/foldval2 (9474c8b) with acl/insert_hugr_defns (81b0f4c)

Summary

✅ 21 untouched benchmarks

@acl-cqc acl-cqc requested review from zrho and ss2165 June 9, 2025 08:56
@acl-cqc acl-cqc marked this pull request as ready for review June 9, 2025 08:57
@acl-cqc acl-cqc requested a review from a team as a code owner June 9, 2025 08:57
Copy link
Member

@ss2165 ss2165 left a comment

Choose a reason for hiding this comment

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

Initial thoughts.
There is a lot of deprecation overhead here, not sure how much is worthwhile. If the fold2 names are kept they may need to become deprecated aliases in the breaking release

/// Representation of values used for constant folding.
/// See [ConstFold], which is used as `dyn` so we cannot parametrize by
/// [HugrNode](crate::core::HugrNode).
// Should we be non-exhaustive??
Copy link
Member

Choose a reason for hiding this comment

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

Don't think so, "Extension" should be covering the points of extension

tag: usize,
/// Describes the type of the whole value.
// Can we deprecate this immediately? It is only for converting to Value
sum_type: SumType,
Copy link
Member

Choose a reason for hiding this comment

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

Could move these fields to an inner struct and mark them private i.e. Sum(SumVal)

/// A constant value defined by an extension
Extension(OpaqueValue),
/// A function pointer loaded from a [FuncDefn](crate::ops::FuncDefn) or `FuncDecl`
LoadedFunction(Node, Vec<TypeArg>), // Deliberately skipping Function(Box<Hugr>) ATM
Copy link
Member

Choose a reason for hiding this comment

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

do we need non_exhaustive for Function(Box<Hugr>), or a stub implementation that errors?

}
}

/// Extract the specified type of [CustomConst] fro this instance, if it is one
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// Extract the specified type of [CustomConst] fro this instance, if it is one
/// Extract the specified type of [CustomConst] for this instance, if it is one

}

impl TryFrom<FoldVal> for Value {
type Error = Option<Node>;
Copy link
Member

Choose a reason for hiding this comment

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

please add docstring to explain error type

///
/// Defaults to calling [Self::fold] with those arguments that can be converted ---
/// [FoldVal::LoadedFunction]s will be lost as these are not representable as [Value]s.
fn fold2(&self, type_args: &[TypeArg], inputs: &[FoldVal], outputs: &mut [FoldVal]) {
Copy link
Member

Choose a reason for hiding this comment

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

why does this follow a mutable output pattern? Would some other process have set some values already that this one would leave unchanged?

Comment on lines +517 to +518
.map(TestVal::to_value)
.map(FoldVal::from)
Copy link
Member

Choose a reason for hiding this comment

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

seems to make more sense to update to_value to go directly to FoldVal?

@acl-cqc acl-cqc marked this pull request as draft June 10, 2025 16:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Expose result of LoadFunction into constant folding
2 participants