Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .trinity/seals/TriKdTree.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"gen_hash_c": "sha256:7658bd16d1d66d14de50176a27cc78f130863a13853fedc2dacc839a2fe4a68f",
"gen_hash_rust": "sha256:ec452f608b4f52459b4c87a32fcc38622f3b833ff8f0591af58949c5a8530bb9",
"gen_hash_rust": "sha256:5109675652b7451a917c1f6f145b99bef55491f2ac4bbc4d9025d55ca37c5fc6",
"gen_hash_verilog": "sha256:c1f0afec0673c3db6f521e9b37b4add257f355a964bb55b153707616595c93e3",
"gen_hash_zig": "sha256:369f3d5632ef02f40c2edea5a3ab0670cce287040188cf7d66ae11fed6ed3dda",
"module": "TriKdTree",
Expand Down
2 changes: 1 addition & 1 deletion .trinity/seals/TriLinkedList.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"gen_hash_c": "sha256:24973c2e300a0a88db9ca2039d8bfb7ed18cc408ccf22acbcc435ac2e473f365",
"gen_hash_rust": "sha256:a84e33b1e860fca96f97c3c133c599840bc2ec83bd918a53baf33724cdda2262",
"gen_hash_rust": "sha256:428047f5cf573a30fb54b11ae32987750b200b9ba01ad7dec87c8a911c03b45f",
"gen_hash_verilog": "sha256:6c52068e721a7503b2bd566c20bf4435c36545b991f689fb4b5e38227b42f7e7",
"gen_hash_zig": "sha256:32622c710581aca2415f300aed3c02dad83c1c53136677df3cdcdca5f8df44d3",
"module": "TriLinkedList",
Expand Down
2 changes: 1 addition & 1 deletion .trinity/seals/TriOctree.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"gen_hash_c": "sha256:0bedc286e426f126d811665fd97147dc6ebfba4f96958a522fb9d779d982cfa0",
"gen_hash_rust": "sha256:5884219ea586303bea5c3910b36b8377dd9ac120ec27be8e6fbb1f83fd032062",
"gen_hash_rust": "sha256:524d49b87aed3207a3f394fbfa97699f5b082c401686c473b1394842a456cbe3",
"gen_hash_verilog": "sha256:bfdd79ebab78682b40028db81ce198b51da58b7c5cb959580165fc9fa01f276d",
"gen_hash_zig": "sha256:01938d9fbbfc4d9f5e19ad941071b5a303b8c7b87e336157ce928c26c34d18eb",
"module": "TriOctree",
Expand Down
2 changes: 1 addition & 1 deletion .trinity/seals/TriQuadtree.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"gen_hash_c": "sha256:3f1b5f372579e92827fa9a413eb3136abc5272daee917df4dcfd9b2fae31ae82",
"gen_hash_rust": "sha256:251c098726ade16a892350dc069771ef00100f35b339cdef789618a29cf81b02",
"gen_hash_rust": "sha256:42d4017e6b586dc73cbc6cca85351bf20f06c83500f5a5823ee4a3e5f626b9b3",
"gen_hash_verilog": "sha256:d13d947ba9e73a5be25d64aa717c5d3f1138396f77674ffdc56a0dfef150fe77",
"gen_hash_zig": "sha256:01514daa510c982d521d72b36552a8ef68f946957d0351799bfad2073128ea4d",
"module": "TriQuadtree",
Expand Down
4 changes: 2 additions & 2 deletions .trinity/seals/collections_TriLinkedList.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"gen_hash_c": "sha256:24973c2e300a0a88db9ca2039d8bfb7ed18cc408ccf22acbcc435ac2e473f365",
"gen_hash_rust": "sha256:a84e33b1e860fca96f97c3c133c599840bc2ec83bd918a53baf33724cdda2262",
"gen_hash_rust": "sha256:428047f5cf573a30fb54b11ae32987750b200b9ba01ad7dec87c8a911c03b45f",
"gen_hash_verilog": "sha256:6c52068e721a7503b2bd566c20bf4435c36545b991f689fb4b5e38227b42f7e7",
"gen_hash_zig": "sha256:32622c710581aca2415f300aed3c02dad83c1c53136677df3cdcdca5f8df44d3",
"module": "TriLinkedList",
"ring": 12,
"sealed_at": "2026-09-05T01:08:39Z",
"sealed_at": "2026-09-06T08:02:09Z",
"sealed_by": "t27c-bootstrap@0.2.0",
"spec_hash": "sha256:5171edf6089a238976e6fad2ba577ed72cff191cf634ee94c28645f3551f9ffc",
"spec_path": "specs/tri/collections/linked_list.t27"
Expand Down
4 changes: 2 additions & 2 deletions .trinity/seals/trees_TriKdTree.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"gen_hash_c": "sha256:7658bd16d1d66d14de50176a27cc78f130863a13853fedc2dacc839a2fe4a68f",
"gen_hash_rust": "sha256:ec452f608b4f52459b4c87a32fcc38622f3b833ff8f0591af58949c5a8530bb9",
"gen_hash_rust": "sha256:5109675652b7451a917c1f6f145b99bef55491f2ac4bbc4d9025d55ca37c5fc6",
"gen_hash_verilog": "sha256:c1f0afec0673c3db6f521e9b37b4add257f355a964bb55b153707616595c93e3",
"gen_hash_zig": "sha256:369f3d5632ef02f40c2edea5a3ab0670cce287040188cf7d66ae11fed6ed3dda",
"module": "TriKdTree",
"ring": 12,
"sealed_at": "2026-09-05T01:08:39Z",
"sealed_at": "2026-09-06T08:02:09Z",
"sealed_by": "t27c-bootstrap@0.2.0",
"spec_hash": "sha256:338dda6bd5fe68db61f018bc4216fd6ab671562bcfc3cf92f1692fbdc2440abd",
"spec_path": "specs/tri/trees/kd_tree.t27"
Expand Down
4 changes: 2 additions & 2 deletions .trinity/seals/trees_TriOctree.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"gen_hash_c": "sha256:0bedc286e426f126d811665fd97147dc6ebfba4f96958a522fb9d779d982cfa0",
"gen_hash_rust": "sha256:5884219ea586303bea5c3910b36b8377dd9ac120ec27be8e6fbb1f83fd032062",
"gen_hash_rust": "sha256:524d49b87aed3207a3f394fbfa97699f5b082c401686c473b1394842a456cbe3",
"gen_hash_verilog": "sha256:bfdd79ebab78682b40028db81ce198b51da58b7c5cb959580165fc9fa01f276d",
"gen_hash_zig": "sha256:01938d9fbbfc4d9f5e19ad941071b5a303b8c7b87e336157ce928c26c34d18eb",
"module": "TriOctree",
"ring": 12,
"sealed_at": "2026-09-06T04:36:45Z",
"sealed_at": "2026-09-06T08:02:09Z",
"sealed_by": "t27c-bootstrap@0.2.0",
"spec_hash": "sha256:63216e4dbe843da95dd62bfc13b7741e6bf343e3bcf3d407e084d6be61e84dfe",
"spec_path": "specs/tri/trees/octree.t27"
Expand Down
4 changes: 2 additions & 2 deletions .trinity/seals/trees_TriQuadtree.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"gen_hash_c": "sha256:3f1b5f372579e92827fa9a413eb3136abc5272daee917df4dcfd9b2fae31ae82",
"gen_hash_rust": "sha256:251c098726ade16a892350dc069771ef00100f35b339cdef789618a29cf81b02",
"gen_hash_rust": "sha256:42d4017e6b586dc73cbc6cca85351bf20f06c83500f5a5823ee4a3e5f626b9b3",
"gen_hash_verilog": "sha256:d13d947ba9e73a5be25d64aa717c5d3f1138396f77674ffdc56a0dfef150fe77",
"gen_hash_zig": "sha256:01514daa510c982d521d72b36552a8ef68f946957d0351799bfad2073128ea4d",
"module": "TriQuadtree",
"ring": 12,
"sealed_at": "2026-09-06T05:46:34Z",
"sealed_at": "2026-09-06T08:02:09Z",
"sealed_by": "t27c-bootstrap@0.2.0",
"spec_hash": "sha256:974e62d1cdcc28189ff5fddbf9405c9e02f8bb01325bc2f9860f0578a053b345",
"spec_path": "specs/tri/trees/quadtree.t27"
Expand Down
42 changes: 42 additions & 0 deletions bootstrap/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23881,6 +23881,47 @@ impl RustCodegen {
}
}

