批8 (i) 小批: @raw_int 放宽接受指针(实测定名 TYP_PTR)+ 两向钉子判据 + diag_gate 夹具换形 - #134
Merged
Merged
Conversation
…ests 【改动】`src/compiler/checker.cr` 的 `@raw_int` 守卫(符号锚 `str_eq(name, "raw_int")`): 白名单由「dex / int」扩到「dex / int / **指针**」。加入标准 = **该类型的原值有语义** (dex 缩放位 · int 原值 · 指针地址字);`TYP_REF` / `TYP_SLICE` / `TYP_ARRAY` 等**仍拒绝**——聚合无「原值」概念、 `TYP_REF` 语义未实测 ⇒ **没证据就不扩**(与子步 0「range 门零命中就不写退出条款」同一条纪律)。 实现细节:判定写成 `av > TI_DEX_S && get_type_kind(av) == TYP_PTR`——类型表下标 0..8 是标量/占位 (`TI_INT`..`TI_DEX_S`),不加上界会把**标量下标当结构类型行读**(假阳性来源)。文案同步为 `@raw_int requires a dex (or int) or pointer expression`(全仓无测试断言旧文案,实测)。 【类型定名 = 实测定名,非假设】只加 `TYP_PTR` 后正控即绿 ⇒ `&x` 表达式解析到的就是 `TYP_PTR` 行; 补充证据 = 突变 M2(把放宽面扩到 `TYP_REF`)时 `&int` 形参负控**恰好翻红** ⇒ 该负控钉的确实是 `TYP_REF`。 【读数】批基点 `802bd24a` pre:`tests/suite/ptr_ref_first.cr` check = rc=1 · TF07×2 · TB01×1; 产物 ELF `fdf8cad6…`(28854B) · `.ccr` `3e27595e…`(95571B)。 改后:check = **rc=0 · 零诊断**(TF07 与其级联 TB01 同批消失);**产物逐字节不变**(诊断面改动,非代码生成); 程序 native rc=0 · 解释器 rc=0。 【判据】`tests/selfhost/test_raw_int_ptr.py`(入 `selfhost-tests`)19 项全绿: A 正控(诊断面零诊断 + 两腿值面)· B 负控 6 类(string/bool/array/slice/ref_type/struct ⇒ check 面 rc=1 + 恰 1 条 TF07 + 文案含 `or pointer`) · B' 既有 dex/int 形态仍受 · C 同源两次构建 ELF 一致。 **负控只写 check 面**:TF07 是 build-scope 豁免码(`diag.cr::diag_gate_exempt`)⇒ 「build 面零产物」在本批**恒假** (豁免未撤,撤条归 (甲) 刀 4)——build 面本批仍 rc=0 + 照出产物,不得当负控。 【突变自证两向(均断言命中目标)】M1 回退放宽 ⇒ 正控回到 pre 读数(rc=1 · TF07×2 · TB01×1)⇒ 正控有牙; M2 放宽过头(+TYP_REF)⇒ `ref_type` 负控翻红(且 slice/array/string 仍拒 ⇒ 钉子按类特异)。 【批报告登记(不落 `diag.cr`)】`diag.cr` 的 TF07 条目(含重复块 `183-186 ≡ 187-190`): 「EC_TF_ARG_TYPE 全仓唯一 raise 点」已因 2(a) 变为 **3 处**(`:4123` @raw_int + `:4191` @ptr_of + `:4197` @str_of)、 行号 `3727`→`4123` 已漂、位点锚 `ptr_ref_first.cr:8` 实为 **`:10`**、第二处引用的 `test_ccr_types.py:1805` 与该码无关 ——**撤条归 (甲) 刀 4**,届时连同重复块一并清理。
【为什么必须同批改】tests/selfhost/test_diag_gate.py 的 build 面正控原写 build_ok("tf07_tb01", "tests/suite/ptr_ref_first.cr", ("TF07","TB01")) —— 它把「该夹具产 TF07+TB01 且被豁免放行」钉成契约。(i) 放宽 @raw_int 接受指针后该夹具**不再产这两个码** ⇒ selfhost-tests 实测红(pos_tf07_tb01)。
【改法 = 换夹具保意图,不是删断言】改用**仍被拒**的串实参级联夹具(2×TF07 → 两侧 TI_NEVER → 1×TB01,与旧夹具**同形**)继续钉「build 面豁免码仍放行(rc=0 + 产物)**且仍被报出**」;原夹具另钉 (i) 的新语义 = **零诊断 + 产物**(build 面干净通过,codes=[])。
实测:级联夹具 check rc=1 · TF07×2 · TB01×1 / build rc=0 · 产物 ✓ · TF07×2 · TB01×1;原夹具 build rc=0 · 产物 ✓ · codes=[]。
复跑 test_diag_gate.py:**20/20 passed**(含两条新钉子)。档头注同步(写明 2026-09-19 (i) 换夹具及理由)。
…TI_DEX ⇒ 指针只是同类别里的又一类型、不引入新类别;「是否应要求 unsafe」是预存更大问题、不在本条解决(若将来裁定,会同时影响 dex/int 既有形态 ⇒ 属改契约批须单独立项)。另记文案单点:全仓仅 checker.cr 一处(bootstrap 侧不认识 raw_int、fail-closed 无副本),本档 B 腿即钉该单点。**doc-only(测试档头注释),判据逻辑零改动**。
…于注释) 【退回意见(team-lead 2026-09-19)】我新钉的 tf07_tb01_ptr_clean **弱于自己的注释**:注释写「零诊断 + 产物」, 而 build_ok(name, path) 不传 want_codes 时只断言「rc=0 + 产物存在」——**TF07 是 build-scope 豁免码 ⇒ 该条无论如何都过** ⇒ 无法区分「干净通过」与「仍产 TF07 但被豁免放行」,正是本批一直在处理的那个豁免面。 【修法】照同档 tf01 先例补**显式缺席断言**,拆两条: · check 面 pos_tf07_tb01_ptr_check_clean:rc=0 且输出**无** TF07、**无** TB01 —— **只有 check 面有意义**(不在 build-scope 豁免内); · build 面保留 build_ok(钉「能过 + 有产物」那一半)。 两条合起来才是「放宽后指针形态干净通过」。**突变覆盖**:M1(回退放宽)会同时打红这两条(check 面 TF07 复现 ⇒ 缺席断言失败)。 复跑 test_diag_gate.py **21/21 passed**;档头注同步写明拆两条及理由。 【自查(同档其它 build_ok 无 want_codes 者)】tf01_build_clean 已有配对(上方 check 面断言「无 TF01」); b04 的注释只声称「仍放行(rc=0 + 产物)」与代码一致、**无越权声称** ⇒ 两处无需改。
dslsdzc
added a commit
that referenced
this pull request
Sep 18, 2026
* docs((i) 小批记录): 实施记录 + **豁免面实证附件**(team-lead 2026-09-19 建议原样落纸) 本档 = (i) 小批(@raw_int 放宽接受指针,PR #134 → develop 08f0b65)的实施记录: 裁定与同文件约束 · 改动(含 av > TI_DEX_S 上界通用坑 · 文案单点 · 安全面边界)· pre/post 读数(产物逐字节不变)· 类型实测定名(M2 交叉证据)· 负控的面 · 突变两向 + **实测红项计数 1+1=2** · 既有判据换夹具重定 · diag.cr 四处失准登记(归 (甲) 刀 4)· 两条通用纪律。 **§4.1 = team-lead 指定原样落纸的实证**:同一 M1 突变下 build 面 build_ok(rc=0+有产物) **仍然 PASS** ⇒ 一句话证明「豁免面上的『能过』断言对该类回归完全不敏感,能抓住的只有 check 面缺席断言」—— 作为「断言弱于注释 / 零产物先问有没有豁免」那条通用纪律的**实证附件**(一次突变同时证伪弱判据、证实强判据)。 doc-only(新增 1 个 .md),src/ 与 tests/ 零改动 ⇒ 不撞 b8-e1 的批 2。**本地提交,不单推**(等下一批 PR 带上)。 * feat(canary D1 确定性闸门): canary ELF 两次构建逐字节对拍(+ 重锁前置落纸 + 两向自证) 【裁定】team-lead 2026-09-19 裁 (乙) 并放行(动 tools/baseline/ 与 b8-e1 的 checker.cr/tests 不撞文件): canary 的 5 个锁定值覆盖的是「与**旧值**比」(F3),**不是**「与**再一次构建**比」。差别在**重锁那一刻**最大—— 若某批合法改了码(须重锁)而同时引入非确定性,只比旧值 ⇒ 操作者采**一次**样即锁,此后 canary 全绿而产物每次都不一样。 ⇒ 新增 **D1**:同一 canary ELF **两次构建逐字节 **,与 F3 互补(F3 防无声变化 · D1 防非确定性)。 【实现】tools/baseline/canary_check.sh: · 新函数 determinism_gate(产物缺失 ⇒ fail-closed 红;不同 ⇒ 红 + 打印两侧 sha/尺寸,红必须可诊断); · collect_into 末尾对 **canary ELF 这一档**再构建一次(+1 clean-cache +1 构建)并过闸——**D1 红 ⇒ 采集阶段即失败,不进入 5/5 校验**(堵死「非确定性采样被当锁定值」这条路); · 自证新增 **S7 两向**(团队约定 #11):同文件⇒绿(防恒红)/ 异文件⇒红且命中诊断(防恒绿)⇒ 合成自证 6 → **8** 子检。 【落纸(你要求的两条)】① 正面断言 = 两次构建 相同;与锁定值比较**照旧保留**(两件都要)。 ② **接进重锁流程**:脚本档头 D1 契约块 + 表头各写明「**重锁前必须先看到 D1 绿**,否则可能把非确定值锁进表」。 【边界(按你裁)】只对**已构建的那一档**做,**不做全语料**;不新增 job; 四条不在本闸门覆盖内(如需另议)。 【读数】起点:canary 5 值(与本表同)+ 脚本时长 0.45–0.68s(早期 1.7/10.8s 读数为机器负载所致); **边际成本实测 = 单次 clean-cache + 构建 240B 语料 ≈ 0.05s**(3 次 0.049/0.057/0.049s)⇒ **远低于「时长翻倍即停」的红线**。 闸门端到端: + 5/5 PASS;载体判据 tests/harness/test_canary_carrier.py 期望 6→8 同步(pass=7 skip=0)。 【突变自证】MUT-D1(在 collect_into 内把第二次构建的产物扰动一字节,断言命中目标)⇒ rc=1 + + **** ⇒ 调用点是活的且 fail-closed。还原后逐字节核对 ✓。 * feat(canary D1 扩到 5 条 + 逐条点名 + 双突变自证): .ccr 四条纳入确定性闸门(team-lead 裁 ①) 【裁定理由】 恰恰是**序列化/顺序面**(段序 · intern 序 · 侧表顺序)——非确定性最可能在那里现形, 而 ELF 是按序发射的机器码;重锁流程覆盖**全部 5 个条目**,只保 ELF 等于**漏掉 4/5**。 【实现】collect_into 第二遍构建改为**全 5 条**(写入 $d/again/,5 次 clean-cache+构建,实测 +0.2s), 逐条过 determinism_gate 并传 **spec 名**作 label ⇒ 诊断形如 (**点名条目**, 否则一次红只说明「有非确定性」而不说去哪查)。档头 D1 契约块的覆盖面/边界同步改写(只 canary 两档的 5 个条目,不做全语料)。 【自证加强】S7b 除「命中 两次构建产物不同」外,**加断言输出含 **(把「诊断点名条目」编码成判据, 不写在报告句子里)。S7 仍为 2 子检 ⇒ 合成自证仍 **8/8**、carrier 期望计数**不变**(8)。 【双突变自证(均断言命中目标 + 点名到正确条目)】 · MUT-D1a 扰动 (ELF)⇒ rc=1 + + ; · MUT-D1b 扰动 ⇒ **ELF 条 PASS** 而 ⇒ **四条 .ccr 是「接上线的」不是「装了没接线」**,且点名精确到条目。 【读数】端到端 0.633/0.679s(另一次 9.9s = 机器负载;CPU 0.32+0.29s 不变)· 边际 5 次构建合计 ≈ 0.27s (单次 0.054/0.057/0.060s)⇒ 仍远低于「时长翻倍即停」。闸门:**5 条 D1 全 PASS** + 5/5 PASS(值一字未动)。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
摘要
(i)小批:@raw_int放宽接受指针。改动面 =src/compiler/checker.cr的@raw_int守卫一行条件 + 文案;判据 = 新套件
tests/selfhost/test_raw_int_ptr.py(挂selfhost-tests)。一、改动
白名单由「dex / int」扩到「dex / int / 指针」。加入标准 = 该类型的原值有语义:
dexintTYP_PTR)TYP_REF/TYP_SLICE/TYP_ARRAY等实现细节:判定写成
av > TI_DEX_S && get_type_kind(av) == TYP_PTR。上界不可省:类型表下标 0..8 是标量/占位(
TI_INT..TI_DEX_S),直接get_type_kind(标量下标)会读到占位行的 kind(假阳性来源)。文案同步为
@raw_int requires a dex (or int) or pointer expression(全仓无测试断言旧文案,实读确认)。二、类型定名 = 实测定名(不假设)
TYP_PTR后正控即绿 ⇒&x表达式解析到的就是TYP_PTR行(代码路径证据:一元取地址分支alloc_type(TYP_PTR, inner, 0))。TYP_REF):&int形参负控恰好翻红,而 slice/array/string 仍拒⇒ 该负控钉的确实是
TYP_REF,且钉子按类特异。二bis、安全面边界(明写,team-lead 开工单要求)
@raw_int现状不要求unsafe——本批不引入新类别:该内建本就接受TI_DEX(取缩放位原值),指针只是同一「取原值」类别里的又一个类型;本批不改变它的安全面。
@raw_int是否应要求unsafe」(与 2(a) 视图内建的安全面 (ii) 对齐)是预存的更大问题,不在本小批解决;若将来裁定要求,会同时影响
dex/int既有形态 ⇒ 属改契约批,须单独立项。checker.cr的@raw_int守卫;bootstrap 侧不认识raw_int,fail-closed、无第二份文案)⇒ 本批文案改动是单点改动,判据 B 腿即钉这个单点。
三、读数(批基点
802bd24a重采 pre)tests/suite/ptr_ref_first.crcheckfdf8cad6…(28854B).ccr3e27595e…(95571B)⇒ 本批是诊断面放宽:产物零变化(非代码生成改动)。
四、判据(
tests/selfhost/test_raw_int_ptr.py,19 项全绿)ptr_ref_firstcheck rc=0 零诊断 + 两腿值面(native rc=0 · 解释器 rc=0)。&int) / struct):check面 rc=1 +恰 1 条
error[TF07]+ 文案含or pointer。@raw_int(dex)/@raw_int(int)⇒ rc=0 零诊断(放宽的两向钉子:不得误伤)。M2 放宽过头(+
TYP_REF)⇒ref_type负控翻红。check面:TF07 是 build-scope 豁免码(diag.cr::diag_gate_exempt)⇒「build 面零产物」在本批恒假(豁免未撤,撤条归
(甲)刀 4)⇒ build 面本批仍 rc=0 + 照出产物,不得当负控。五、批报告登记(不落
diag.cr,撤条归(甲)刀 4)diag.cr的 TF07 条目(含重复块183-186 ≡ 187-190)现存四处失准:① 「
EC_TF_ARG_TYPE全仓唯一 raise 点」已因 2(a) 变为 3 处(checker.cr:4123@raw_int ·:4191@ptr_of ·:4197@str_of); ② 引用行号3727→ 实际4123(漂移); ③ 位点锚ptr_ref_first.cr:8(@raw_int)实为 **:10**(第 8 行是p := &x;); ④ 第二处引用的test_ccr_types.py:1805与该码无关(实读为 tk-dump 解析代码)。 **本 PR 不动diag.cr`**(该条目将被刀 4 整行撤销,重写即白做且会撞车)。六、既有判据的重定(换夹具保意图,不是删断言)
tests/selfhost/test_diag_gate.py的 build 面正控原写build_ok("tf07_tb01", "tests/suite/ptr_ref_first.cr", ("TF07","TB01"))—— 它把「该夹具产 TF07+TB01 且被豁免放行」钉成契约。(i)放宽后该夹具不再产这两个码 ⇒ 实测selfhost-tests红(pos_tf07_tb01)。改法:改用仍被拒的串实参级联夹具(2×TF07 → 两侧
TI_NEVER→ 1×TB01,与旧夹具同形),继续钉「build 面豁免码仍放行(rc=0 + 产物)且仍被报出」;原夹具另钉新语义 = 零诊断 + 产物(
codes=[])。实测:级联夹具 check rc=1 · TF07×2 · TB01×1 / build rc=0 · 产物 ✓ · TF07×2 · TB01×1;复跑
test_diag_gate.py20/20 passed。⇒ 豁免的覆盖面未减少,且新增一条「放宽后指针形态在 build 面干净通过」的钉子。
七、本地全量层
五档(
check/bootstrap-tests/selfhost-tests/suite/full-bootstrap,后两档按 team-lead 要求顺带跑——PR 门只 3/5)selftest-types/selftest-purity逐字节 +test_view_builtins(2(a))+test_raw_int_ptr(本批)。读数(本 head)见表末;
corec2/corec3cmpIDENTICAL(b940b141…)。