Skip to content

Commit b0c33f9

Browse files
committed
the count was four and it is two, and the grouping used the wrong key
THE RE-MEASUREMENT AFTER THE WITHDRAWAL REFUTED A NUMBER THIS REPOSITORY HAD WRITTEN IN FIVE PLACES. `cenv.cppm`, `predefines.cppm`, `docs/21`, `docs/22` and the CHANGELOG all said the borrowed `__CYGWIN__` cost four members: archive, sqlite3, mimalloc, c-ares. The 30-member run on 2026.9.21.2 says otherwise. total failures 10 -> 5 newly failing none the windows.h group 4 -> 2, not 4 -> 0 And the half that did not hold is the useful half, because it says the DENOMINATOR was wrong: archive (xz) __CYGWIN__ correct cleared sqlite3 __CYGWIN__ correct cleared c-ares __CYGWIN__ WRONG still fails mimalloc __CYGWIN__ WRONG still fails c-ares reaches `windows.h` through `#ifdef HAVE_WINDOWS_H`, and that macro is defined by mcpp-index's own recipe in its Windows branch --- a recipe defect, the same shape as curl's `HAVE_LINUX_TCP_H`. mimalloc no longer reaches a header at all. ALL FOUR WERE GROUPED BY THEIR DIAGNOSTIC. Every one of them stopped at `windows.h`, so they were recorded as one cause. GROUPING BY DIAGNOSTIC IS NOT GROUPING BY CAUSE, and a count collected that way overstates what withdrawing a name can fix. This is the mirror of a lesson already in this repository: a conclusion gets re-checked, its REASONS do not. The conclusion --- withdraw the borrowed name --- was right and was re-verified. The number inside the reason was inherited from an earlier record three times over, into engine comments, a changelog and a pull request body, and nothing checked it until the measurement did. AND mimalloc IS A FINDING OF ITS OWN: fatal error: error in backend: Target OS doesn't support __builtin_thread_pointer() yet. `presents = "posix"` on Windows realises as `--target=x86_64-pc-cygwin`, and LLVM does not implement that builtin for that OS. Every previous note about the substitution discussed what the PREPROCESSOR sees --- the ABI unchanged, the link unchanged, only macro visibility different. This is the first measured cost that the CODE GENERATOR sees, and it is recorded rather than fixed: the repair belongs either in mimalloc's recipe or in the choice of substitute triple, and that is a measurement not yet taken. A tooling defect surfaced with it. The measurement recorded mimalloc as `fails: error: build failed`, because `compat.py`'s `first_diagnostic` matched none of its three patterns --- a backend error carries no `file:line:` and no `FAIL` --- and its fallback returns the LAST line, which is mcpp's own summary. A fallback that returns something diagnostic-shaped when the match failed is worse than returning nothing.
1 parent 9fa3e53 commit b0c33f9

7 files changed

Lines changed: 162 additions & 22 deletions

File tree

