fix(TreeBuilder::build_conflict): resolve not-really conflicts (left and right agree) #188

Closed
ada4a wants to merge 6 commits from ada4a:not_really_a_conflict into main
Owner

depends on #187

fixes #170 (see there for motivation and discussion)

depends on #187 fixes #170 (see there for motivation and discussion)
add a type alias
All checks were successful
/ test (pull_request) Successful in 47s
6e0e867add
ada4a force-pushed not_really_a_conflict from 67cf86a8d5 to 4b8b38c9a9 2025-02-03 20:04:26 +01:00 Compare
ada4a force-pushed not_really_a_conflict from 4b8b38c9a9 to 679c0eabd2 2025-02-03 20:06:21 +01:00 Compare
ada4a changed title from fix(TreeBuilder::build_conflict): resolve non-really conflicts (left and right agree) to fix(TreeBuilder::build_conflict): resolve not-really conflicts (left and right agree) 2025-02-03 20:49:43 +01:00
ada4a force-pushed not_really_a_conflict from 679c0eabd2 to 14366323e4 2025-02-03 20:49:54 +01:00 Compare
ada4a force-pushed not_really_a_conflict from 14366323e4 to 353e4c95c8 2025-02-04 11:18:29 +01:00 Compare
ada4a force-pushed not_really_a_conflict from 353e4c95c8 to 8a11b6f32a 2025-02-04 11:18:56 +01:00 Compare
explain the test a bit
All checks were successful
/ test (pull_request) Successful in 46s
f100d1813c
Author
Owner

WIP'd because I think there's another solution: #170 (comment)

WIP'd because I think there's another solution: https://codeberg.org/mergiraf/mergiraf/issues/170#issuecomment-2680689
ada4a changed title from fix(TreeBuilder::build_conflict): resolve not-really conflicts (left and right agree) to WIP: fix(TreeBuilder::build_conflict): resolve not-really conflicts (left and right agree) 2025-02-04 11:51:32 +01:00
ada4a changed title from WIP: fix(TreeBuilder::build_conflict): resolve not-really conflicts (left and right agree) to fix(TreeBuilder::build_conflict): resolve not-really conflicts (left and right agree) 2025-02-11 19:06:50 +01:00
Author
Owner

The last commit could be a separate PR

