Skip to content

fix(labels): keep full feature ids in web label locks - #1302

Merged
Mavrick-F merged 1 commit into
opengeos:mainfrom
Mavrick-F:fix/locked-label-reused-id
Nov 2, 2026
Merged

Mavrick-F merged 1 commit into
opengeos:mainfrom
Mavrick-F:fix/locked-label-reused-id

Conversation

@Mavrick-F

@Mavrick-F Mavrick-F commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

Summary

On the web, label locks identify features through a usize, so IDs 1 and 4294967297 become the same key. Locking while only Alpha fits, then zooming until Beta has room, incorrectly shows Beta although its label was never locked.

Keep the feature ID as u64 throughout label placement, locked-class filtering, extrusion lookup and removed-feature lock pruning. The lock is runtime-only (serde(skip)), so the saved project format stays the same.

- LabelKey = (u32, usize, usize, usize)
+ LabelKey = (u32, u64, usize, usize)

The deletion/reused-ID case in this issue was fixed by #1271; this completes its remaining wasm32 truncation case.

Testing

  • A small wasm32 probe using the production key type and conversion verbatim (run in Node): IDs 1 and 4294967297 collide before, remain distinct after.
  • Renderer regression (passes) locks Alpha while Beta collides, zooms in, and checks Beta stays hidden until unlocked; relocking keeps both full IDs.
  • The existing engine regression now uses adjacent IDs above 2^32, covering delete/reuse, lock pruning, undo and redo.
  • cargo xtask ci: passes (formatting, workspace Clippy, tests, layers).
  • cargo build --locked --target wasm32-unknown-unknown -p rustgis-web: passes.
  • pre-commit run --all-files: passes.

UI evidence

Real web app, two point features with IDs 1 and 4294967297. The existing hosted web app and this branch's local wasm build run inside the same iframe harness. Both lock at the same initial view, where only Alpha fits, then zoom in four steps. Before: Beta incorrectly appears. After: only Alpha remains labelled.

Before:

Before: Beta incorrectly appears while labels are locked

After:

After: only Alpha remains labelled while locked

Related issue

Closes #1135

Summary by CodeRabbit

  • Bug Fixes
    • Label locks now remain distinct for features with large IDs, preventing one feature’s lock from affecting another.
    • Label locks remain associated with the correct features when edits change their positions, including on platforms that support only 32-bit indexing. Existing lock and unlock behavior is otherwise unchanged.

@coderabbitai

coderabbitai Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 53349e26-fc97-4465-8c8d-5cfc90db0bf7
Commits

Reviewing files that changed from the base of the PR and between 3360310 and 02119b3.

Files selected for processing: 4
  • crates/engine/src/lib.rs
  • crates/engine/src/tests.rs
  • crates/map/src/symbology.rs
  • crates/render/src/lib.rs

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 6 remain after this review.

Walkthrough

Label keys, rendering lookups, and lock tracking now retain full-width u64 feature IDs. Removed feature IDs are pruned without narrowing conversions. Tests cover distinct IDs above u32::MAX across label locking, pruning, and undo.

Changes: Label lock identity

Layer / File(s) Summary
Full-width label keys
crates/map/src/symbology.rs, crates/render/src/lib.rs
LabelKey and rendering lookup keys use u64 feature IDs. The render test checks distinct IDs across locking and unlocking.
Prune removed feature IDs
crates/engine/src/lib.rs, crates/engine/src/tests.rs
Lock pruning stores and compares feature IDs as u64. The engine test exercises full-width IDs through lock placement, pruning, and undo.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Low

Suggested reviewers: jgregoriorincon

Merge Risk: Minimal · up to 02119

No actionable merge-blocking issue is identified. The changes address full-width label identity consistently; automated wasm32 regression coverage remains a documented follow-up.

Pre-merge checks: Passed 5
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main change: preserving full feature IDs in web label locks.
Description check Passed The description includes all required sections: Summary, Testing, UI evidence, and Related issue. It explains the bug, implementation, compatibility impact, validation steps, and provides before-and-a…
Linked Issues check Passed Issue #1135 requires removed-feature lock entries to be pruned and feature IDs in LabelKey to remain full-width. The existing pruning path now stores and compares IDs as u64. LabelKey now uses u64, an…
Out of Scope Changes check Passed The changes are limited to label-lock ID width and related lookup and pruning paths. The added and updated tests verify the issue behavior. No unrelated functional change is shown.
Docstring Coverage Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentati…
Full details: Description check

Explanation

