Skip to content

core: (Constraints) more complex AnyOf simplification#6084

Open
alexarice wants to merge 3 commits into
mainfrom
alexarice/any-of-any-of
Open

core: (Constraints) more complex AnyOf simplification#6084
alexarice wants to merge 3 commits into
mainfrom
alexarice/any-of-any-of

Conversation

@alexarice

Copy link
Copy Markdown
Collaborator

Some more complex simplification of AnyOf constraints.

I'm not sure I'm happy with this setup with adding the extra merge helper function, but it could be helpful for extending this in the future if wanted.

Code is a bit messy so would welcome any nitpicking

@alexarice alexarice requested a review from superlopuh May 14, 2026 14:49
@alexarice alexarice self-assigned this May 14, 2026
@alexarice alexarice added the core xDSL core (ir, textual format, ...) label May 14, 2026
@codecov

codecov Bot commented May 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.87%. Comparing base (aef4ae6) to head (a2919a0).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #6084   +/-   ##
=======================================
  Coverage   86.86%   86.87%           
=======================================
  Files         428      429    +1     
  Lines       64264    64311   +47     
  Branches     7374     7383    +9     
=======================================
+ Hits        55825    55870   +45     
- Misses       6874     6875    +1     
- Partials     1565     1566    +1     

☔ View full report in Codecov by Harness.
📢 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.

Comment thread xdsl/irdl/constraints.py
return
raise VerifyException(f"Unexpected attribute {attr}")

def __or__(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why the rename? is it because you'd like to make merge variadic later? I feel like using | is pretty

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It's not a renaming, | is still there. merge is different because it can fail.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh, then I feel like it would be nice to add more to the doc string as motivation, as I'm not sure that I get the purpose. Is the idea for | to use the merged output if possible and fall back to AnyOf if that fails? Isn't this kinda what already happens in the code?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the return below could just return super.__or__(self, other) instead, right?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The purpose is purely to merge ParamAttrConstraints together in an AnyOf. I agree that's not obvious from the naming and will happily take suggestions. I actively don't want to fall back to AnyOf here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The alternative is to inline the logic into the loop of AnyOf.get but pyright was getting really angry with ParamAttrConstraint[Unknown]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

OK sorry let me actually properly read the code now

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

OK I think I get it now. I would still like to avoid this merge method if possible, although I now understand its purpose better. I'll have a think about it as currently I have no good suggestions. My gut tells me that we might be able to leverage the init better, or maybe rethink the init of this constraint (and the internal storage) A part of the idea here is whether the AnyOf is actually just an AnyOf of length one, right? Couldn't we construct the AnyOf, and then check whether it could actually be represented by a single constraint? I'm not 100% sure of the details of how this would work, curious if you think it's promising.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I'm not sure this is related to the length 1 thing. The idea is that you have a list of constraints, and some of these may be "mergable" ParamAttrConstraints (i.e. same base and have at most 1 differing parameter constraint)

AnyOf.get then goes through its constraints and for each constraint, it tries to "merge" it with all the constraints it's seen before. If the merge succeeds, we replace both constraints with the merged one, and if not we leave both in the AnyOf.

I think I've maybe made things messier by combining this with unrolling nested AnyOf's. In any case I don't like the code I've written so definitely need to polish it up.

Comment thread xdsl/irdl/constraints.py
@alexarice

Copy link
Copy Markdown
Collaborator Author

@superlopuh should I split this up?

@superlopuh

Copy link
Copy Markdown
Member

Sorry I thought you were planning to play with this some more. I haven't really had the mental bandwidth to look at this properly, if you're not blocked on this then having another few days to take a look would be great.

@alexarice

Copy link
Copy Markdown
Collaborator Author

I think I'll split off the easier bit anyway, because that can't be a bad thing. I'm not blocked on any of this, but I did promise to get the ParamAttrConstraint merging in

@superlopuh

Copy link
Copy Markdown
Member

Just to double check, this .get is fully addressing this comment, right? #6056 (comment)

@alexarice

Copy link
Copy Markdown
Collaborator Author

This does implement that functionality yes. (This is what this .merge function is doing)

@alexarice

Copy link
Copy Markdown
Collaborator Author

Just thought I'd add an update here. I haven't had time to work on this much but my current thinking is that it might be cleaner for the main building function be something that adds a single element to an existing AnyOf. This would fit better with how we usually build these constraints as:

constr1 | constr2 | constr3

and I think it will be cleaner code.

@superlopuh

Copy link
Copy Markdown
Member

That would be great, in the discussion above you mentioned that this wasn't always possible. I think it might still be preferable to it not working at all for the time being.

@superlopuh

Copy link
Copy Markdown
Member

@alexarice what's your plan/timeline here? Will you have time to work on it this week or is it more of a post-CGO thing?

@alexarice

Copy link
Copy Markdown
Collaborator Author

My CGO deadline is fine. It's my POPL deadlines that I'm stressing for. I certainly won't have time this week, but could schedule some time to tackle it next week?

@alexarice

Copy link
Copy Markdown
Collaborator Author

I had a look at this and have kind of been defeated by trying to do this in a nicer way.

@superlopuh

Copy link
Copy Markdown
Member

Yeah it's tough. I'll try to take a look at this later this week, I think some way that works is better than nothing.

@alexarice

Copy link
Copy Markdown
Collaborator Author

I had hoped to remove AnyOf.attr_constrs and just make the init deal with the other three fields, but we depend on attr_constrs for hashing apparently

@alexarice

Copy link
Copy Markdown
Collaborator Author

I think the idea here is ok, if we can find a better name than merge for "try to combine these constraints into a single one"

@superlopuh

Copy link
Copy Markdown
Member

As per our chat on Zulip, I think relax_constraint would be nice here

Comment thread xdsl/irdl/constraints.py
Comment on lines +151 to +152
self, other: AttrConstraint[AttributeCovT]
) -> AttrConstraint[AttributeCovT] | None:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

How do you feel about this?

Suggested change
self, other: AttrConstraint[AttributeCovT]
) -> AttrConstraint[AttributeCovT] | None:
self, other: Self
) -> Self | None:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Feels like a useful restriction to me

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Also, feels like adding this separately might be useful, with a dedicated test for relaxing parametrized attribute constraints? That way we know that we're testing this functionality separately from the AnyOf stuff.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm also wondering whether the default implementation should be an equality check, returning self if self == other, feels like this would be a good discussion for a focussed PR.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I haven't looked at this code in a while but at the point we use relax_constraint we don't know if the two types are the same. I feel if we went down this route it would be better just to hardcode the logic for ParamAttrConstraint. To be honest I can't remember why I didn't do this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hmm, I see what you mean. Let's forget about the Self stuff. To me it feels like it's fine as-is in this case.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Actually I still feel like adding this in a separate PR might be worth it, just to make things a little cleaner. I would also probably add the return self if self == other else None default implementation.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just so that we're on the same page, I meant adding the changes highlighted in this comment in a different PR, adding the function here and on ParamAttrConstraint, adding the relevant tests, and then adding the AnyOf simplification + tests in a different PR. LMK if you feel like this kind of split doesn't make sense.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I'm on the same page, and this makes sense, but it is not my priority at the moment.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry, forgot about POPL, not urgent on my end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core xDSL core (ir, textual format, ...)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants