已合并
fix: add local mode impl #2065
fix: add local mode impl #2065
已合并
songjian创建于 8月21日
songjian仓颉Developer
8月21日

Change Details (Required)

编译器支持local mode

Change Type (Required)

Simply save and click the checkbox, or when editing, change [ ] to [x] for the relevant item.

Self-Check of Changes (Required)

Please do not modify or delete the following options. Simply save and click the checkbox, or when editing, change [ ] to [x] for the relevant item.

Local Compilation Verification Results:

Local Test Case Verification Results:

https://gitcode.com/Cangjie/cangjie_compiler/issues/1095

likedislike
Pull Request已成功合入, 合并人@cangjie-ci
(感谢 songjian 的贡献)
Ssongjian仓颉Developer
8月21日 关联了issue:[Feature]: 编译器支持local mode
cangjie-ci成员
8月21日 评论:

PR创建成功通知 | 感谢您的贡献 🎉

您好!系统已检测到您成功创建 Pull Request(PR),感谢您对项目的支持与参与!以下几点需要您着重关注:

一、PR必须关联Issue ❗️

触发门禁检查的必要步骤:在PR描述框输入Issue完整链接,完成Issue关联。

请注意,一个 Issue 不能同时关联同一 base 仓库内同一个分支的多个开启状态的 PR

二、门禁触发规则 🔧

  1. 门禁类型判定:由Issue关联的PR所属代码仓数量决定
    • 关联多个代码仓PR:触发「多仓联合门禁」
    • 关联单个代码仓PR:触发「单仓门禁」
  2. 启动指令与检查范围:需主动回复指令:
    • 回复 "start build":执行Cangjie的主要基础检查,包含commit格式检查、静态告警分析、OAT开源声明检查、多平台构建、单元/集成测试等
    • 关联同一issue的多个PR,仅需在任意一个PR里回复触发一次门禁,该PR门禁通过后,所有PR都会添加Label和测试人
    • 每个pr只能同时运行一条CI流水线,如需重新启动,请先关闭运行中的,再评论触发门禁
    • Markdown修改仅触发文档类构建测试门禁,不会触发Cangjie的编译测试门禁
    • commit 信息格式请遵循:Conventional Commits 规范
    • 请保证每一条 commit 都已添加 Signed-Off-By 信息
    • 回复 "start build cov":执行覆盖率构建工程,生成该提交的增量代码覆盖率报告

三、合入条件 ⚠️

  • 满足最低评审人数,且评审问题需全部解决;
  • 禁止合入本人创建的PR,需由其他协作者操作;
  • 合并前确保关联流水线任务运行成功(build-test-passed);
  • 需求类覆盖率门禁:当关联的 Issue 标题以 [feature]: 开头(需求类 Issue)时,联合提交中属于 cangjie_compiler、cangjie_runtime、cangjie_stdx、cangjie_tools、llvm-project 仓库的 PR,必须先回复 "start build cov" 触发增量覆盖率流水线并通过,使 PR 获得 cov-test-passed 标签后方可合入。

四、合并PR ✅

回复 "start merge",CI流水线会自动检查所有关联PR的状态、版本号标签、检视意见密度、兼容性、需求类覆盖率门禁,若所有PR都满足合并条件,则将会同时合并所有PR。若存在不满足合并条件的PR,则不会合并任何PR。

如果希望不进行兼容性相关的检测,请任一合法审查人复制以下内容,在 start merge 前提交评论:

本 pr 不需要兼容性相关检测,对于引发的任何兼容性问题(即由于本 pr 合入将导致用户需适配代码的话),由本人承担。

If you wish to avoid compatibility-related checks, please have any approver copy the following content and submit it as a comment before sending start merge:

This PR does not require compatibility-related checks. For any compatibility issues caused by this PR (i.e., if the integration of this PR will require users to adapt their code), I will take full responsibility.

五、补充说明 📢

likedislike
Ccangjie-ci维护者
8月21日 添加了label:waiting-start-build
Ccangjie-ci维护者
8月21日 重置了测试状态
songjian成员
8月21日 评论:

start build

