fix: Avoid displaying spurious conflicts #371

Merged
wetneb merged 8 commits from wetneb/mergiraf:356-spurious-conflicts into main 2025-05-10 21:11:47 +02:00
Owner

Fixes #356.

Not including the original case as integration test case because I didn't manage to minimize it sufficiently. I think the unit test is enough.

Fixes #356. Not including the original case as integration test case because I didn't manage to minimize it sufficiently. I think the unit test is enough.
Owner

Hm, I don't think this is the right approach to the problem – it's of course nice (especially for the end user) to graciously handle these spurious conflicts, but imo we should try to find the reason such conflicts appear in the first place, like with #170

Hm, I don't think this is the right approach to the problem – it's of course nice (especially for the end user) to graciously handle these spurious conflicts, but imo we should try to find the reason such conflicts appear in the first place, like with #170
Owner

Or maybe we could merge this as is, and then I could investigate the issue when I have time?

Or maybe we could merge this as is, and then I could investigate the issue when I have time?
Author
Owner

I agree that it feels unsatisfactory to have this check at such a downstream case, but to me it's a legitimate safety belt to add. Conflicts with identical sides can be created in at least two places:

  • when dealing with isomorphic nodes that are unmatched for one reason or another, in merged_tree.rs. We could add another check for isomorphism there, it's true (for now we only detect the left == right case there too). It's not clear to me if it would be much more efficient
  • but also in the highlighting of duplicate signatures (same)

Maybe the logic between those two places could be shared in a helper method that creates a Conflict or a list of ExactTree depending on whether any two of the three sides are isomorphic or not. I'd still keep the downstream check to make sure we never output spurious conflicts, it's cheap enough, no?

I agree that it feels unsatisfactory to have this check at such a downstream case, but to me it's a legitimate safety belt to add. Conflicts with identical sides can be created in at least two places: * when dealing with isomorphic nodes that are unmatched for one reason or another, in merged_tree.rs. We could add another check for isomorphism there, it's true (for now we only detect the `left == right` case there too). It's not clear to me if it would be much more efficient * but also in the highlighting of duplicate signatures (same) Maybe the logic between those two places could be shared in a helper method that creates a `Conflict` or a list of `ExactTree` depending on whether any two of the three sides are isomorphic or not. I'd still keep the downstream check to make sure we never output spurious conflicts, it's cheap enough, no?
wetneb force-pushed 356-spurious-conflicts from 3fba8c55f7 to 5fc178a961 2025-05-10 08:04:07 +02:00 Compare
wetneb force-pushed 356-spurious-conflicts from fe9036124e to 3e560bead7 2025-05-10 08:39:44 +02:00 Compare
wetneb force-pushed 356-spurious-conflicts from 3e560bead7 to cd351b0470 2025-05-10 08:42:33 +02:00 Compare
wetneb force-pushed 356-spurious-conflicts from cd351b0470 to 609133ae78 2025-05-10 08:56:41 +02:00 Compare
wetneb force-pushed 356-spurious-conflicts from 609133ae78 to 165400d47f 2025-05-10 09:40:37 +02:00 Compare
Author
Owner

I've added another commit to check for the isomorphism of sides earlier on, which can help catch some spurious conflicts in the presence of reformatting. Sadly, the method I introduced for that (MergedTree::new_conflict) can't be used in the other place where we create conflicts (the highlighting of duplicate signatures) because at that stage we need to check for isomorphism of merged trees directly, so it's not quite the same code.

I've added another commit to check for the isomorphism of sides earlier on, which can help catch some spurious conflicts in the presence of reformatting. Sadly, the method I introduced for that (`MergedTree::new_conflict`) can't be used in the other place where we create conflicts (the highlighting of duplicate signatures) because at that stage we need to check for isomorphism of merged trees directly, so it's not quite the same code.
@ -115,0 +118,4 @@
left: Vec<&'a AstNode<'a>>,
right: Vec<&'a AstNode<'a>>,
class_mapping: &ClassMapping<'a>,
) -> Vec<Self> {
Owner

it's a bit weird that we return a vec in a method which says it should return a conflict normally, and I guess we could use Either<Self, Vec<Self>>, but the value of that would be... questionable

it's a bit weird that we return a vec in a method which says it should return _a_ conflict normally, and I guess we could use `Either<Self, Vec<Self>>`, but the value of that would be... questionable
Owner

other than that, I really like that we've extracted this somewhat messy logic into a method!

other than that, I really like that we've extracted this somewhat messy logic into a method!
Author
Owner

Yes it's a bit wonky… By the way, I originally tried to make this method return iterators directly, since all we do is just append those elements to another vector, but I convinced myself that the ownership rules make that unfeasible. Do you agree?

Yes it's a bit wonky… By the way, I originally tried to make this method return iterators directly, since all we do is just append those elements to another vector, but I convinced myself that the ownership rules make that unfeasible. Do you agree?
Owner

Oh, thanks for the heads-up! I played a bit around with it, and did in fact manage to do that. Granted, I ended up needing the Either after all... I'll try opening a PR to your branch to demonstrate the steps, see if you like the end result

Oh, thanks for the heads-up! I played a bit around with it, and did in fact manage to do that. Granted, I ended up needing the `Either` after all... I'll try opening a PR to your branch to demonstrate the steps, see if you like the end result
ada4a marked this conversation as resolved
Owner

It's not clear to me if it would be much more efficient

I'm not really concerned with efficiency in this case to be fair -- what I fear is that noticing the spurious conflict too late might lead to actual correctness issues, like with #170

I'd still keep the downstream check to make sure we never output spurious conflicts, it's cheap enough, no?

Yeah yeah I'm sure it'll be plenty cheap. Let's keep it

> It's not clear to me if it would be much more efficient I'm not really concerned with efficiency in this case to be fair -- what I fear is that noticing the spurious conflict too late might lead to actual correctness issues, like with #170 > I'd still keep the downstream check to make sure we never output spurious conflicts, it's cheap enough, no? Yeah yeah I'm sure it'll be plenty cheap. Let's keep it
doesn't compile, since the types of the last branch is technically
different from the rest
all we needed was to have `{first,second}_rev` inside the closure
restore iter::once to make the overall Either an Iterator
All checks were successful
/ test (pull_request) Successful in 58s
76fb75154f
could replace the `iter::Once` in the return type signature, but I think
it's actually nice, since it signifies that in that case, we return the
`MergedTree:Conflict`, _once_
ada4a approved these changes 2025-05-10 20:23:06 +02:00
wetneb merged commit a007e90952 into main 2025-05-10 21:11:47 +02:00
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#371
No description provided.