Skip to content

Commit 68b29ef

Browse files
Agent Userclaude
andcommitted
rules/iostream: restore the missing t1 refcount target -- a latent tree-wide load failure
`src.cpp` declares `using t1 = std::ostream;` and `tgt_unsafe.rs` has a `t1`, but `tgt_refcount.rs` did not. That is the `using tN` with no matching tN target case, which aborts at LOAD TIME (translation_rule.cpp:233, `ir_src.json type entry has no matching IR target rule`) and under NDEBUG presents as rc=139 with no message. check-ir.sh reported `LOAD FAILURE (refcount model) -- this tree poisons EVERY translation`. It was LATENT, not new. rules/iostream had not been regenerated into a published tree since Cpp2Rust#164 made Rust type rules standalone functions, so nothing had ever exercised it; it surfaced only when the module was regenerated for 0edd622's ios_base::in/out keys. The same class of latent asymmetry was hit twice in one hour, which is why this commit spells the rule out in the file: A MODULE THAT HAS A tgt_refcount.rs MUST CARRY EVERY KEY IN IT, even where the body is byte-identical. The "a value-like key needs no refcount override" guidance is about the ir_refcount.json OVERLAY, and it does not license omitting a TYPE key from the target file. Body mirrors tgt_unsafe.rs's t1 verbatim, because a plain owned value is model-independent -- no Ptr, no raw pointer, nothing to re-shape. Deliberately NOT "improved": `File::open("")` always fails so that initializer would panic if it were ever materialised, which deserves its own look, but changing committed unsafe behaviour while fixing a load failure would conflate two things. Also recorded here because it cost two slots and is still open: refreshing pin/ir.v9 to HEAD exposed a SECOND, unrelated latent load failure, in rules/shared_ptr f1 -- `LLVM ERROR: Expr rule uses init but its src pack is not declared as Init<T, Args>`. That one is NOT fixed by this commit. f1 records as the bare `std::shared_ptr<T1> std::make_shared()` with the `Init<T1, Args>` pack LOST while both its targets emit `{"init": null}`; every working init user (unique_ptr f8, vector f112-114, vector_cxx11 f1-3, deque f12-13, deque_cxx11 f1-2) records an `init_type` pack and a `(&&...)` key. Removing the unused leading `typename T2` from f1 -- making it match unique_ptr f8 exactly -- did NOT change the recorded key, so that hypothesis is dead. pin/ir.v9 is green only because it deliberately retains the OLD pre-break shared_ptr IR, which is recorded in its provenance file; regenerating shared_ptr into it would re-poison every agent's baseline via newir.sh. The same error independently blocks all structured-binding measurement (`auto t = std::tie(x, y)` aborts identically), so it now gates the top measured row as well. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 0edd622 commit 68b29ef

1 file changed

Lines changed: 43 additions & 0 deletions

File tree

‎rules/iostream/tgt_refcount.rs‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,27 @@ use libcc2rs::*;
55
use std::os::fd::AsFd;
66

77
// TODO: t2 and t3 should be translated to Ptr<dyn Traits>
8+
// t1 -- `std::ostream` by VALUE (t2 is `std::ostream &`, t3 is `std::ostream *`).
9+
//
10+
// THIS WAS MISSING, AND ITS ABSENCE POISONED EVERY REFCOUNT TRANSLATION. src.cpp declares
11+
// `using t1 = std::ostream;` and tgt_unsafe.rs has a `t1`, but this file did not -- the
12+
// `using tN =` with no matching tN target case, which aborts at LOAD TIME
13+
// (translation_rule.cpp:233, `ir_src.json type entry has no matching IR target rule`) and
14+
// under NDEBUG presents as rc=139 with no message. `check-ir.sh` reported
15+
// `LOAD FAILURE (refcount model) -- this tree poisons EVERY translation`.
16+
// It was LATENT rather than new: rules/iostream had not been regenerated since #164 made
17+
// Rust type rules standalone functions, so no published tree had ever exercised it, and it
18+
// only surfaced when this module was regenerated for the ios_base::in/out keys.
19+
//
20+
// The body mirrors tgt_unsafe.rs's t1 verbatim because a plain owned value is
21+
// model-independent -- no Ptr, no raw pointer, nothing to re-shape. Deliberately NOT
22+
// "improved": `File::open("")` always fails so this initializer would panic if it were ever
23+
// materialised, which is worth a separate look, but changing committed unsafe behaviour while
24+
// fixing a load failure would conflate two things.
25+
fn t1() -> std::fs::File {
26+
std::fs::File::open("").unwrap()
27+
}
28+
829
fn t2() -> Ptr<std::fs::File> {
930
Ptr::null()
1031
}
@@ -28,3 +49,25 @@ fn f3() -> Ptr<::std::fs::File> {
2849
fn f4() -> Ptr<::std::fs::File> {
2950
libcc2rs::cerr()
3051
}
52+
53+
// f5/f6 -- std::ios_base::in / ::out. Bodies identical to tgt_unsafe.rs: these are plain
54+
// `unsigned int` constants (libcxx/ios:283-288, `typedef unsigned int openmode; in = 0x08;
55+
// out = 0x10`), so nothing here is model-dependent.
56+
//
57+
// THEY ARE RESTATED ANYWAY, AND THAT IS NOT OPTIONAL. 0edd6227 added them to src.cpp and
58+
// tgt_unsafe.rs only, on the reasoning that a value-like key needs no refcount override
59+
// because ir_unsafe.json is the unconditional base layer. That reasoning is right about the
60+
// OVERLAY and wrong about THIS module: because rules/iostream HAS a tgt_refcount.rs, omitting
61+
// a key from it leaves ir_refcount.json with 6 keys against ir_src.json's 9, and the
62+
// converter then ABORTS AT LOAD TIME in the refcount model -- `check-ir.sh` reported
63+
// `LOAD FAILURE (refcount model) -- this tree poisons EVERY translation` with a core dump.
64+
// So the rule is: a module that has a tgt_refcount.rs must carry EVERY key in it, even where
65+
// the body is byte-identical. (rules/mlir legitimately runs 151 src / 149 refcount keys, so
66+
// the omission is tolerated somewhere -- but not here, and check-ir.sh is the authority.)
67+
fn f5() -> u32 {
68+
0x08
69+
}
70+
71+
fn f6() -> u32 {
72+
0x10
73+
}

0 commit comments

Comments
 (0)