The last commit could be a separate PR
@ -451,0 +451,4 @@
debug_assert!(
list_left.len() <= 1,
"I don't really know what it means for these lists to have more than one element"
Owner

Do we agree that it's clear that list_left can be of length more than outside of this if block, for any conflict that has more than a single element on the left-hand side?
Then, I think list_left can very well still be of length more than one inside the if. That would happen when the tree matching heuristic failed to match not just one pair of left/right elements, but multiple elements (consecutive children of the same parent).

Do we agree that it's clear that `list_left` can be of length more than outside of this `if` block, for any conflict that has more than a single element on the left-hand side? Then, I think `list_left` can very well still be of length more than one inside the `if`. That would happen when the tree matching heuristic failed to match not just one pair of left/right elements, but multiple elements (consecutive children of the same parent).
Author
Owner

Do we agree that it's clear that list_left can be of length more than outside of this if block, for any conflict that has more than a single element on the left-hand side?

I'm not sure I completely understand you. You probably meant "list_left can be of length more than one outside of this if block"? If yes, then... sure, that sounds right.

Then, I think list_left can very well still be of length more than one inside the if. That would happen when the tree matching heuristic failed to match not just one pair of left/right elements, but multiple elements (consecutive children of the same parent).

Ohh, I think I understand it now. Each list is, well, a list of PCS nodes, starting from a given divergence point (where we started to build the conflict) to a point where the two given revisions converge again?

As I said, as I was writing the comment, I didn't really understand what any of this meant. Funnily enough, now that I do get it, the comments in extract_conflict_side look pretty obvious. I guess that's just the curse of knowledge, and I'll try to rewrite the comment so that it's actually helpful to someone who isn't already familiar with the method.

But back to the question. I now agree that the lists may well be of length 1+ (but surely not 0 -- otherwise we wouldn't have called build_conflict in the first place, no?) EDIT: nevermind, both sides could've removed their node, so their corresponding lists can in fact both end up being empty. So I guess this is really similar to what we do at

Lines 244 to 260 in cabfdd6
if let PCSNode::Node { node: leader, .. } = node {
if let Some(commutative_parent) = self
.lang_profile
.get_commutative_parent(leader.grammar_name())
{
let solved_conflict = self.resolve_commutative_conflict(
conflict,
commutative_parent,
visiting_state,
)?;
children.extend(solved_conflict);
} else {
children.push(conflict);
}
} else {
children.push(conflict);
}

after we get the conflict - we can either manage to resolve it, in which case we children.extend(resolved), or don't, in which case we children.push(conflict). But that's only done on conflicts that turn out to be commutative -- I think we should add similar logic for when it's not. Or rather, expand resolve_commutative_conflict so that it also checks for isomorphic left and right sides (and returns Vec<MergedTree> if they are) before continuing on with the rest of its logic. We could rename it to try_resolve_conflict to reflect the fact that it now handles all the cases where a conflict can be resolved.

> Do we agree that it's clear that `list_left` can be of length more than outside of this `if` block, for any conflict that has more than a single element on the left-hand side? I'm not sure I completely understand you. You probably meant "`list_left` can be of length more than **one** outside of this `if` block"? If yes, then... sure, that sounds right. > Then, I think `list_left` can very well still be of length more than one inside the `if`. That would happen when the tree matching heuristic failed to match not just one pair of left/right elements, but multiple elements (consecutive children of the same parent). Ohh, I think I understand it now. Each `list` is, well, a list of PCS nodes, starting from a given divergence point (where we started to build the conflict) to a point where the two given revisions converge again? As I said, as I was writing the comment, I didn't really understand what any of this meant. Funnily enough, now that I do get it, the comments in `extract_conflict_side` look pretty obvious. I guess that's just the curse of knowledge, and I'll try to rewrite the comment so that it's actually helpful to someone who isn't already familiar with the method. But back to the question. I now agree that the lists may well be of length ~1+ (but surely not 0 -- otherwise we wouldn't have called `build_conflict` in the first place, no?)~ EDIT: nevermind, both sides could've removed their node, so their corresponding lists can in fact both end up being empty. So I guess this is really similar to what we do at https://codeberg.org/mergiraf/mergiraf/src/commit/cabfdd6c2ad4d266d19b63eee438c0a2f72acbd1/src/tree_builder.rs#L244-L260 after we get the conflict - we can either manage to resolve it, in which case we `children.extend(resolved)`, or don't, in which case we `children.push(conflict)`. But that's only done on conflicts that turn out to be commutative -- I think we should add similar logic for when it's not. Or rather, expand `resolve_commutative_conflict` so that it also checks for isomorphic left and right sides (and returns `Vec<MergedTree>` if they are) before continuing on with the rest of its logic. We could rename it to `try_resolve_conflict` to reflect the fact that it now handles all the cases where a conflict can be resolved.
misc: use let-else
All checks were successful
/ test (pull_request) Successful in 47s
917051ff87
similar to the "1 successor" branch
Author
Owner

This PR's history has become kind of messy. I'll wait for your response, and, if you agree with my proposal, will open a new PR to implement it

This PR's history has become kind of messy. I'll wait for your response, and, if you agree with my proposal, will open a new PR to implement it
Author
Owner

@ada4a wrote in #188 (comment):

The last commit could be a separate PR

done, see #203

@ada4a wrote in https://codeberg.org/mergiraf/mergiraf/pulls/188#issuecomment-2812480: > The last commit could be a separate PR done, see #203
Author
Owner

@ada4a wrote in #188 (comment):

This PR's history has become kind of messy. I'll wait for your response, and, if you agree with my proposal, will open a new PR to implement it

I went ahead and did that already, so that you can see what I have in mind

@ada4a wrote in https://codeberg.org/mergiraf/mergiraf/pulls/188#issuecomment-2814479: > This PR's history has become kind of messy. I'll wait for your response, and, if you agree with my proposal, will open a new PR to implement it I went ahead and did that already, so that you can see what I have in mind
Owner

Superseded by #204.

Superseded by #204.
wetneb closed this pull request 2025-02-15 11:15:01 +01:00
ada4a deleted branch not_really_a_conflict 2025-02-15 11:24:33 +01:00
All checks were successful
/ test (pull_request) Successful in 47s

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: mergiraf/mergiraf#188
No description provided.