‎.agents/docs/2026-09-21-openkal-ecosystem-completion-and-acceptance.md‎

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,52 @@ static assertion failed: UnwindCursor<> does not fit in unw_cursor_t
198198
runtime 的清单从**索引**钉 `openkal-musl = "0.19.0"`。所以用 `openkal_ref` 验之前,
199199
musl 0.19.0 必须先登记进索引。
200200
201+
#### E1d — 「四个成员」是二,而那个分组按诊断而不是按真因(2026-09-21 重测)
202+
203+
撤销之后的 30 成员重测:**总失败 10→5,新增失败零**。但判据的另一半「`windows.h` 组
204+
4→0」没有达成——是 **4→2**,而未达成的原因不是撤销无效,是**这个组从一开始就数错了**。
205+
206+
| 成员 | 记的真因 | 实测真因 | 撤销后 |
207+
|---|---|---|---|
208+
| `archive`(经 xz) | `__CYGWIN__` | **对** | **清了** |
209+
| `sqlite3` | `__CYGWIN__` | **对** | **清了** |
210+
| `c-ares` | `__CYGWIN__` | **错**:`ares_setup.h:81` 是 `#ifdef HAVE_WINDOWS_H`,而那个宏由 `mcpp-index` 自己的配方在 `windows = {` 块里 `#define`(`compat.c-ares.lua:1283`) | 仍红 |
211+
| `mimalloc` | `__CYGWIN__` | **错**:已经不走到任何头文件 | 仍红 |
212+
213+
**四个是按「诊断」分的组。** 四个当时都停在 `windows.h`,于是被记成同一类。
214+
**按诊断分组不是按真因分组**,这样数出来的数目会高估一次撤销能修掉多少。
215+
216+
这条是[[reasons-written-from-memory-kill-good-fixes]] 的镜像:结论(「撤销是对的」)被
217+
复查并成立,而**理由里的那个数目从未被复查**,它被从上一份记录继承了三次——写进引擎注释、
218+
CHANGELOG 和 PR 正文,直到重测把它否掉。
219+
220+
**判据达成一半比没写判据更有价值**:没达成的那一半正是它指出分母错了的地方。
221+
222+
#### E1e — `mimalloc` 暴露替身三元组的一个代价,与宏无关
223+
224+
```
225+
fatal error: error in backend: Target OS doesn't support __builtin_thread_pointer() yet.
226+
```
227+
228+
`presents = "posix"` 在 Windows 上实现成 `--target=x86_64-pc-cygwin`。LLVM 没有为那个 OS
229+
实现 `__builtin_thread_pointer()`,而 mimalloc 用它取线程局部堆指针。
230+
231+
**这是这次替换的第一个被测量到的、超出宏名之外的代价。** 此前 `cenv.cppm` 关于替身三元组
232+
的全部记录都只讨论「预处理器看到什么」——ABI 不变、链接不变、只有宏可见性变。这条说明
233+
**代码生成器也看得见那个 OS**。
234+
235+
**可能的修法(都未验证)**:mimalloc 的配方关掉那条路径(它有 `MI_*` 配置);或替身三元组
236+
换一个 LLVM 实现了该 builtin 的 OS。**先量再选**——这条记在这里正是为了下一个人不必
237+
从三十个成员的诊断里重新走一遍。
238+
239+
#### 一条测量工具的缺陷:`mimalloc` 的真诊断被兜底吃掉了
240+
241+
重测里 `mimalloc` 记的是 `fails: error: build failed`——`compat.py` 的 `first_diagnostic`
242+
三条模式都没匹配(后端错误不带 `file:line:` 也不含 `FAIL`),于是兜底取了**最后一行**,
243+
而最后一行是 mcpp 自己的总结。真因要本机复现才拿得到。
244+
245+
**判据的兜底不能是「最后一行」**:它在匹配失败时给出一个看起来像诊断的东西,比留空更坏。
246+
201247
#### E1b — 引擎拥有的宏改为全大写(2026.9.21.2)
202248
203249
**状态**:已落地,与 E1 第三步同一个 PR(用户要求:不分开,免得发布周期太长)。
@@ -756,7 +802,7 @@ openkal-musl 0.18.0,而 0.18.0 当时还没进索引,消费者自己的 CI
756802

757803
| 编号 | 判据 | 怎么算通过 | 状态 |
758804
| --- | --- | --- | --- |
759-
| E1 | 30 成员重测 | `windows.h` 组 4→0 且总失败不增 | **待测**(由移 `pins.toml` 的那个 PR 触发);`openkal-cross` 九格已全绿 |
805+
| E1 | 30 成员重测 | `windows.h` 组 4→0 且总失败不增 | **一半达成,而未达成的那半否掉了判据自己的分母**:总失败 10→5、新增失败为零;但该组实际只有两个成员读 `__CYGWIN__`,见 §2.1 E1d |
760806
| E1b | 大写重命名 | 上一版红、本版绿 | **已通过**:验证脚本 B 段,`2026.9.21.1` fails=2 → `2026.9.21.2` fails=0 |
761807
| E1c | 交叉验证协议的反向 | `openkal_ref` 留空时行为不变 | **已落地** |
762808
| E2 | 引用未提供接口的符号 | 链接期被点名拒绝;声明正确时零开销 | **退出本轮**:阻塞是设计决定不是工作量,见 §2.1 |

‎CHANGELOG.md‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,38 @@
55

66
## [Unreleased]
77

