Skip to content

Support static array literals and &[T;N] → &[T] coercion#123

Draft
coord-e wants to merge 4 commits into
mainfrom
claude/static-arrays-slices-y6hmtr
Draft

Support static array literals and &[T;N] → &[T] coercion#123
coord-e wants to merge 4 commits into
mainfrom
claude/static-arrays-slices-y6hmtr

Conversation

@coord-e

@coord-e coord-e commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Summary

Three commits, each paired with a pass/fail test:

  1. Basic supportPlaceElem::Index in src/refine/env.rs: MIR place projections (*s)[i] now resolve to a select constraint on the underlying CHC array term. Handles both slice (Tuple → proj 0 → deref) and raw Array types. Adds tests/ui/fail/slice_2.rs to pair the existing pass test.

  2. Construction supportAggregateKind::Array arm in src/analyze/basic_block.rs: array literals [1, 2, 3] produce rty::Type::Array(Int, T) with element values pinned via store folds over a base existential. Element type for empty arrays is read directly from AggregateKind::Array(ty) rather than derived from elements. Paired tests: s[0] == 1 passes, s[0] == 99 → Unsat.

  3. Coercion supportPointerCoercion::Unsize arm in src/analyze/basic_block.rs: &[T; N] → &[T] coercions wrap the array place type in a (Array<Int,T>, N) tuple with the concrete length, enabling bounds verification. Paired tests: index 3 on a 4-element slice passes, index 4 → Unsat.

Test plan

  • cargo test — all existing tests continue to pass; 4 new tests pass
  • tests/ui/pass/array_literal_1.rss[0] == 1 verifies
  • tests/ui/fail/array_literal_1.rss[0] == 99 reports Unsat
  • tests/ui/pass/array_literal_2.rss[3] on 4-element slice is safe
  • tests/ui/fail/array_literal_2.rss[4] on 4-element slice reports Unsat
  • tests/ui/fail/slice_2.rss[2] with only len >= 2 guaranteed reports Unsat

Known limitations (out of scope)

  • [x; N] repeat syntax compiles to Rvalue::Repeat, not handled here
  • Direct static-array indexing without a coercion (arr[i] as array place, not slice) is not exercised by these tests

claude added 4 commits June 12, 2026 16:21
Add `model::Slice<T>` and `Model` impls for `[T]`, `model::Slice<T>`,
and `[T; N]` so that the existing Model-trait normalization pipeline
handles these types without changes to the core type-builder logic:

- `[T]` normalizes to `model::Slice<T::Ty>` = `(Array<Int,T>, Int)`,
  matching the Vec model (`.0` = array, `.1` = length)
- `[T; N]` normalizes to `model::Array<Int, T::Ty>`, reusing the
  existing array model (N is statically known, written directly in specs)
- `&[T]` and `&mut [T]` flow through the existing reference handling

Add `Rvalue::Len` handling in `basic_block.rs` (slice length comes from
fat-pointer metadata in MIR, not a function call):
- For slice model (TupleType): project element 1 then deref the box
- For static array model (ArrayType): evaluate the const N from MIR

Add `UnOp::PtrMetadata` handling for `&[T]` references: extract the
length by deref → tuple_proj(1) → deref.

Add extern specs for `<[T]>::len`, `<[T]>::index`, `<[T]>::index_mut`,
and `<[T]>::is_empty`, mirroring the existing Vec specs.

Add test cases:
- `tests/ui/pass/slice_1.rs`: safe indexing with non-empty slice
- `tests/ui/fail/slice_1.rs`: out-of-bounds access (empty slice)
- `tests/ui/pass/slice_2.rs`: two-element slice, two safe indices

https://claude.ai/code/session_01BV92ggaKvAp7oNknvVmGsM
Add Path::Index variant and path_type() arm in env.rs so that MIR place
projections of the form (*s)[i] resolve to a select constraint on the
underlying CHC array term. Handles both slice (Tuple → proj 0 → deref)
and raw Array types.

Add tests/ui/fail/slice_2.rs: accessing index 2 on a slice guaranteed
only len >= 2 cannot be proven safe → Unsat, pairing the existing pass.

https://claude.ai/code/session_01BV92ggaKvAp7oNknvVmGsM
Handle AggregateKind::Array in rvalue_type(): fold store operations over a
base existential to build a CHC array term with each element constrained to
its concrete value. Elements are not boxed — they go directly into the array.
For empty arrays, element type is read from AggregateKind::Array(ty) directly.

Paired tests: pass asserts s[0]==1 (correct), fail asserts s[0]==99 → Unsat.

https://claude.ai/code/session_01BV92ggaKvAp7oNknvVmGsM
… model

Add PointerCoercion::Unsize arm in rvalue_type(): reads N from the MIR
source type before consuming the operand, then wraps the array place type
in a (Array<Int,T>, N) tuple to produce the slice model with concrete length.

Paired tests: pass accesses index 3 on a 4-element slice (safe), fail
accesses index 4 → Unsat.

https://claude.ai/code/session_01BV92ggaKvAp7oNknvVmGsM
@coord-e coord-e force-pushed the claude/static-arrays-slices-y6hmtr branch from 4df27b4 to 7f78620 Compare June 13, 2026 06:49
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