FStarLang / FStarLang/pal

Unqualified type name emitted for a self-referential struct with an `_array` field of pointers to itself

Open
#283 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
11
Forks
1
Avg merge
2d 3h
Merged PRs (30d)
47

Description

**Versions:** PAL `a9ebbed` · F\*/Pulse nightly `2026-08-27` · Clang 20.1.8

## Summary

When a struct is **self-referential** *and* has an **`_array` field whose element type is a pointer to that same struct**, PAL emits an **unqualified** type name into the generated typedef module, and F\* cannot resolve it.

Translation reports no errors; the failure appears in generated code.

## Minimal repro

```c
#include "pal.h"

/* 1: TRIGGERS THE BUG */
typedef struct node_t {
struct node_t *next;
_array struct node_t **to_nodes; /* array of pointers to the SAME struct */
int n;
} node_t;

int f1(node_t *p) _requires(p->to_nodes._length > 0) { return p->n; }

/* 2: control -- _array of a different type. VERIFIES */
typedef struct node2_t {
struct node2_t *next;
_array double **vals;
int n;
} node2_t;

int f2(node2_t *p) _requires(p->vals._length > 0) { return p->n; }

/* 3: control -- self-referential, no _array field. VERIFIES */
typedef struct node3_t {
struct node3_t *next;
int n;
} node3_t;

int f3(node3_t *p) { return p->n; }
```

```
$ pal --outdir out repro.c # no errors
$ run-fstar.sh --include out out/Func_f1.fst
Error 72 at out/Typedef_node_t.fst(15,36-15,49):
- Identifier not found: struct_node_t
$ run-fstar.sh --include out out/Func_f2.fst # Verified module: Func_f2
$ run-fstar.sh --include out out/Func_f3.fst # Verified module: Func_f3
```

Neither self-reference alone nor an `_array` field alone is enough — it is the combination.

## The generated code

`out/Typedef_node_t.fst`, as emitted:

```fstar
[@@pulse_eager_unfold] let predicate ty_node_t__uninit_pred
([@@@mkey] this: ty_node_t)
(val_this_0: (array_spec (ref struct_node_t))) <-- line 15, unqualified
(val_this_1: (array_spec (ref Pulse.Lib.C.float64)))
(val_this_2: (array_spec Pulse.Lib.C.float64)) =
((Struct_node_t.struct_node_t__uninit_pred this val_this_0 val_this_1 val_this_2))
```

Every other occurrence in the same file is correctly qualified as `Struct_node_t.struct_node_t`. Only the `array_spec (ref ...)` argument inside `__uninit_pred` is bare — this looks like a single missing module qualifier on the path that renders an `_array`-of-`ref`-to-self field type.

## Impact

We are using PAL to prove spatial memory safety (every array access in bounds) on the Olden and Ptrdist benchmark suites, holding the C source fixed and adding only annotations.

This is the natural C shape for a graph node. From `olden/em3d`'s `em3d.h:38-46`, unmodified:

```c
typedef struct node_t {
double *value;
struct node_t *next;
_array struct node_t **to_nodes; /* array of nodes pointed to */
_array double **from_values;
_array double *coeffs;
int from_count;
int from_length;
} node_t;
```

Because the failure is in the typedef module, it blocks **every** function that mentions the type — `compute_nodes`, `make_neighbors`, `fill_from_fields` — and with them **12 of em3d's 24** array-bounds obligations, none of which is otherwise problematic.

## Workaround

None from the annotation side: the failure is in generated code, before any user annotation is consulted.

## Suggested fix

Qualify the type name on the `array_spec (ref …)` rendering path inside `__uninit_pred`, as is already done everywhere else in the same generated file.

Happy to test a fix against the benchmark suite.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by running the minimal C reproduction with `pal --outdir out repro.c`, then inspect `out/Typedef_node_t.fst`, especially the `__uninit_pred` array_spec argument. Trace the `_array`-of-self-reference rendering path in PAL and compare it with the qualified occurrences elsewhere in that generated file. Done means the self-referential case resolves and the f1, f2, f3 commands verify successfully.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, rust
Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
70/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.