The description includes all required sections: Summary, Testing, UI evidence, and Related issue. It explains the bug, implementation, compatibility impact, validation steps, and provides before-and-after UI evidence.

Full details: Linked Issues check

Explanation

Issue #1135 requires removed-feature lock entries to be pruned and feature IDs in LabelKey to remain full-width. The existing pruning path now stores and compares IDs as u64. LabelKey now uses u64, and renderer lock filtering, label placement, extrusion lookup, and synthetic keys use u64 without truncating feature IDs. Engine and renderer regressions cover deletion/reuse and IDs 1 and 4294967297.

Full details: Docstring Coverage

Explanation

Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 5 functions across 3 files. (1 skipped: 1 too large.)

Finishing Touches
Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

A rabbit checks each label key,
And keeps wide IDs as wide as can be.
Old locks lose IDs no longer in view,
While Alpha and Beta keep their names true.
The bunny hops off, pleased with the queue.

Comment thread crates/render/src/lib.rs
/// A lock keeps source ids wider than a wasm32 pointer distinct, including when a label
/// that collided at lock time later has room to draw (#1135).
#[test]
fn locked_labels_keep_full_width_feature_ids() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage note (low severity, not a blocker): on the native test target usize is 64-bit, so this test, and the engine test changes, also pass on the pre-fix code. The truncation only happens on wasm32, and CI runs no tests there, only cargo build --target wasm32-unknown-unknown -p rustgis-web. So nothing in CI would catch this coming back. The Node probe in the PR description covers the wasm32 side once, but it isn't committed. Consider saying in the PR that these tests guard behaviour on native only, and that the wasm32 truncation check is manual.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarified the PR description: these Rust tests run on native and also pass before the fix because usize is 64-bit there. The wasm32 truncation checks are manual: the source-extracted Node probe and the before/after browser run in an iframe. CI currently builds wasm32 without running these regressions there.

@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Code review

I found no bugs, security issues, or performance problems in this change. I checked every use of LabelKey, label_lock, and feature-id casts across crates/, and apps/. The one thing I flagged is a test-coverage note, posted inline.

Bugs: none found. Feature.id is u64 (crates/data/src/lib.rs:150), so the new key type matches the source. The lock keys, locked_classes, the extrusion row lookup, and the removed-feature pruning in forget_locks_of_removed_features all now compare full-width ids. The remaining as usize casts I found are unrelated to lock keys. The engine test's direct id assignment goes through DerefMut, which clears the cached max_id, so the id-reuse scenario still holds.

Security: none. The lock is serde(skip) (crates/map/src/lib.rs:1205), so no persisted format changes.

Performance: none. The change swaps integer widths and adds no work.

Quality:

  • Test coverage (confidence: high on the fact, low on severity): the new render test and the engine test changes pass on the pre-fix code on native, because usize is 64-bit there. The truncation only happens on wasm32, and CI runs no tests there. Posted inline on crates/render/src/lib.rs:5422. This is a note, not a request for changes. It may wait for the release quality pass.

AGENTS.md: no violations found. The change is type-only, so the wasm build is unaffected. It adds no user-visible strings, no assets, and no new dependencies. The layering is unchanged.

Already raised: 0 earlier concerns, since there are no prior review threads on this PR.

Change size

Compared: the whole PR against main (merge base 3360310 to PR head 02119b3).

Measure Value
Files changed 4 (added 0, modified 4, removed 0, renamed 0)
Size before 2.0 MB
Size after 2.0 MB
Total size change +1.9 KB
Path Before After Change
crates/render/src/lib.rs 435.4 KB 436.9 KB +1.7 KB
crates/engine/src/tests.rs 1.3 MB 1.3 MB +148 B
crates/map/src/symbology.rs 154.7 KB 154.8 KB +69 B
crates/engine/src/lib.rs 83.7 KB 83.6 KB -13 B

@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

📖 Docs preview

Item Value
Preview https://preview.rustgis.app/pr-1302/
Web app https://preview.rustgis.app/pr-1302/app/
Commit 02119b3

GitHub Pages takes a minute or two to publish a new commit. Newer commits from the fork aren't published until a maintainer adds the preview label (once per commit).

@Mavrick-F
Mavrick-F merged commit 1ba9904 into opengeos:main Nov 2, 2026
18 checks passed
@Mavrick-F
Mavrick-F deleted the fix/locked-label-reused-id branch November 2, 2026 02:38
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.

[Bug]: A locked label can attach to a new feature that reuses a deleted feature's id

1 participant