8+
### 更正:那个「四个成员」是二,而分组用错了依据
9+
10+
2026.9.21.2 的条目、`cenv.cppm` 与 `predefines.cppm` 的注释、`docs/21` 与 `docs/22`
11+
都写着「借来的 `__CYGWIN__` 代价是四个成员:archive、sqlite3、mimalloc、c-ares」。
12+
**撤销之后的重测把这个数目否掉了。**
13+
14+
| 成员 | 记的真因 | 实测真因 | 撤销后 |
15+
|---|---|---|---|
16+
| `archive`(经 xz) | `__CYGWIN__` | **对** | **清了** |
17+
| `sqlite3` | `__CYGWIN__` | **对** | **清了** |
18+
| `c-ares` | `__CYGWIN__` | **错**:`#ifdef HAVE_WINDOWS_H`,而那个宏由 mcpp-index 自己的配方在 windows 分支 `#define` | 仍红 |
19+
| `mimalloc` | `__CYGWIN__` | **错**:已经不走到任何头文件——`error in backend: Target OS doesn't support __builtin_thread_pointer() yet` | 仍红 |
20+
21+
**四个是按「诊断」分的组,不是按「真因」。** 四个都停在 `windows.h`(mimalloc 当时如此),
22+
于是被记成同一类。**按诊断分组不是按真因分组**,这样数出来的数目会高估一次撤销能修掉多少。
23+
24+
这条更正本身来自判据:重测把总失败从 10 降到 5、**新增失败为零**,而「`windows.h` 组 4→0」
25+
这半条没有达成——是 4→2。**一个达成了一半的判据,比一个没写的判据更有价值:它指出了
26+
分母是错的。**
27+
28+
### `mimalloc` 暴露出替身三元组的一个代价,与宏无关
29+
30+
```
31+
fatal error: error in backend: Target OS doesn't support __builtin_thread_pointer() yet.
32+
```
33+
34+
`presents = "posix"` 在 Windows 上实现成 `--target=x86_64-pc-cygwin`。LLVM 没有为那个
35+
OS 实现 `__builtin_thread_pointer()`,而 mimalloc 用它取线程局部堆指针。**这是替身
36+
三元组的第一个被测量到的、超出宏名之外的代价**;先前关于这次替换的记录只讨论了预处理器
37+
看到什么。
38+
39+
840
## [2026.9.21.2] - 2026-09-21
941

1042
### 引擎拥有的宏改为全大写

‎docs/21-the-target-triple.md‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,10 +683,21 @@ rule: a name mcpp owns means what mcpp says it means, while `__OPENKAL__` is
683683
owned and names *openkal* rather than mcpp. The alternative — borrowing —
684684
was tried. `__CYGWIN__` was left defined so that code needing "PE object
685685
format, POSIX C environment" would have a name, and a 30-member measurement
686-
found four members reading it as *Win32 is available* and reaching `#include
686+
found members reading it as *Win32 is available* and reaching `#include
687687
<windows.h>`, which is what upstream means by it. **A borrowed name means what
688688
the lender's history made it mean**, not what the borrower intended.
689689

690+
**That count was four and it is two** (corrected 2026-09-21 against the
691+
re-measurement on the release that withdrew the name). `archive` (through xz)
692+
and `sqlite3` read it; both cleared. The other two were grouped with them
693+
because all four stopped at `windows.h`, and their guards differ: `c-ares`
694+
reaches the header through `#ifdef HAVE_WINDOWS_H`, which this ecosystem's own
695+
recipe defines in its Windows branch, and `mimalloc` no longer reaches a
696+
header at all — it fails in the code generator on a builtin LLVM does not
697+
implement for the substitute triple's OS. **Grouping by diagnostic is not
698+
grouping by cause**, and a count collected that way overstates what a
699+
withdrawal can fix.
700+
690701
`__unix__` is the exception that proves the rule: mcpp SUPPLIES it rather than
691702
owning it, so it keeps the standard spelling and mcpp may not change its
692703
meaning. Read it exactly as on any other POSIX system.

‎docs/22-target-side.md‎

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -441,12 +441,22 @@ an ordinary Windows build still has `_WIN64`.
441441

442442
**`__CYGWIN__` is still defined, and that is a sequence rather than a
443443
decision to keep it.** The 30-member measurement settled that the borrowed
444-
name costs four members: `archive`, `sqlite3`, `mimalloc` and `c-ares` each
445-
stop at `#include <windows.h>`, reached through
444+
name costs members that stop at `#include <windows.h>`, reached through
446445
`#if defined(_WIN32) || defined(__CYGWIN__)`. Upstream means *Win32 is
447-
available* by it — mimalloc states so in the guard itself, sqlite3 lists it
448-
under `SQLITE_OS_WIN`. **A borrowed name means what the lender's history made
449-
it mean**, not what the borrower intended.
446+
available* by it — sqlite3 lists it under `SQLITE_OS_WIN`. **A borrowed name
447+
means what the lender's history made it mean**, not what the borrower
448+
intended.
449+
450+
**The count was four and it is two** (corrected 2026-09-21). `archive`
451+
(through xz) and `sqlite3` read the name; both cleared on the release that
452+
withdrew it. `c-ares` and `mimalloc` were grouped with them because all four
453+
stopped at `windows.h`, and neither was this name's doing: `c-ares` reaches
454+
the header through `#ifdef HAVE_WINDOWS_H`, a macro mcpp-index's own recipe
455+
defines in its Windows branch, and `mimalloc` no longer reaches a header —
456+
it fails in the code generator with *Target OS doesn't support
457+
`__builtin_thread_pointer()` yet*, which is a property of the substitute
458+
triple rather than of any macro. **Grouping by diagnostic is not grouping by
459+
cause.**
450460

