Skip to content

Lifting an Option with to_option returns it unchanged - #56

Merged
nz merged 1 commit into
mainfrom
nz/idempotent-to-option
Aug 12, 2026
Merged

Lifting an Option with to_option returns it unchanged#56
nz merged 1 commit into
mainfrom
nz/idempotent-to-option

Conversation

@nz

@nz nz commented Aug 12, 2026

Copy link
Copy Markdown
Member

Independent of the #53#54#55 stack; reviewable on its own.

Lifting an Option nested it

to_option lifts a value that may be nil. An Option is already lifted, so a second lift produced Some(Some(x)), which still answers some? and unwraps to an Option. Nothing raised at the lift; the mistake surfaced wherever something later reached for the inner value.

Some(1).to_option   # was Some(Some(1)), now Some(1)
None().to_option    # was Some(None), now None()

Where it shows up

Wherever a wrapped source meets an unwrapped one, which is every partially converted application. The idiom that hits it is lifting an association that returns nil today and then reaching through it for an attribute that is already an Option:

widget.widget_snapshot.to_option.and_then(&:data).unwrap_or({})

If widget_snapshot is a plain record that reads fine. Once the model on the other side converts, the same line double-wraps and and_then hands Some(record) to a block that expects the record — Errgonomic::UnwrappedAccessError, far from the lift that caused it. The second test in this PR is exactly that shape, and it fails without the fix.

Testing

rake — 26 tests, 68 assertions, and 118 doctests, all passing.

to_option lifts a value that may be nil, and an Option is already lifted.
Wrapping it again produced Some(Some(x)), which still answers some? and
unwraps to an Option, so the nesting surfaced somewhere far from the lift.

It shows up wherever a wrapped and an unwrapped source meet — an
association that returns nil today, lifted and then reached through for an
attribute that is already an Option.
@nz
nz merged commit 6495426 into main Aug 12, 2026
1 check passed
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.

2 participants