Skip to content

Conversation

@ppolesiuk
Copy link
Member

This PR refactors the implementation of subeffecting constraint simplification. The changes can be summarized as follows.

  • Introduced internal representation of constraints used by the simplification algorithm.
  • The simplification process is explicitly divided to several rules that can be combined used some combinators represented as higher-order functions.
  • Irrelevant constraints are recognized.
  • Added simplification rule: variant variables with no upper-bound are set to the join of their lower bounds.
  • Added simplification rule: redundant constraints are removed.

This commit refactors the implementation of subeffecting constraint
simplification. The changes can be summarized as follows.
- Introduced internal representation of constraints used by the
  simplification algorithm.
- The simplification process is explicitly divided to several rules that
  can be combined used some combinators represented as higher-order
  functions.
- Irrelevant constraints are recognized.
- Added simplification rule: variant variables with no upper-bound are
  set to the join of their lower bounds.
- Added simplification rule: redundant constraints are removed.
Copilot finished reviewing on behalf of ppolesiuk November 16, 2025 12:14
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors the constraint simplification algorithm for subeffecting constraints, introducing a cleaner internal representation and adding new simplification rules to improve the constraint solving process.

  • Introduced internal constraint representation with explicit effect variables and formulas, separating the simplification algorithm into composable rules
  • Added new simplification rules: variant variables with no upper-bound are set to the join of lower bounds, and redundant constraints are removed
  • Enhanced API with compare functions for type variables and generalizable variables, and added functions to remove variables from effects

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/Lang/ConEPriv/TVar.mli Added compare function for type variables to support ordering
src/Lang/ConEPriv/Effct.mli Added GVar.compare for ordering and remove_tvar/remove_gvar functions for variable removal from effects
src/Lang/ConEPriv/Effct.ml Implemented remove operations for both map types, exposed GVar.Ordered module, and added remove_tvar/remove_gvar effect operations
src/Lang/ConE.mli Exposed new comparison and removal functions in the public API
src/EffectInference/ConstrSimplify.ml Complete refactoring of constraint simplification with new internal representation, expanded state tracking, and four composable simplification rules with proper iteration control

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@ppolesiuk ppolesiuk requested a review from Copilot November 16, 2025 12:31
Copilot finished reviewing on behalf of ppolesiuk November 16, 2025 12:34
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Collaborator

@Foxinio Foxinio left a comment

Choose a reason for hiding this comment

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

I think this needs minor changes for future programmers reading this code

Comment on lines 97 to 100
let get_gvar eff =
match T.Effct.view eff with
| ([], [(gv, p)]) when IncrSAT.Formula.is_true p -> gv
| _ -> assert false
Copy link
Collaborator

Choose a reason for hiding this comment

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

This function seems super unsafe. While I guess it is used correctly and is a nice shorthand wherever it's needed, I have three problems with it.

  1. It's used in so few places, there it can be replaced with a safer variant.
  2. If it was to fail, it should provide a better error description than assertion failed.
  3. While right now I believe it is used correctly, in the future it is bound to be used by someone who doesn't fully understand what it does.

Copy link
Member Author

Choose a reason for hiding this comment

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

True. But it don't see how this "safer variant" could look like. To solve this issue, I could write explicitly the invariant maintained in the algorithm that guarantees that all calls to this function are safe. The error message can be improved too.

| GVar of T.effct

(** Internal representation of a (normalized) constraint. *)
type constr =
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe I would add to documentation of this module, description that normalized constraint is always a relevant one.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think that this is important. The representation of normalized constraints admits irrelevant constraints, and none of the implemented simplification rules require only relevant constraints on its input. Irrelevant constraints are separated from relevant ones as an optimization, and no other parts of the implementation assumes that this optimization is enabled.

mutable pgvs : T.GVar.Set.t;
mutable ngvs : T.GVar.Set.t;
mutable irr : Constr.t list (** Irrelevant constraints. *)
{ scope : Scope.t;
Copy link
Collaborator

Choose a reason for hiding this comment

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

in my opinion this should be called outer_scope, it would be longer to write, but it wouldn't bring up any wrong ideas.

Copy link
Member Author

Choose a reason for hiding this comment

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

I disagree. I looked at the code again, and it seems that there is a convention to call the outer scope just scope in all places related to generalization (see for instance Lang.ConE.Type.collect_gvars). However, I can add a few comments that reminds that the scope means "outer scope".

@ppolesiuk ppolesiuk requested a review from Foxinio November 19, 2025 21:19
Copy link
Member

@forell forell left a comment

Choose a reason for hiding this comment

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

I really like the outcome of this refactor. I pointed out one comment that could be clarified, but otherwise I think these changes are good to go.

Comment on lines 270 to 271
[eff], or to [None] if it has multiple upper-bounds, or bounds are not
clear. Variables that have no upper-bound are not present in the map. *)
Copy link
Member

Choose a reason for hiding this comment

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

Before reading the implementation, it's unclear what is meant by "bounds are not clear" in this comment.

@ppolesiuk
Copy link
Member Author

After the discussion with @Foxinio we agreed that the outer_scope issue should be resolved as a separate PR, that should update the name consequently through the entire code of DBL, and I promise to prepare it in coming days.

@forell @Foxinio do you think that we can merge this PR now?

@ppolesiuk ppolesiuk requested a review from forell November 21, 2025 18:12
Copy link
Collaborator

@Foxinio Foxinio left a comment

Choose a reason for hiding this comment

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

I'm very happy with how these changes turned out

@ppolesiuk ppolesiuk merged commit 6ea4ab8 into master Nov 23, 2025
2 checks passed
@ppolesiuk ppolesiuk deleted the constr-simplify branch November 23, 2025 18:06
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.

4 participants