/// A field whose type names the struct being defined needs indirection in Rust.
///
/// `pub const KDNode = struct { left : "?KDNode", ... }` maps to
/// `pub left: Option<KDNode>` inside `pub struct KDNode`, and rustc answers
/// `recursive type `KDNode` has infinite size ... insert some indirection (e.g. a
/// `Box`, `Rc`, or `&`)`. There is no version of this that compiles without one, so
/// this is not a choice about representation -- it is the difference between output
/// and no output. `Box` is the ownership-preserving one of the three rustc names.
///
/// Nine structs in the corpus refer to themselves; three of them are specs whose ONLY
/// remaining error is this one.
///
/// Deliberately narrow. `Vec<Name>` already carries its indirection and is left alone,
/// and so is anything more deeply nested than `Option<Name>` -- a type this does not
/// recognise keeps its current output rather than getting a guess.
fn box_if_self_referential(field_type: &str, struct_name: &str) -> String {
if struct_name.is_empty() {
return field_type.to_string();
}
if field_type == struct_name {
return format!("Box<{struct_name}>");
}
let opt = format!("Option<{struct_name}>");
if field_type == opt {
return format!("Option<Box<{struct_name}>>");
}
// `[Option<OctNode>; 8]`. An array is inline storage, so it is as recursive as a
// bare field; only the element needs the box. This was previously written off as
// "genuinely infinitely sized" -- it is not, `[Option<Box<OctNode>>; 8]` is finite
// and is what octree and quadtree need.
if let Some(rest) = field_type.strip_prefix('[') {
if let Some((elem, tail)) = rest.rsplit_once(';') {
let boxed = Self::box_if_self_referential(elem.trim(), struct_name);
if boxed != elem.trim() {
return format!("[{boxed};{tail}");
}
}
}
field_type.to_string()
}