451461
Withdrawing it was tried and broke the two headers above, which read it for
452462
want of any other target-wide name. libunwind's `static_assert` failed

‎docs/zh/21-the-target-triple.md‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,10 +599,17 @@ ABI 给记录定尺寸。呈现 POSIX 的 Windows 目标**有意**没有 `_WIN32
599599
`__MCPP_` 这个前缀是承重的,但它是**前缀**而不是规则的全部:**一个 mcpp 拥有的名字,语义
600600
由 mcpp 自己定**,而 `__OPENKAL__` 同样是拥有的,它命名的是 *openkal* 而不是 mcpp。另一条
601601
路——**借用**——试过:`__CYGWIN__` 曾被保留定义,为的是让需要「PE 目标文件格式 + POSIX C
602-
环境」的代码有个名字,而 30 成员测量发现四个成员把它读成「**Win32 可用**」并走向
602+
环境」的代码有个名字,而 30 成员测量发现有成员把它读成「**Win32 可用**」并走向
603603
`#include <windows.h>`——那正是上游用它表达的意思。**一个借来的名字,语义由借出方的历史
604604
决定**,不由借用方的意图决定。
605605

606+
**那个数目写的是四,实际是二**(2026-09-21 按撤销该名字那一版的重测更正)。`archive`
607+
(经由 xz)与 `sqlite3` 确实读它,两个都清了。另外两个是被归进来的——四个都停在
608+
`windows.h`——而它们的守卫并不相同:`c-ares` 走的是 `#ifdef HAVE_WINDOWS_H`,那个宏由
609+
本生态自己的配方在 windows 分支里 `#define`;`mimalloc` 已经不再走到任何头文件,它死在
610+
代码生成器里,用的那个 builtin 在替身三元组的 OS 上 LLVM 没有实现。**按诊断分组不是按
611+
真因分组**,这样数出来的数目会高估一次撤销能修掉多少。
612+
606613
`__unix__` 是印证这条规则的例外:mcpp **供给**它而不拥有它,所以它保持标准拼法,mcpp 也
607614
不得改变它的含义。读它就按在任何别的 POSIX 系统上那样读。
608615

