How Table.Put is not atomic, and is non-recoverable upon ErrBadHash.
How Table.Drop cannot provide a meaningful error scenario.
How Table.Put will stack-overflow if it is unable to construct a table on resize.
Changes
Clearly note in the documentation that upon this error, you MUST rebuild the table from the source data.
Add this note to the documentation for ErrBadHash.
Note in the package-level documentation that Table is NOT a source of truth, and should not be trusted as one.
Update the contract of Table.Drop to return bool. Ignore the error when shrinking the table.
Limit resizes to 64.
Add internal defaultResizeLimit constant.
Design Decisions
It was tempting to return the displaced entry for Table.Put, and provide this invariant: on error, the displaced entry along + the tables current contents = the inserted entry + the old table. I chose not to, because for developers, receiving this error will probably just prompt them to just propagate it, or ignore it. Both times, the displaced entry is unused, so why return it?
Currently, the only error in Table.Drop is caused when the user tries to shrink. But, because Table.shrink is atomic, it won't break the table. Plus, because table capacity is an internal optimization, why should the user care?
The resize limit of 64 was arbitrary, and chosen as a large enough number to not get called unless the hash is truly broken.
We now return an error immediately if Table.Put cannot grow, due to a hash collision. The chance an even larger table size will fit the items is astronomically small, so we choose to ignore it.
Checklist
Tests pass
Docs updated
## Description
Closes #11. This PR attempts to grapple with:
1. How `Table.Put` is not atomic, and is non-recoverable upon `ErrBadHash`.
2. How `Table.Drop` cannot provide a meaningful error scenario.
3. How `Table.Put` will stack-overflow if it is unable to construct a table on resize.
## Changes
1. Clearly note in the documentation that upon this error, you MUST rebuild the table from the source data.
- Add this note to the documentation for `ErrBadHash`.
- Note in the package-level documentation that `Table` is NOT a source of truth, and should not be trusted as one.
2. Update the contract of `Table.Drop` to return `bool`. Ignore the error when shrinking the table.
3. Limit resizes to 64.
- Add internal `defaultResizeLimit` constant.
### Design Decisions
- It was tempting to return the displaced entry for `Table.Put`, and provide this invariant: on error, the displaced entry along + the tables current contents = the inserted entry + the old table. I chose not to, because for developers, receiving this error will probably just prompt them to just propagate it, or ignore it. Both times, the displaced entry is unused, so why return it?
- Currently, the only error in `Table.Drop` is caused when the user tries to shrink. But, because `Table.shrink` is atomic, it won't break the table. Plus, because table capacity is an internal optimization, why should the user care?
- The resize limit of 64 was arbitrary, and chosen as a large enough number to not get called unless the hash is truly broken.
- We now return an error immediately if `Table.Put` cannot grow, due to a hash collision. The chance an even larger table size will fit the items is astronomically small, so we choose to ignore it.
## Checklist
- [x] Tests pass
- [x] Docs updated
mvhutz
changed title from WIP: feat!: put fails gracefully, allows recovery to feat!: `Table.Drop` returns `bool`, `Table.Put` doesn't cause stack-overflow2026-04-17 01:19:45 +00:00
mvhutz
changed title from feat!: `Table.Drop` returns `bool`, `Table.Put` doesn't cause stack-overflow to feat!: `Table.Drop` returns `bool`, `Table.Put` doesn't stack-overflow2026-04-17 01:19:51 +00:00
mvhutz
changed title from feat!: `Table.Drop` returns `bool`, `Table.Put` doesn't stack-overflow to feat!: `Drop` returns `bool`, `Put` doesn't stack-overflow2026-04-17 01:20:02 +00:00
mvhutz
merged commit 39548b4332 into main2026-04-17 01:31:02 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Description
Closes #11. This PR attempts to grapple with:
Table.Putis not atomic, and is non-recoverable uponErrBadHash.Table.Dropcannot provide a meaningful error scenario.Table.Putwill stack-overflow if it is unable to construct a table on resize.Changes
ErrBadHash.Tableis NOT a source of truth, and should not be trusted as one.Table.Dropto returnbool. Ignore the error when shrinking the table.defaultResizeLimitconstant.Design Decisions
Table.Put, and provide this invariant: on error, the displaced entry along + the tables current contents = the inserted entry + the old table. I chose not to, because for developers, receiving this error will probably just prompt them to just propagate it, or ignore it. Both times, the displaced entry is unused, so why return it?Table.Dropis caused when the user tries to shrink. But, becauseTable.shrinkis atomic, it won't break the table. Plus, because table capacity is an internal optimization, why should the user care?Table.Putcannot grow, due to a hash collision. The chance an even larger table size will fit the items is astronomically small, so we choose to ignore it.Checklist
WIP: feat!: put fails gracefully, allows recoveryto feat!: `Table.Drop` returns `bool`, `Table.Put` doesn't cause stack-overflowfeat!: `Table.Drop` returns `bool`, `Table.Put` doesn't cause stack-overflowto feat!: `Table.Drop` returns `bool`, `Table.Put` doesn't stack-overflowfeat!: `Table.Drop` returns `bool`, `Table.Put` doesn't stack-overflowto feat!: `Drop` returns `bool`, `Put` doesn't stack-overflow