AL+

Language: RO (română) EN (English)

Email us: paul@alplustech.com

Looking back at the week of 8–14 January 2025

An address is only part of a Rust pointer

Rust 1.84 made pointer provenance APIs stable. Preserve pointer derivation in tagged data structures and define integer boundaries explicitly during review.

Citiți articolul în română

A tagged pointer needs an explanation of where the pointer came from, not merely a calculation that recovers its numeric address. Rust 1.84 gave stable code better tools for expressing that distinction. Where a data structure can retain pointer derivation while manipulating an address, it should do so. An integer round trip should be a deliberate boundary with its own justification.

Looking back from November 2026 at the week of 8 January 2025, the relevant event is the Rust 1.84 release on 9 January. Its strict-provenance APIs help separate an address from the provenance associated with a pointer. They improve the language available to implementers and reviewers. They do not establish that an arbitrary block of unsafe code is sound.

Preserve the relationship while changing the address

A numeric address describes a location. It does not, by itself, describe the allocation from which a pointer was derived or establish that a particular access is permitted. That distinction becomes important when low-level code stores metadata in pointer bits and later removes it. Recovering the original number answers only part of the correctness question.

Consider an illustrative data structure that uses otherwise available low bits for a small tag. Its author must justify the alignment that makes those bits available, the mask that separates metadata from the address, and the point at which the untagged pointer is used. The lifetime of the underlying allocation must also cover that use. None of these conditions follows simply from two integers being equal.

The January release provides operations including addr, with_addr and map_addr. addr extracts an address without exposing provenance; with_addr and map_addr can change an address while retaining the source pointer’s provenance. The implementation can express that an adjusted address belongs with a known pointer, rather than suggesting that an integer alone carries the entire relationship. The precise safety conditions still belong to each operation and subsequent access.

The current pointer documentation, consulted in November 2026, explains the conceptual distinction in more detail. It is later, mutable documentation, not a snapshot of the January release.

Make the invariant reviewable

For the hypothetical tagged structure, the useful review question is which pointer remains available when the tag is removed. If the answer is a pointer derived from the allocation being accessed, the code can make that relationship explicit. If all that survives is an integer, a reviewer needs a different explanation of the reconstruction.

That explanation should sit beside the representation decision. State what the tag means, which bits it may occupy, and why changing those bits cannot accidentally turn metadata into an access to unrelated storage. Also state when the allocation can be freed. A clear address transformation cannot repair a dangling pointer or an incorrect ownership protocol.

This is a maintenance consequence as much as a language detail. A compact representation may survive longer than the person who designed it. Later changes to alignment, allocation or concurrency can invalidate assumptions that once seemed obvious. Explicit derivation gives the next maintainer something concrete to follow, but the surrounding invariant must remain understandable too.

For a business depending on a native component, the decision affects how confidently that component can be changed. There is no measured saving implied here. The practical benefit sought is a smaller gap between the representation's intended rules and the operations visible in the code. That can make specialist review more focused without turning review into a guarantee.

Integer interoperability remains a real requirement

The strongest objection is external interoperability. Some interfaces or existing representations pass addresses as integers. Requiring every boundary to behave like a self-contained Rust data structure can be unrealistic. The release therefore also discusses exposed-provenance operations, which serve cases where strict-provenance operations cannot express the necessary interaction.

Treat this as a reason to define the boundary carefully. Identify what the external interface supplies, which allocation the reconstructed pointer is intended to access, and who maintains its lifetime. Prefer keeping the exceptional conversion localized so that ordinary internal transformations do not inherit an unexplained integer-based contract.

Exposed provenance is not automatically evidence of a bug. Nor is replacing every cast with a newer API a complete migration strategy. A change that preserves the numeric output but obscures the external contract can make the implementation harder to assess. Choose the operation that expresses the actual representation and acknowledge the constraints that remain outside Rust's local view.

Keep January separate from November

The Rust 1.83 announcement of 28 November 2024 discussed expanded constant evaluation, including pointer-related operations in constant contexts. That work concerns what computations can happen during compilation. January's provenance stabilization concerns how pointer derivation and addresses are expressed. One release should not be cited as the date of the other's feature.

The distinction also prevents a misleading adoption argument. A component might benefit from constructing fixed data at compile time without using tagged pointers. Another might need provenance-aware address manipulation entirely at runtime. These are separate design decisions with separate acceptance conditions, even when both involve pointers.

Start with one low-level representation rather than a project-wide replacement campaign. Draw its path from allocation to final access, identify every integer conversion, and decide which transformations can preserve derivation. Keep any external reconstruction boundary explicit. For custom software development, that is a useful deliverable: an implementation whose storage rules another engineer can explain, with remaining unsafe obligations stated rather than concealed by an API name.