Skip to content

Fix meet_2 unwrapping a None when a source focus holds an empty node - #75

Open
imlvts wants to merge 1 commit into
Adam-Vandervorst:masterfrom
imlvts:bugfix/meet-2-empty-source-node
Open

Fix meet_2 unwrapping a None when a source focus holds an empty node#75
imlvts wants to merge 1 commit into
Adam-Vandervorst:masterfrom
imlvts:bugfix/meet-2-empty-source-node

Conversation

@imlvts

@imlvts imlvts commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

meet_2 guards both sources with try_as_tagged, then on the Identity arm unwraps into_option on the same value. The two disagree: try_as_tagged answers Some for a BorrowedRc whatever it holds, while into_option answers None when that node is empty. So a source whose focus holds an empty node passes the guard and panics on the unwrap. An empty node is what create_path leaves behind, so a read zipper rooted at a dangling path is enough:

a.create_path(&[0]);
wz.meet_2(&a.read_zipper_at_path(&[0]), &b.read_zipper_at_path(&[0]));

The mask on the Identity arm says which operand the intersection equals, so an empty operand means an empty intersection: graft nothing and report None. That is what the model specifies for meet_2 when either source node is empty.

Regression test: write_zipper_meet_2_with_an_empty_source_node, three shapes for the other operand, both operand orders. Fails before this change with an Option::unwrap() panic.

`meet_2` guards both sources with `try_as_tagged`, then on the
`Identity` arm unwraps `into_option` on the same value.  The two
disagree: `try_as_tagged` answers `Some` for a `BorrowedRc` whatever it
holds, while `into_option` answers `None` when that node is empty.  So a
source whose focus holds an empty node passes the guard and panics on
the unwrap.  An empty node is what `create_path` leaves behind, so a
read zipper rooted at a dangling path is enough:

    a.create_path(&[0]);
    wz.meet_2(&a.read_zipper_at_path(&[0]), &b.read_zipper_at_path(&[0]));

The mask on the `Identity` arm says which *operand* the intersection
equals, so an empty operand means an empty intersection: graft nothing
and report `None`.  That is what the model specifies for `meet_2` when
either source node is empty.

Regression test: `write_zipper_meet_2_with_an_empty_source_node`, three
shapes for the other operand, both operand orders.  Fails before this
change with an `Option::unwrap()` panic.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZmoASqM5FUuzvJeJaYQjR
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.

1 participant