‎src/toolchain/cenv.cppm‎

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,17 @@
8282
// defining it produces more new failures than it fixes, the answer flips".
8383
//
8484
// The measurement settled the THIRD-PARTY half (2026-09-20, 60 member-target
85-
// combinations): keeping it costs four members, each stopping at
85+
// combinations): keeping it costs members that stop at
8686
// `#include <windows.h>` reached through `#if defined(_WIN32) ||
8787
// defined(__CYGWIN__)`. Upstream means "Win32 is available" by the name ---
88-
// mimalloc says so in the guard's own comment, sqlite3 lists it under
89-
// `SQLITE_OS_WIN`. A BORROWED NAME MEANS WHAT THE LENDER'S HISTORY MADE IT
90-
// MEAN, not what the borrower intended by it.
88+
// sqlite3 lists it under `SQLITE_OS_WIN`. A BORROWED NAME MEANS WHAT THE
89+
// LENDER'S HISTORY MADE IT MEAN, not what the borrower intended by it.
90+
//
91+
// THE COUNT SAID FOUR AND IT WAS TWO. Corrected against the re-measurement on
92+
// 2026.9.21.2: `archive` and `sqlite3` read the name and both cleared.
93+
// `c-ares` and `mimalloc` were grouped with them because all four stopped at
94+
// `windows.h`, and a shared diagnostic is not a shared cause --- see the
95+
// emission site below.
9196
//
9297
// WITHDRAWING IT WAS TRIED TOO EARLY ONCE, AND BROKE THIS ECOSYSTEM'S OWN
9398
// INSTALLED HEADERS. `openkal-musl`'s `bits/setjmp.h` and
@@ -328,11 +333,30 @@ inline std::expected<Realisation, std::string> realise(
328333
// `__CYGWIN__` IS WITHDRAWN HERE, AND THAT IS THE LAST STEP OF
329334
// A SEQUENCE RATHER THAN A DECISION TAKEN ON ITS OWN. The
330335
// 30-member measurement settled that the borrowed name costs four
331-
// members (archive, sqlite3, mimalloc, c-ares stop at
332-
// `#include <windows.h>` through `#if defined(_WIN32) ||
333-
// defined(__CYGWIN__)`; upstream means "Win32 is available" by
334-
// it, as mimalloc's own guard comment says). The three steps, in
335-
// the order they were taken:
336+
// members that stop at `#include <windows.h>` through
337+
// `#if defined(_WIN32) || defined(__CYGWIN__)`; upstream means
338+
// "Win32 is available" by it. The three steps, in the order they
339+
// were taken:
340+
//
341+
// THE COUNT WAS FOUR AND IT IS TWO, and recording the correction
342+
// matters more than the number. The re-measurement on this
343+
// release cleared `archive` and `sqlite3`; `c-ares` and
344+
// `mimalloc` remain, and neither was ever this name's doing:
345+
//
346+
// c-ares `#ifdef HAVE_WINDOWS_H`, and that macro is defined
347+
// by mcpp-index's own recipe in its Windows branch.
348+
// A recipe defect, the same shape as curl's
349+
// `HAVE_LINUX_TCP_H`.
350+
// mimalloc no longer reaches a header at all. It fails in the
351+
// code generator: "Target OS doesn't support
352+
// __builtin_thread_pointer() yet" --- LLVM does not
353+
// implement that builtin for the substitute triple's
354+
// OS. THE SUBSTITUTION HAS A COST BEYOND MACRO NAMES,
355+
// and this is the first measurement of one.
356+
//
357+
// All four were grouped by their DIAGNOSTIC. Grouping by
358+
// diagnostic is not grouping by cause, and a count collected that
359+
// way overstates what withdrawing the name can fix.
336360
//
337361
// 1. 2026.9.21.1 defined mcpp's own name beside the borrowed
338362
// one; 2026.9.21.2 re-spelt it `__MCPP_TARGET_WINDOWS__`.

‎src/toolchain/predefines.cppm‎

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,21 @@
5151
// THE `__MCPP_` PREFIX IS LOAD-BEARING. A name mcpp owns means what mcpp says
5252
// it means. The alternative was tried: `__CYGWIN__` was left defined so that
5353
// code needing "PE object format, POSIX C environment" would have a name, and
54-
// a 30-member measurement found four members reading it as "Win32 is
55-
// available" and reaching `#include <windows.h>` --- which is what upstream
56-
// means by it (mimalloc says so in the guard's own comment; sqlite3 lists it
57-
// under `SQLITE_OS_WIN`). A BORROWED NAME MEANS WHAT THE LENDER'S HISTORY
58-
// MADE IT MEAN, not what the borrower intended.
54+
// a 30-member measurement found members reading it as "Win32 is available"
55+
// and reaching `#include <windows.h>` --- which is what upstream means by it
56+
// (sqlite3 lists it under `SQLITE_OS_WIN`). A BORROWED NAME MEANS WHAT THE
57+
// LENDER'S HISTORY MADE IT MEAN, not what the borrower intended.
58+
//
59+
// THE COUNT WAS FOUR AND IT IS TWO, corrected 2026-09-21 against the
60+
// re-measurement on the release that withdrew the name. `archive` (through
61+
// xz) and `sqlite3` read it and both cleared. The other two were grouped by
62+
// their diagnostic --- all four stopped at `windows.h` --- rather than by
63+
// their guard, and the guards differ: `c-ares` reaches it through
64+
// `#ifdef HAVE_WINDOWS_H`, a macro this ecosystem's own recipe defines in its
65+
// Windows branch, and `mimalloc` does not reach it at all any more; it fails
66+
// in the code generator on `__builtin_thread_pointer()`, which LLVM does not
67+
// implement for the substitute triple's OS. GROUPING BY DIAGNOSTIC IS NOT
68+
// GROUPING BY CAUSE.
5969
//
6070
// ── STABILITY ──────────────────────────────────────────────────────────────
6171
//

0 commit comments

Comments
 (0)