Files
endorphin-tabularium-docs/content/docs/language-design/04-questions.md
T
codex-bot ef1ba88161
Verify and deploy Tabularium / verify-and-deploy (push) Waiting to run
Add language design question collection with discussion decisions and provenance
2026-10-28 14:02:12 +08:00

162 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 04 · 存储与生命周期
0/20 项已确认。当前推进 04-01;本分类尚未完成选择。
本页整理原讨论的问题、验收要求和候选方案。勾选代表讨论中已确认的规则,不代表编译器或运行时已经实现。
## 04-01 赋值的默认语义
- [ ] 待讨论
明确赋值默认是独立值、共享还是移动;是否按值的类别区分,以及如何识别这种区别。
## 04-02 创建、身份与存储位置
- [ ] 待讨论
明确何时产生新实例、身份是否可观察,以及存储位置和地址是否属于语言保证。依赖:对象与类型模型。
## 04-03 初始化流程
- [ ] 待讨论
明确初始化顺序、必需字段、默认值和“可正常使用”的判定条件。
## 04-04 初始化期间的访问与逃逸
- [ ] 待讨论
明确未完成初始化的值能否被读取、调用、共享或捕获,以及违规行为。
## 04-05 初始化失败
- [ ] 待讨论
明确失败如何传播、已初始化部分如何清理,以及外部可观察状态的保证。
## 04-06 别名与修改权限
- [ ] 待讨论
明确多个引用能否同时存在、谁能修改,以及修改对其他持有者是否可见。
## 04-07 复制规则
- [ ] 待讨论
明确哪些值可复制、浅复制与深复制的含义、内部共享关系及复制失败行为。
## 04-08 移动规则
- [ ] 待讨论
明确是否支持移动、何时发生、源值之后能做什么,以及禁止移动的情况。
## 04-09 跨函数与闭包传递
- [ ] 待讨论
明确传参、返回值、闭包捕获沿用哪些生命周期规则,局部值逃逸如何处理。依赖:函数与闭包相关规则。
## 04-10 所有权与借用
- [ ] 待讨论
明确是否存在所有者、借用及其期限;哪些约束由静态检查或运行时检查保证。依赖:类型系统。
## 04-11 引用失效与悬空访问
- [ ] 待讨论
明确销毁、容器变化、存储迁移等情况下引用何时失效,以及失效访问的处理。
## 04-12 自动回收机制
- [ ] 待讨论
明确采用作用域释放、引用计数、追踪式 GC 或混合机制,并区分语言保证与实现自由。
## 04-13 循环引用与弱引用
- [ ] 待讨论
明确循环如何处理,是否提供弱引用,以及弱引用失效后的访问结果。
## 04-14 销毁时机与顺序
- [ ] 待讨论
明确销毁是否及时、顺序是否保证,以及正常退出和提前退出时的行为。
## 04-15 清理中的异常行为
- [ ] 待讨论
明确清理失败、重复清理、清理期间重入,以及重新发布待销毁值的处理规则。
## 04-16 非内存资源
- [ ] 待讨论
明确文件、锁等资源如何及时释放,是否支持显式关闭或作用域管理,以及关闭后操作的结果。
## 04-17 用户自定义生命周期操作
- [ ] 待讨论
明确哪些创建、复制、移动、清理操作允许定制,其触发时机与限制。依赖:定制协议。
## 04-18 分配失败与手动存储能力
- [ ] 待讨论
明确内存不足如何表现,以及是否暴露手动分配、释放或分配器选择;不支持也须明确。
## 04-19 并发、异步与外部接口边界
- [ ] 待讨论
明确跨执行单元共享或转移、任务取消、外部代码持有值时的生命周期契约;不支持的能力明确排除。依赖:相应并发及外部接口规则。
## 04-20 跨分类一致性验收
- [ ] 待讨论
用创建、共享、传递、失败、退出的完整例子检查已定规则;解决与类型、对象、协议和运行时规则的冲突。
## 当前问题的方案与语言对照
以下沿用原讨论材料;建议和参考语言的做法均不自动成为本语言规则。
当前仍是 **04-01:`b = a` 默认意味着什么?** 重点看两个问题:修改 `b` 是否影响 `a`,赋值后还能否使用 `a`。
- **Python:赋值建立绑定,不复制对象。**
`a = [1]; b = a; b.append(2)` 后,`a` 也是 `[1, 2]`。但给 `b` 重新赋值不会改变 `a` 的绑定。共享很方便,代价是可变对象的修改会沿别名传播。对我们的启发是:必须分清“修改同一个值”和“变量改为指向另一个值”。这是 Python 的语义,不依赖 CPython 的引用计数实现。[官方说明](https://docs.python.org/3/library/copy.html)
- **JS:对象赋值保留同一对象;TS 沿用这一运行时行为。**
`const a = {n: 1}; const b = a; b.n = 2` 后,`a.n` 为 `2`。`const` 限制重新赋值,不会冻结对象;数字等原始值则没有可共享修改的内部状态。TS 的类型标注不会让赋值自动复制对象。好处是对象共享直接,代价是静态类型本身不消除别名影响。启发是:绑定是否可改、值是否可变、是否共享,需要分别规定。[JS 规范](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-assignment-operators-runtime-semantics-evaluation)、[TS 文档](https://www.typescriptlang.org/docs/handbook/2/basic-types.html#erased-types)
- **Go:复制赋给变量的值,但不递归复制它引用的数据。**
`a := [1]int{1}; b := a; b[0] = 2` 后,`a[0]` 仍为 `1`;换成切片 `a := []int{1}`,同样操作后 `a[0]` 为 `2`,因为复制的切片描述信息仍引用同一底层数组。好处是支持直接的数据复制,也能方便共享;代价是必须理解类型内部是否含引用。启发是:**“赋值复制值”不保证整份数据相互独立。** [Go 规范](https://go.dev/ref/spec#Assignment_statements)
- **Rust:赋值根据类型发生复制或移动。**
`let a = 1; let b = a;` 后仍可读 `a`,因为整数实现了 `Copy`;`let a = String::from("hi"); let b = a;` 后再读取 `a` 会被编译器拒绝。好处是无需隐式复制字符串,也能明确资源归属;代价是使用者需要理解移动、借用和复制能力。启发是:按类型区分可行,但需要类型系统支撑;“放在栈上还是堆上”并非判断复制或移动的规则。[Rust 官方教程](https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html)
回到我们的待选方案:
| 方案 | 普通可变数据的 `b = a` |
|---|---|
| **A:默认独立值** | 修改 `b` 不影响 `a`;需要明确独立性覆盖到哪一层。 |
| **B:默认共享** | 修改共享内容会影响 `a`;需要独立副本时显式复制。 |
| **C:默认移动** | 转移使用资格;之后不能继续读取原来的 `a`。 |
| **D:按类别区分** | 为普通数据、共享引用、唯一资源分别规定行为;类别必须可识别。 |
**我的建议是先从 A 或 B 确定普通可变数据的使用体验**,再在复制、移动任务中检查其他类别是否需要不同规则。这样能先明确用户可观察的行为,不必提前决定完整类型系统或回收机制。这只是推进建议,尚未替你选择。
对于普通可变记录或序列,你更希望默认 **A:各自独立**,还是 **B:共享修改**?如果你希望所有权成为语言的基础,也可以直接选 C 或 D。
## 讨论来源
《语言设计 04:存储与生命周期》,整理日期 2026-10-28。章节编号沿用原清单。