fn gen_struct(&mut self, node: &Node) {
// The serde derives were unconditional, and the corpus compiles this
// output as a standalone `--crate-type lib` with no `--extern`. Every
Expand Down Expand Up @@ -23952,6 +23993,7 @@ impl RustCodegen {
if child.kind == NodeKind::ExprIdentifier && !child.name.is_empty() {
let field_name = &child.name;
let field_type = Self::t27_type_to_rust(&child.extra_type);
let field_type = Self::box_if_self_referential(&field_type, &node.name);
if field_type.trim() == "bool" {
self.bool_fields.insert(field_name.clone());
}
Expand Down
2 changes: 1 addition & 1 deletion bootstrap/stage0/FROZEN_HASH
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5b05ef6357a7139dbc16bd60977eda9294eecb01f9d2d3be58c8816796e418cc bootstrap/src/compiler.rs
6b3304d63e8f39cbb57953dbaf39769550a677d5565923a387bc4d6c94348f64 bootstrap/src/compiler.rs
20 changes: 20 additions & 0 deletions docs/now/2026-09-06-a-field-that-names-its-own-struct.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# NOW -- A field that names its own struct needs a Box (2026-09-06)

## A field that names its own struct needs a Box (Refs #3377)

- First fix in five passes to move the column, and the first whose target was PICKED:
`tri one-away` reported this class as the sole error of 3 specs whose count is exact,
and the repair moved exactly those 3.
- `pub left: Option<KDNode>` inside `pub struct KDNode` is infinitely sized. There is
no version that compiles without indirection, so nothing is chosen about representation
-- `Box` is the ownership-preserving one of the three names rustc itself offers.
- Two shapes. `Option<Name>` is kd_tree. `[Option<Name>; N]` is octree and quadtree,
and an earlier pass of mine wrote octree off as "genuinely infinitely sized". **That was
wrong**: an array is inline storage, only the element needs the box, and
`[Option<Box<OctNode>>; 8]` is finite.
- Measured, two pinned binaries from the same commit in ONE pass, 650 specs:
**357 -> 360, +3, zero regressions.**
- Nine structs in the corpus name themselves. Three were one-away and are now green; the
rest carry other errors.
- Narrow on purpose: `Vec<Name>` already carries indirection and is untouched, and a
shape this does not recognise keeps its current output rather than getting a guess.