Skip to content

Ptr - #1469

Open
sbillig wants to merge 9 commits into
argotorg:masterfrom
sbillig:ptr
Open

Ptr#1469
sbillig wants to merge 9 commits into
argotorg:masterfrom
sbillig:ptr

Conversation

@sbillig

@sbillig sbillig commented May 23, 2026

Copy link
Copy Markdown
Collaborator

This PR adds first-class typed memory pointers to Fe and redesigns the core, ABI, and EVM memory APIs around explicit pointer, view, ownership, and capacity types.

The previous APIs represented memory addresses primarily as u256 values or effect-handle wrappers. This made it difficult for the type system and borrow analysis to distinguish memory pointers from integer-backed handles, track pointer provenance, prevent pointers from escaping into storage, and express bounded memory operations.

Language changes

  • Adds typed memory pointer syntax: *T.
  • Supports dereference reads and writes with *ptr.
  • Supports pointer field access, equality, typed pointer casts, and pointer arithmetic helpers.
  • Allows borrowing through pointer dereferences.
  • Implements Index and IndexMut for pointer-backed arrays and memory arrays.
  • Routes indexed augmented assignments such as items[i] += value through IndexMut.
  • Treats a bare * at the start of a line as a dereference. Multiline multiplication must keep * on the preceding line.
  • Keeps nested dereferences such as * *ptr lexically separate when formatting because ** is the exponentiation token.

Memory APIs

Adds core::ptr with:

  • *T: a typed address in linear memory.
  • MemArray<T>: a dynamically sized typed memory allocation.
  • MemSlice<T>: a copyable, read-only bounded view.
  • MemSpan: an alias for MemSlice<u8>.
  • MemBuffer: an owned byte allocation with separate logical length and writable capacity.
  • FixedMemBuffer<N>: a fixed-size, non-escaping allocation that exposes constant allocation sizes to backend scratch-memory planning.
  • Allocation, casting, offset, copying, zeroing, slicing, and checked indexing helpers.

Memory-bearing EVM APIs now accept MemSpan, MemBuffer, or typed pointers instead of loose integer address/length pairs. This applies to hashing, logging, copying, return/revert data, contract creation, ABI encoding, and low-level calls.

Low-level call results retain both the amount written into the supplied output buffer and the complete returndata length. Higher-level call outcomes can preserve owned returndata for decoding or bubbling reverts.

ABI changes

  • Encode<A> now writes directly to *u8.
  • Allocation-based encoding helpers return MemBuffer.
  • Removes the cursor-based AbiEncoder abstraction.
  • ABI inputs and outputs use bounded memory regions.
  • Static contract returns use fixed, non-escaping buffers so the backend can place them in scratch memory.

Pointer safety

The compiler now tracks pointer provenance through aggregates, projections, calls, control flow, and returns.

Pointer-bearing values cannot be written into persistent or transient storage, including through generic functions that become storage-specialized later.

Memory pointers implement EffectHandle directly. User-defined effect handles must use *Target and the memory address space; integer-backed handles remain reserved for compiler-provided core and standard-library address spaces.

Parser and tooling

  • Aligns the compiler parser, formatter, and Tree-sitter grammar on pointer syntax and the line-start * policy.
  • Fixes Tree-sitter parsing of chained || conditions.
  • Regenerates the bundled Tree-sitter WASM artifact.
  • Makes enum-tag sizing portable across host pointer widths, including WASM/WASI builds.

Breaking changes and migration

Previous API Replacement
MemPtr<T> *T
core::abi::MemoryInput MemSpan or another ByteInput
std::evm::MemoryBytes MemSpan
std::evm::mem::alloc core::ptr allocation helpers or MemBuffer
integer pointer/length EVM arguments MemSpan, MemBuffer, or *T
AbiEncoder Encode::encode(..., *u8) and allocation helpers returning MemBuffer
Into<T> explicit conversion APIs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 42ce9fb159

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/mir/src/runtime/lower/body.rs Outdated
@sbillig
sbillig marked this pull request as draft May 23, 2026 23:15
@sbillig
sbillig marked this pull request as ready for review May 26, 2026 14:49

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ce37ed5675

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/mir/src/runtime/lower/classify.rs Outdated
Comment thread crates/hir/src/analysis/semantic/borrowck/check.rs Outdated
@sbillig

sbillig commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator Author

On hold till after 26.2 release.

@micahscopes micahscopes left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

agent:

One borrowck question without a single line to hang it on: callee analysis
seeds pointer params as pairwise-disjoint pointees, but I couldn't find
anywhere that rejects f(p, p) — no check at the call site, no diagnostic in
the callee. Is the no-alias contract meant to be checked, modeled as may-alias,
or documented as a soundness precondition?

Comment thread crates/hir/src/analysis/semantic/borrowck/canon.rs Outdated
Comment thread ingots/core/src/ptr.fe Outdated
@micahscopes

Copy link
Copy Markdown
Collaborator

agent:

One more from the same family as the call-havoc question: the Store handler
early-returns when the source type isn't pointer-bearing (canon.rs:847-850),
deciding from the value type alone that pointer slots can't be affected. With
ptr-to-ptr casts (core::ptr::cast does this generically) the written region
can overlap a pointer slot of a different type:
let raw = core::ptr::cast<Holder, u256>(h); *raw = 123 physically overwrites
h.ptr while its strong fact stays live — and slot keys are typed-path-based, so
the punned view never collides with the original's key either. Punning is
misuse territory, but if the hardening goal is that laundering degrades to
Unknown, a store through a cast-derived view should probably havoc the pointer
slots under the written roots rather than keep stale precise facts.

@micahscopes

Copy link
Copy Markdown
Collaborator

agent:

Possible ICE on the lowering side: when a Deref projection hits a class with no
deref_target() — i.e. RawAddr { target: None }, every pointer-to-scalar —
both body.rs:4428-4431 and classify.rs:653-668 fall back to the root local's
pointee type. For struct S { p: *u256 }, the place s + [Field(p), Deref]
has a non-pointer root, so the fallback returns None and classify's
expect("invalid deref projection class") panics; for pp: **u256, **pp
reuses the first-level pointee for the second deref (right mload chain by
accident, wrong class label). Might be unreachable depending on how HIR
normalizes these shapes — no fixture covers either.

@micahscopes

Copy link
Copy Markdown
Collaborator

agent:

Two policy-level things. ty_is_noesc returns false for *T (and for
aggregates containing only pointers), so noesc's check_store permits storing
raw pointers / MemArray into storage and transient — memory addresses that
persist past the transaction and dangle on the next one. If pointer-in-storage
is intended (transient scratch?), worth stating; otherwise pointers should
probably be noesc. Separately, the parser change making infix * terminate at
a line break (parser/expr.rs:378-385) silently reparses previously-valid
multi-line multiplications — a newline * b was a * b, now a followed by
a deref statement. Was a corpus check done for that pattern?

@sbillig
sbillig force-pushed the ptr branch 4 times, most recently from bda49ea to 311fc25 Compare July 31, 2026 15:27
@sbillig

sbillig commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 311fc250a6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/hir/src/analysis/ty/ty_check/expr.rs
Comment thread crates/parser/src/parser/expr.rs
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