Fix maps:from_keys/2 dedup for boxed terms (tuples, etc.) - #2393
Open
CoderDennis wants to merge 1 commit into
Open
Fix maps:from_keys/2 dedup for boxed terms (tuples, etc.)#2393CoderDennis wants to merge 1 commit into
CoderDennis wants to merge 1 commit into
Conversation
sort_keys_uniq's dedup phase compared keys with raw pointer `!=`
after sorting them with real structural comparison. For immediates
(small integers, atoms) the tagged word *is* the value, so `!=`
happened to work. For boxed terms (tuples, bignums, ...) the word is
a tagged pointer, so two separately-allocated but structurally equal
keys were never deduplicated, even though the preceding sort placed
them adjacent via correct structural comparison.
sets:from_list/1 hits the same bug since it's built on top of
maps:from_keys/2.
Use term_compare/4 in the dedup phase instead, mirroring the existing
pattern in term_find_map_pos.
Add a regression test to maps_nifs.erl: build five separately
heap-allocated {1, 1} tuples and confirm maps:from_keys/2 collapses
them to a map of size 1.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016go5qvVW72PrRnvPTnYkq9
Signed-off-by: Dennis Palmer <dodava@gmail.com>
CoderDennis
force-pushed
the
fix-maps-from-keys-boxed-term-dedup
branch
from
September 6, 2026 12:44
5ee856a to
735ff79
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Claude and I hit this bug when building what I thought would be a simple Conway's Game of Life on an ESP32 device with a small touch screen.
Expected behavior
maps:from_keys(List, Value)andsets:from_list(List)should deduplicateListusingstructural equality — the same semantics as OTP, and as AtomVM's own
term_find_map_pos. Fiveseparately-allocated
{1, 1}tuples should collapse to size 1.Actual behavior
On AtomVM, five separately-allocated but structurally-identical
{1, 1}tuples produce amap/set of size 5 — no deduplication happens for boxed terms. Immediates (small integers,
atoms) are unaffected.
sort_keys_uniq's dedup phase compared keys with raw pointer!=after sorting them with real structural comparison. For immediates (small integers, atoms), the tagged word is the value, so!=happened to work. For boxed terms like tuples, the word is a tagged pointer, so two separately allocated but structurally equal keys were never deduplicated, even though the preceding sort placed them adjacent via correct structural comparison.sets:from_list/1hits the same bug since it's built on top ofmaps:from_keys/2.Fix
Use
term_compare/4in the dedup phase instead, mirroring the existing pattern interm_find_map_pos.Add a regression test to
maps_nifs.erl: build five separately heap-allocated{1, 1}tuples and confirmmaps:from_keys/2collapses them to a map of size 1.