likedislike
此处折叠了1199条消息 查看更多
wangyinqiang
wangyinqiang成员9月12日进行代码检视2
src/CHIR/AST2CHIR/TranslateASTNode/TranslateArrayExpr.cpp
@@ -80,3 +29,1 @@
80- }
81- }
82- return funcCall;
29+ CJC_ABORT();
wangyinqiang
wangyinqiang9月12日评论:

[minor] 用 CJC_ABORT() 标记不可达路径,但它在 NDEBUG 下是空宏

问题:本函数删除了原有四条 RawArray 构造路径(共 175 行),非 VArray 分支替换为 CJC_ABORT(); return nullptr;。改道本身是完整的——InitArrayByCollection / InitArrayByItem / InitArrayByLambda 已彻底移除(定义 0、调用 0),Sema/Desugar/DesugarInTypeCheck.cpp:639 会把 ArrayExpr 标为 isValueArray = true,因此该路径确属不可达标记。问题在于 include/cangjie/Utils/CheckUtils.h:56 的 #define CJC_ABORT() 在 NDEBUG 下展开为空。

影响:若将来某条改动让非 VArray 的 ArrayExpr 重新到达 CHIR 翻译(新增数组字面量形式、或 desugar 条件被改窄),debug 构建会在正确位置 abort 便于定位;release 构建则返回一个 nullptr 的 Ptr<Value> 交给 CHIR 构造流程,在后续某个毫不相关的位置空指针解引用崩溃,或生成结构不完整的 CHIR。用户拿到的是一个指向错误位置的 ICE。

补 return nullptr 避免了掉出函数尾的 UB,这一点是对的;但也因此把「立刻暴露」变成了「静默传播」。

建议:换成 release 下也生效的形式(CJC_ABORT_WITH_MSG 或 InternalError),让 release 构建也给出明确的「非 VArray ArrayExpr 到达 CHIR 翻译」内部错误。

likedislike
songjian成员
9 天前 评论:

说的不对。不可达路径按仓内 CJC_ABORT 惯例,不改。

wangyinqiang
wangyinqiang成员9月12日进行代码检视2
demangler/DeCompression.cpp
@@ -523,17 +523,21 @@ size_t DeCompression<T>::ForwardName(T& mangled, size_t idx)
523523 numberLen++;
524524 }
525525 uint32_t number{};
526+#ifndef CANGJIE_ENABLE_GCOV
wangyinqiang
wangyinqiang9月12日评论:

[nit] 覆盖率构建下这处 try/catch 被整体剥离,畸形 mangled name 会由 return idx 优雅退出变成 std::terminate——建议改用不抛异常的 std::from_chars 替代 std::stoll,既消除 try/catch 也让两种构建行为一致(#ifndef CANGJIE_ENABLE_GCOV 包裹 try/catch 是本仓既有惯例,SafePointer.cpp、ParserUtils.cpp、DiagnosticEngine.cpp 等处已有同样写法,故仅记为 nit)。

likedislike
songjian成员
9 天前 评论:

说的不对。属仓内既有 GCOV 惯例,非本 PR 特有问题。

wangyinqiang
wangyinqiang成员9月12日进行代码检视2
src/IncrementalCompilation/PollutionAnalyzer.cpp
@@ -938,2 +939,3 @@
938939 auto primitiveType = StaticCast<const PrimitiveType*>(&extendedType);
939- return ASTMangler::ManglePrimitiveType(*primitiveType);
940+ return ASTMangler::ManglePrimitiveType(*primitiveType) +
941+ MangleUtils::MangleTypeMode(primitiveType->modal.ToModalInfo());
wangyinqiang
wangyinqiang9月12日评论:

[nit] 本 switch 里 PRIMITIVE_TYPE 与命中 LookupSpecialBuiltinType 的 REF_TYPE 追加了 MangleTypeMode,而一般 REF_TYPE 与 QUALIFIED_TYPE 两条分支(经 mangled2Decl 查表 return pair.first)没有——但这两条路径不可达:cangjie_test 的 Sema/modal/decl/extend_modal_type.cj 与 typealias_modal_type.cj 证明 extend T @local! 与 type L = T @local! 均在解析期被 parse_unexpected_modal_type 拒绝,故 extend 的被扩展类型与 type alias 目标类型都不可能带 modal,已补的两处其实也是死代码。建议二选一:去掉这两处并加注释说明「解析期即禁止,此处无需处理」(更贴近事实),或在 switch 之后统一补齐保持四条分支一致——目前两补两不补,容易被读成漏改(本次检视即误判过一次)。

likedislike
songjian成员
9 天前 评论:

说的不对。一般 REF/QUALIFIED 路径解析期已拒,非漏改。

wangyinqiang
wangyinqiang成员9月12日进行代码检视2
src/CHIR/AST2CHIR/TranslateASTNode/TranslateArrayExpr.cpp
@@ -80,3 +29,1 @@
80- }
81- }
82- return funcCall;
29+ CJC_ABORT();
wangyinqiang
wangyinqiang9月12日评论:

【更正】接本行上一条 [minor] 用 CJC_ABORT() 标记不可达路径 ——我给出的修法有误,请勿采用其中一项。

该条建议段写的是「换成 release 下也生效的形式(CJC_ABORT_WITH_MSG 或 InternalError)」。经复核,include/cangjie/Utils/CheckUtils.h 的 #ifdef NDEBUG 分支里两个宏都是空操作:

#define CJC_ABORT()                                      // 第 56 行
#define CJC_ABORT_WITH_MSG(msg) static_cast<void>(msg)   // 第 57 行

即改成 CJC_ABORT_WITH_MSG 后缺陷原样保留,却看起来已经修复——比不改更糟。

更正后的建议:只有 InternalError 成立。原意见其余部分(release 下静默返回 nullptr、后续在无关位置空指针崩溃、改道本身完整)不变。

为我发出这条错误建议致歉。

likedislike
songjian成员
9 天前 评论:

已阅。本条不采纳修改,维持 CJC_ABORT。

wangyinqiang
wangyinqiang成员9月12日进行代码检视2
schema/PackageFormat.fbs
@@ -108,0 +105,4 @@
105+ modal: ModalInfo;
106+}
107+ 
108+enum Mode: int16 {
wangyinqiang
wangyinqiang9月12日评论:

[major] 同一 namespace 下新增了两个同名的 Mode,当前仅因消费者集合不相交才编得过

问题:schema/ModuleFormat.fbs:8 与 schema/PackageFormat.fbs:7 都声明 namespace PackageFormat;。本次在这同一个命名空间里新增了两个同名但不同种类、不同语义的 Mode:

  • ModuleFormat.fbs:629:table Mode { local: LocalMode; },其中 LocalMode: uint8 { NOT, FULL, HALF }(AST / cjo 侧,由 src/Modules/ASTSerialization/ASTSerializeUtils.cpp 消费)
  • PackageFormat.fbs:108(本行):enum Mode: int16 { NONE, MAYBE, MUST }(CHIR 侧,由 CHIR 序列化消费)

二者种类不同(table vs enum)、底层类型不同(uint8 vs int16)、取值与语义都不同,却共用 PackageFormat::Mode 这一个全限定名。

影响:当前能编过只是因为两个生成头的消费者恰好不相交——ModuleFormat_generated.h 被 13 个文件引用、PackageFormat_generated.h 被 5 个,交集为空。任何一次把两个生成头引入同一编译单元的改动(新增一个既要读 cjo AST 又要读 CHIR 的工具、或某个头文件的传递包含发生变化)都会立刻触发重定义错误,且报错信息指向生成代码,排查成本高。即使不谈编译,PackageFormat::Mode 在阅读时已经有两种含义。

建议:把 CHIR 侧这个改名为 ChirMode(或 CHIRLocalMode),或将其移入独立 namespace。改名代价随消费者增多而上升,越早越便宜。

相关:src/Modules/ASTSerialization/ASTSerializeUtils.cpp:22 上另有一条意见,指出内部 Mode(IDEAL/NOT/FULL/HALF)与内部 ASTMode(NONE/NOT/HALF/FULL)的 FULL/HALF 顺序已经不一致。加上本条,这套模态枚举目前共有四个相关类型分布在三个命名层面,建议一并梳理命名。

likedislike
songjian成员
9 天前 评论:

说的不对。分属 ModuleFormat.fbs 与 PackageFormat.fbs 两文件、两套生成头,现有消费者也不共 TU,谈不上冲突。