From d451caf0f1e121b0e7580e3e6a373421b7a57ba5 Mon Sep 17 00:00:00 2001 From: Codex Bot Date: Sun, 15 Nov 2026 19:25:51 +0800 Subject: [PATCH] docs(objects): clarify protocol tracking and ownership boundaries --- crates/core/src/eval.rs | 1 + crates/objects/src/builtins.rs | 18 +++++++++--------- crates/objects/src/changes.rs | 3 ++- crates/objects/src/object.rs | 5 ++++- crates/objects/src/store.rs | 7 +++++++ crates/objects/src/store_builtins.rs | 3 +++ 6 files changed, 26 insertions(+), 11 deletions(-) diff --git a/crates/core/src/eval.rs b/crates/core/src/eval.rs index 54489f9..0730e78 100644 --- a/crates/core/src/eval.rs +++ b/crates/core/src/eval.rs @@ -1126,6 +1126,7 @@ impl Vm { Value::Bool(value) => Ok(*value), Value::Text(value) => Ok(!value.is_empty()), Value::Number(value) => Ok(!value.is_zero()), + // 对象真值走 Store 的载荷协议;该底层入口当前不自动登记对象版本依赖。 Value::Object(reference) => self.is_true(*reference), } } diff --git a/crates/objects/src/builtins.rs b/crates/objects/src/builtins.rs index 2122185..9aa07e8 100644 --- a/crates/objects/src/builtins.rs +++ b/crates/objects/src/builtins.rs @@ -24,7 +24,7 @@ impl EndorStringObject { Self { text: text.into() } } - /// 字典 key_equal 和宿主查询借用 UTF-8 内容;借用不创建托管根,也不修改字符串。 + /// 字典 key_equal、eval 文本比较和宿主查询借用 UTF-8 内容;借用不创建托管根,也不修改字符串。 pub fn as_str(&self) -> &str { &self.text } @@ -41,7 +41,7 @@ impl EndorStringObject { } impl ObjectPayload for EndorStringObject { - /// ObjectStore::assign 调用,声明默认 assign_from 不会就地修改载荷;只读阶段可跳过写尝试,允许调用方重绑局部引用。 + /// ObjectStore::assign_from 调用,声明默认 assign_from 不会就地修改载荷;只读阶段可跳过写尝试,允许调用方重绑局部引用。 fn reference_assignment_only(&self) -> bool { true } @@ -120,7 +120,7 @@ impl EndorDictObject { } impl ObjectPayload for EndorDictObject { - /// ObjectStore::assign 调用,声明默认 assign_from 不会就地修改载荷;只读阶段可跳过写尝试,允许调用方重绑局部引用。 + /// ObjectStore::assign_from 调用,声明默认 assign_from 不会就地修改载荷;只读阶段可跳过写尝试,允许调用方重绑局部引用。 fn reference_assignment_only(&self) -> bool { true } @@ -174,7 +174,7 @@ impl EndorCellObject { } impl ObjectPayload for EndorCellObject { - /// ObjectStore::assign 调用,声明默认 assign_from 不会就地修改载荷;只读阶段可跳过写尝试,允许调用方重绑局部引用。 + /// ObjectStore::assign_from 调用,声明默认 assign_from 不会就地修改载荷;只读阶段可跳过写尝试,允许调用方重绑局部引用。 fn reference_assignment_only(&self) -> bool { true } @@ -276,7 +276,7 @@ impl ObjectPayload for EndorFunctionObject { fn is_function(&self) -> bool { true } - /// ObjectStore::assign 调用,声明默认 assign_from 不会就地修改载荷;只读阶段可跳过写尝试,允许调用方重绑局部引用。 + /// ObjectStore::assign_from 调用,声明默认 assign_from 不会就地修改载荷;只读阶段可跳过写尝试,允许调用方重绑局部引用。 fn reference_assignment_only(&self) -> bool { true } @@ -362,7 +362,7 @@ impl EndorBaseExceptionObject { self.suppress_context = true; self } - /// 分配前的构建器记录上下文强边;不自动改变 suppress_context,也不执行上下文异常。 + /// 分配前的构建器保存上下文句柄;allocate 后才登记强边,不自动改变 suppress_context 或执行异常。 pub fn with_context(mut self, context: ObjectRef) -> Self { self.context = Some(context); self @@ -390,11 +390,11 @@ impl EndorBaseExceptionObject { pub fn args(&self) -> &[Value] { &self.args } - /// ObjectStore::validate_builtin/trace 读取可选显式原因;返回借用身份,不创建新拥有根。 + /// ObjectStore::validate_builtin 和宿主读取可选显式原因;返回借用身份,不创建新拥有根。 pub fn cause(&self) -> Option { self.cause } - /// ObjectStore::validate_builtin/trace 读取可选上下文;即使已抑制显示,此强边仍参与追踪。 + /// ObjectStore::validate_builtin 和宿主读取可选上下文;即使已抑制显示,分配后的上下文边仍参与追踪。 pub fn context(&self) -> Option { self.context } @@ -413,7 +413,7 @@ impl EndorBaseExceptionObject { } impl ObjectPayload for EndorBaseExceptionObject { - /// ObjectStore::assign 调用,声明默认 assign_from 不会就地修改载荷;只读阶段可跳过写尝试,允许调用方重绑局部引用。 + /// ObjectStore::assign_from 调用,声明默认 assign_from 不会就地修改载荷;只读阶段可跳过写尝试,允许调用方重绑局部引用。 fn reference_assignment_only(&self) -> bool { true } diff --git a/crates/objects/src/changes.rs b/crates/objects/src/changes.rs index e07aa5a..6ca379a 100644 --- a/crates/objects/src/changes.rs +++ b/crates/objects/src/changes.rs @@ -23,7 +23,8 @@ pub struct ObjectChange { pub version: u64, } -/// Store::take_changes 返回上次取走后累计的合并结果;取走时重置内部批次。 +/// Store::take_changes 返回上次取走后累计发布的合并结果;取走时重置内部批次。 +/// 只读域中新建结果的允许写入更新对象版本,但不发布到此应用通知批次。 /// 溢出会丢弃精确条目并要求全面重验,消费者不能把空 changes 解释为没有修改。 #[derive(Debug, Default)] pub struct ChangeBatch { diff --git a/crates/objects/src/object.rs b/crates/objects/src/object.rs index f73bab2..48d3fb4 100644 --- a/crates/objects/src/object.rs +++ b/crates/objects/src/object.rs @@ -106,6 +106,7 @@ pub trait ObjectPayload: Any + fmt::Debug + Send + Sync { fn kind_name(&self) -> &'static str; /// Heap 在分配/替换载荷时收集内部强边(含重复边);GC 此后使用边快照。 + /// 单独调用 trace 只枚举借用身份,不替调用者取得拥有根。 /// 默认无边;实现不能在快照建立后通过内部可变性悄悄改变这些引用。 fn trace(&self, _visit: &mut dyn FnMut(ObjectRef)) {} @@ -249,6 +250,7 @@ impl EndorNativeFunctionObject { &self.name } /// 构造阶段补充完整签名,并同步数量限制;分配后签名中的引用由 Heap 边快照持有。 + /// 此构建器不验证签名结构;Store::native_signature 查询或 VM 调用时再校验完整契约。 pub fn with_signature(mut self, signature: crate::CallSignature) -> Self { self.arity = Some(signature.arity); self.signature = Some(signature); @@ -306,7 +308,8 @@ impl ObjectPayload for EndorNativeFunctionObject { fn call_arity(&self) -> Option { self.arity } - // VM 分派或宿主直接调用:先检查数量,再将同一参数切片借给 Rust 回调。 + // VM 分派或宿主直接调用:此载荷方法只检查数量,再将同一参数切片借给 Rust 回调。 + // 直接调用不执行 VM 的完整参数/返回类型检查,结果中的对象也仍借用;完整调用请经 Vm::call。 fn call(&self, arguments: &[Value]) -> Result { // 未声明 arity 时不在这里限制数量;声明后错误必须先于回调的任何副作用返回。 if let Some(arity) = self.arity { diff --git a/crates/objects/src/store.rs b/crates/objects/src/store.rs index 2cec058..6c6bb70 100644 --- a/crates/objects/src/store.rs +++ b/crates/objects/src/store.rs @@ -58,6 +58,7 @@ impl ObjectStore { } /// 缓存使用者重验一次观察;失效句柄或当前读取失败都表示依赖不再有效。 /// 经正常读取入口比较,因此若当前另有读取作用域,也会登记相应观察。 + /// 名称/字典种类比较当前状态而非永久失效位,删除遮蔽或恢复原值后可再次有效。 pub fn read_dependency_valid(&self, dependency: &crate::ReadDependency) -> bool { // 整对象检查版本;种类只检查仍是字典;名称检查当前 Option 是否保持相等。 match dependency { @@ -104,12 +105,14 @@ impl ObjectStore { } /// 宿主缓存或类型配置把有效强句柄转为弱句柄;不增加计数,也不消耗调用方已有根。 + /// 仍经 object 验证,处于只读追踪作用域时会登记此对象的版本读取。 pub fn downgrade(&self, reference: ObjectRef) -> Result { self.object(reference)?; Ok(WeakObjectRef(reference)) } /// 宿主升级弱句柄:存活则 retain 一份外部根,已释放返回 None;跨堆引用仍是错误。 + /// 存活验证经过 object,可能登记读取;升级失败不交付拥有根。 pub fn upgrade(&mut self, weak: WeakObjectRef) -> Result, VmError> { // 先验证代际与堆身份;只有 InvalidHandle 被解释为过期,其他错误原样传播。 match self.object(weak.0) { @@ -344,21 +347,25 @@ impl ObjectStore { } /// Vm::str 委托用户可见文本表示,默认载荷实现回退到 repr。 + /// 当前文本协议直接借用 Heap 载荷,不自动登记对象版本读取;不能把调用成功当成已收集内容依赖。 pub fn str(&self, reference: ObjectRef) -> Result { self.heap.get(reference)?.payload().str(reference) } /// VM 真值转换调用载荷协议;错误保持为错误,不把协议失败解释为 false。 + /// 当前真值协议直接借用 Heap 载荷,不自动登记对象版本读取;不能把调用成功当成已收集内容依赖。 pub fn is_true(&self, reference: ObjectRef) -> Result { self.heap.get(reference)?.payload().is_true() } /// 通用字典键准入及宿主哈希调用载荷协议,载荷可明确拒绝哈希。 + /// 当前哈希协议直接借用 Heap 载荷,不自动登记对象版本读取;不能把调用成功当成已收集内容依赖。 pub fn hash(&self, reference: ObjectRef) -> Result { self.heap.get(reference)?.payload().hash(reference) } /// VM 对象比较和字典对象键查找共用的双向协议;不运行源码函数比较方法。 + /// 此入口自身不登记双方版本;调用方其他读取可能另外收集依赖。 pub fn compare( &self, left: ObjectRef, diff --git a/crates/objects/src/store_builtins.rs b/crates/objects/src/store_builtins.rs index 024f182..5305e6d 100644 --- a/crates/objects/src/store_builtins.rs +++ b/crates/objects/src/store_builtins.rs @@ -80,6 +80,7 @@ impl ObjectStore { /// Vm 的执行入口及 eval 创建闭包时调用,组合代码、全局空间、默认值和捕获槽。 /// name 用作函数标识;code 指向可执行代码;closure 按该代码的自由变量顺序排列。 + /// 输入对象均借用,成功返回一份函数拥有根;代码、环境、默认值和捕获对象由函数内部边保活。 pub fn new_function( &mut self, name: impl Into, @@ -150,6 +151,7 @@ impl ObjectStore { /// eval 查找全局名和内置名时调用:既记录命中值,也记录“此名称不存在”。 /// 这里只查一个字典;全局未命中后再查 builtins 的顺序由 eval 决定。 /// 通用 dict_get 和条目迭代仍采用整字典依赖。 + /// 返回 Value 中对象身份仅借用;名称观察快照也不取得对象根。 pub fn dict_get_name( &self, dictionary: ObjectRef, @@ -201,6 +203,7 @@ impl ObjectStore { } /// Vm::dict_delete 删除一个键;返回值说明是否存在该键,错误通过 Result 单独传播。 + /// 缺键时只完成读取并返回 false,不触发替换写屏障;已有键在只读域内删除仍会被拒绝。 pub fn dict_delete(&mut self, dictionary: ObjectRef, key: &Value) -> Result { // 先复制载荷准备新状态;Rust clone 不 retain,提交前仍由旧字典持有原有引用边。 let mut dict = self.payload::(dictionary, "dict")?.clone();