docs(objects): explain capability conformance and annotation resolution

This commit is contained in:
2026-11-15 17:40:20 +08:00
parent 2e48e7455c
commit e5da8055e0
+125 -2
View File
@@ -975,16 +975,22 @@ impl ObjectStore {
})
}
/// 类型附着、字段/方法更新和能力查询共用:沿父链收集去重的借用能力身份。
fn inherited_traits(&self, definition: ObjectRef) -> Result<Vec<ObjectRef>, VmError> {
// 去重能力身份,不建立堆外拥有注册表或延长能力寿命。
let mut found = std::collections::BTreeSet::new();
// 从类型自身开始,继承能力和本层能力一起核对。
let mut current = Some(definition);
// 沿固定基类链逐层读取,不按名称猜测类型。
while let Some(definition) = current {
// 验证类型载荷后才读取其基类或能力列表。
let definition = self.payload::<EndorTypeObject>(definition, "Type")?;
found.extend(definition.traits.iter().copied());
current = definition.base;
}
Ok(found.into_iter().collect())
}
/// 能力验证单项方法存在及数量,完整签名存在时再调用 contracts 的替换检查。
fn validate_requirement(
&self,
capability: ObjectRef,
@@ -993,6 +999,7 @@ impl ObjectStore {
definition: ObjectRef,
defer_unknown: bool,
) -> Result<(), VmError> {
// 构造带能力名/方法名的错误,调用方不需要解析诊断文本定位失败。
let invalid = |reason| VmError::TraitViolation {
capability: self
.payload::<EndorTraitObject>(capability, "Trait")
@@ -1002,15 +1009,19 @@ impl ObjectStore {
method: requirement.name.clone(),
reason,
};
// 能力要求的方法必须实际存在,不能以缺少元数据替代。
let function = function.ok_or_else(|| invalid("required method is missing"))?;
// 查询函数可见数量约束;缺失原生数量元数据不能证明满足能力。
let arity = self
.call_arity(function)?
.ok_or_else(|| invalid("required member has no positional signature"))?;
// 能力最小数量不含 self,校验时加一个显式接收者。
if !arity.accepts(requirement.parameters + 1) {
return Err(invalid(
"positional parameter count does not match (including self)",
));
}
// 完整签名存在时还要验证参数/返回/效果,不只检查数量。
if let Some(expected) = self
.payload::<EndorTraitObject>(capability, "Trait")?
.signatures
@@ -1027,14 +1038,18 @@ impl ObjectStore {
}
Ok(())
}
/// 能力声明/查询检查全部要求,递归定义通过 with_trait_check 防止无限重入。
fn validate_trait(
&self,
definition: ObjectRef,
capability: ObjectRef,
defer_unknown: bool,
) -> Result<(), VmError> {
// 递归检查对按定义/能力区分,回调结束后 RAII 清理标记。
self.with_trait_check(definition, capability, || {
// 能力载荷先验证,再借用名称/完整签名/最小要求。
let contract = self.payload::<EndorTraitObject>(capability, "Trait")?;
// 遍历能力全部要求,任一失败阻止声明/更新。
for requirement in &contract.requirements {
self.validate_requirement(
capability,
@@ -1047,7 +1062,9 @@ impl ObjectStore {
Ok(())
})
}
/// 源码类创建后检查所有继承能力,允许暂缓尚未解析的源码注解。
fn validate_inherited_traits(&self, definition: ObjectRef) -> Result<(), VmError> {
// 全部继承能力都参与,不以首个成功项短路。
for capability in self.inherited_traits(definition)? {
self.validate_trait(definition, capability, true)?;
}
@@ -1055,9 +1072,12 @@ impl ObjectStore {
}
// Enumerate borrowed heap handles only while validating a definition update;
// no global type registry or owning descendant index is introduced.
/// 方法/能力更新前扫描存活类型,返回包含 base 自身的全部子类型借用身份。
fn descendant_types(&self, base: ObjectRef) -> Result<Vec<ObjectRef>, VmError> {
self.payload::<EndorTypeObject>(base, "Type")?;
// 去重能力身份,不建立堆外拥有注册表或延长能力寿命。
let mut found = vec![];
// 扫描当前存活对象;只选类型载荷及其名义子类型。
for reference in self.heap.live_references() {
if self
.object(reference)?
@@ -1071,34 +1091,46 @@ impl ObjectStore {
}
Ok(found)
}
/// define_method 提交前只检查真实会受该父方法变化影响的后代能力要求。
fn validate_method_update(
&self,
changed: ObjectRef,
name: &str,
function: ObjectRef,
) -> Result<(), VmError> {
// 父定义变更必须考虑现有后代,不能只核对当前类型。
for descendant in self.descendant_types(changed)? {
// 从后代向父层寻找当前方法的实际来源。
let mut current = Some(descendant);
// 记录是否在遇到更近覆盖前到达 changed。
let mut affected = false;
// 沿固定基类链逐层读取,不按名称猜测类型。
while let Some(definition) = current {
// 查找会使用此次变更的方法,该后代属于影响范围。
if definition == changed {
affected = true;
break;
}
// 验证类型载荷后才读取其基类或能力列表。
let definition = self.payload::<EndorTypeObject>(definition, "Type")?;
// 更近后代已覆盖同名方法,父层更新不会改变该后代查找结果。
if definition.methods.contains_key(name) {
break;
}
current = definition.base;
}
// 未受查找影响的后代跳过能力重验。
if !affected {
continue;
}
// 全部继承能力都参与,不以首个成功项短路。
for capability in self.inherited_traits(descendant)? {
// 遍历能力全部要求,任一失败阻止声明/更新。
for requirement in &self
.payload::<EndorTraitObject>(capability, "Trait")?
.requirements
{
// 只校验当前被替换方法对应要求,其他方法表项没有变化。
if requirement.name == name {
self.validate_requirement(
capability,
@@ -1113,23 +1145,27 @@ impl ObjectStore {
}
Ok(())
}
/// 宿主/VM 显式声明能力;先验证后代和已有实例,再提交定义强边。
pub fn implement_trait(
&mut self,
definition: ObjectRef,
capability: ObjectRef,
) -> Result<(), VmError> {
self.payload::<EndorTraitObject>(capability, "Trait")?;
// 父定义变更必须考虑现有后代,不能只核对当前类型。
for descendant in self.descendant_types(definition)? {
self.validate_trait(descendant, capability, false)?;
}
// Existing objects must satisfy the same storage invariant as new writes.
// Borrowed heap enumeration adds no owning instance registry.
// 已有实例也必须满足新写入的存储约束;堆枚举只借用,不延长实例寿命。
// 类型化能力才需要扫描实例存储,最小数量能力没有遮蔽签名要求。
if !self
.payload::<EndorTraitObject>(capability, "Trait")?
.signatures
.is_empty()
{
// 枚举已有实例检查同一存储不变量,不建立持有实例的注册表。
for object in self.heap.live_references() {
// 按有效类型判断是否属于被声明类型及后代,兼容类型转发门面。
if let Some(actual) = self.type_of(object)?
&& self.is_subtype(actual, definition)?
{
@@ -1137,20 +1173,25 @@ impl ObjectStore {
}
}
}
// 复制定义准备提交;此前检查失败不改变真实能力列表。
let mut updated = self.payload::<EndorTypeObject>(definition, "Type")?.clone();
// 重复声明是无操作,首次声明才更新载荷边与版本。
if !updated.traits.contains(&capability) {
updated.traits.push(capability);
self.heap.replace_payload(definition, updated)?;
}
Ok(())
}
/// 名义能力查询要求显式声明/继承,命中后重验当前方法,不以结构相似猜测。
pub fn implements_trait(
&self,
definition: ObjectRef,
capability: ObjectRef,
) -> Result<bool, VmError> {
self.payload::<EndorTraitObject>(capability, "Trait")?;
// 显式声明或继承才算支持能力,方法形状相同也不会自动成为声明。
let declared = self.inherited_traits(definition)?.contains(&capability);
// 命中声明后重验当前方法/实例,避免把历史声明当作永久有效证明。
if declared {
self.validate_trait(definition, capability, false)?;
}
@@ -1158,12 +1199,15 @@ impl ObjectStore {
}
/// Typed capability methods belong to the method table. Instance fields
/// cannot replace them independently of dispatch through that table.
/// Store 属性读写及元数据查找防止字段遮蔽类型化能力方法,带按线程递归守卫。
pub(crate) fn check_typed_method_write(
&self,
object: ObjectRef,
name: &str,
) -> Result<(), VmError> {
// 递归属性检查按线程隔离。
let thread = std::thread::current().id();
// 同线程同对象检查重入时返回,避免 type_target 读取自身属性导致无限递归。
if !self
.active_attribute_checks
.lock()
@@ -1174,14 +1218,19 @@ impl ObjectStore {
{
return Ok(());
}
// 成功登记后建立守卫,错误和正常返回都清理本次对象检查标记。
let _guard = AttributeCheckGuard {
store: self,
thread,
object,
};
// 仅有有效名义类型时才有继承能力可检查。
if let Some(definition) = self.type_of(object)? {
// 全部继承能力都参与,不以首个成功项短路。
for capability in self.inherited_traits(definition)? {
// 能力载荷先验证,再借用名称/完整签名/最小要求。
let contract = self.payload::<EndorTraitObject>(capability, "Trait")?;
// 实例字段不得取代能力方法表分派,拒绝同名属性遮蔽。
if contract.signatures.contains_key(name) {
return Err(VmError::TraitViolation {
capability: contract.name.clone(),
@@ -1194,26 +1243,34 @@ impl ObjectStore {
Ok(())
}
/// 类型附着/能力声明/宿主分派前核对实际属性存储及固有属性不遮蔽能力方法。
fn check_capability_storage(
&self,
object: ObjectRef,
capability: ObjectRef,
) -> Result<(), VmError> {
// 能力载荷先验证,再借用名称/完整签名/最小要求。
let contract = self.payload::<EndorTraitObject>(capability, "Trait")?;
// 没有完整签名时无此处的类型化方法存储不变量。
if contract.signatures.is_empty() {
return Ok(());
}
// 沿属性转发链确定实际存储终点,attribute_path 成功时链必非空。
let storage = *self
.attribute_path(object)?
.last()
.expect("nonempty attribute path");
// 检查每个类型化方法名的固有元数据及存储属性冲突。
for name in contract.signatures.keys() {
// 查询原对象固有属性身份,而不是只查看转发终点。
let payload = self.object(object)?.payload();
// Type 的 name/base/类方法与 Trait 的 name 都是固有属性,可能与能力方法冲突。
let intrinsic = if payload.as_any().is::<EndorTypeObject>() {
name == "name" || name == "base" || self.lookup_method(object, name)?.is_some()
} else {
payload.as_any().is::<EndorTraitObject>() && name == "name"
};
// 固有属性无法经普通存储删除,声明该冲突能力必须失败。
if intrinsic {
return Err(VmError::TraitViolation {
capability: contract.name.clone(),
@@ -1221,6 +1278,7 @@ impl ObjectStore {
reason: "intrinsic attribute shadows a typed capability method",
});
}
// 字段命中即冲突;不存在或不允许属性可继续,其他错误传播。
match self.heap.get_attr(storage, name) {
Ok(_) => {
return Err(VmError::TraitViolation {
@@ -1240,9 +1298,13 @@ impl ObjectStore {
/// Method names whose instance storage participates in typed capability
/// validity. Hosts can subscribe to these attribute keys when caching.
/// 宿主缓存查询当前类型化能力涉及的属性键,返回去重名称,不建立订阅。
pub fn typed_method_names(&self, object: ObjectRef) -> Result<Vec<String>, VmError> {
// 按名称去重,多个能力共用方法名只返回一次。
let mut names = std::collections::BTreeSet::new();
// 仅有有效名义类型时才有继承能力可检查。
if let Some(definition) = self.type_of(object)? {
// 全部继承能力都参与,不以首个成功项短路。
for capability in self.inherited_traits(definition)? {
names.extend(
self.payload::<EndorTraitObject>(capability, "Trait")?
@@ -1257,8 +1319,11 @@ impl ObjectStore {
/// Validate instance storage before host dispatch that bypasses attribute
/// lookup. Raw storage access is trusted but cannot certify conformance.
/// 绕过普通属性查找的宿主分派必须显式重验实例存储,原始载荷读取不能证明符合能力。
pub fn check_typed_instance_storage(&self, object: ObjectRef) -> Result<(), VmError> {
// 仅有有效名义类型时才有继承能力可检查。
if let Some(definition) = self.type_of(object)? {
// 全部继承能力都参与,不以首个成功项短路。
for capability in self.inherited_traits(definition)? {
self.check_capability_storage(object, capability)?;
}
@@ -1266,11 +1331,15 @@ impl ObjectStore {
Ok(())
}
/// 值级能力查询:先验证有效类型显式声明,再检查实例实际存储,旧无类型对象为 false。
pub fn supports(&self, object: ObjectRef, capability: ObjectRef) -> Result<bool, VmError> {
self.payload::<EndorTraitObject>(capability, "Trait")?;
// 无有效类型返回 false,有类型还需显式能力声明及实例存储检查。
match self.type_of(object)? {
Some(definition) => {
// 显式声明或继承才算支持能力,方法形状相同也不会自动成为声明。
let declared = self.implements_trait(definition, capability)?;
// 命中声明后重验当前方法/实例,避免把历史声明当作永久有效证明。
if declared {
self.check_capability_storage(object, capability)?;
}
@@ -1285,19 +1354,31 @@ impl ObjectStore {
/// while validating the return, so rebinding globals cannot release it mid-call.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AnnotationType {
/// 内建 Object 注解,接受所有有效值,不等于特定 Object 名义定义。
Any,
/// 只接受 Value::Nil。
Unit,
/// 接受直接 Number 或堆数值载荷。
Number,
/// 接受直接 Text 或堆字符串载荷。
String,
/// 只接受直接 Bool。
Bool,
/// 按载荷 is_function 判定,不接受所有可调用 Type。
Function,
/// 要求 Type 载荷。
Type,
/// 要求 Trait 载荷。
Trait,
/// 借用名义类型定义,按实例继承关系匹配。
Nominal(ObjectRef),
/// 借用显式能力定义,按 supports 完整检查。
Capability(ObjectRef),
}
impl AnnotationType {
/// 帧/签名 trace 和保护逻辑取得注解携带的借用定义引用,直接类别没有引用。
pub fn reference(self) -> Option<ObjectRef> {
// 只有 Nominal/Capability 携带定义强边来源,其余注解是直接类别。
match self {
Self::Nominal(reference) | Self::Capability(reference) => Some(reference),
_ => None,
@@ -1305,7 +1386,9 @@ impl AnnotationType {
}
}
impl ObjectStore {
/// 源码字段/函数解析内建注解名,优先于环境同名绑定;Text 与 String 同义。
fn primitive_annotation(name: &str) -> Option<AnnotationType> {
// 内建注解直接映射固定类别,不访问语言全局空间。
match name {
"Object" => Some(AnnotationType::Any),
"Unit" => Some(AnnotationType::Unit),
@@ -1319,6 +1402,7 @@ impl ObjectStore {
}
}
/// Store 字段写入/删除按对象有效类型查字段真实声明层,返回借用定义及字段。
pub(crate) fn declared_field(
&self,
object: ObjectRef,
@@ -1327,17 +1411,22 @@ impl ObjectStore {
self.declared_field_in_type(self.type_of(object)?, name)
}
/// 字段验证沿继承链只搜索每层自有后缀,使继承字段使用原声明环境。
fn declared_field_in_type(
&self,
mut current: Option<ObjectRef>,
name: &str,
) -> Result<Option<(ObjectRef, &ClassField)>, VmError> {
// 沿固定基类链逐层读取,不按名称猜测类型。
while let Some(definition) = current {
// 先验证定义/函数载荷,再访问字段表或声明环境。
let data = self.payload::<EndorTypeObject>(definition, "Type")?;
// 父字段占当前布局前缀,当前层只搜索其后的自有声明。
let inherited = match data.base {
Some(base) => self.payload::<EndorTypeObject>(base, "Type")?.fields.len(),
None => 0,
};
// 命中字段时返回当前声明 owner,让后续注解解析使用正确环境。
if let Some(field) = data.fields[inherited..]
.iter()
.find(|field| field.name == name)
@@ -1349,12 +1438,14 @@ impl ObjectStore {
Ok(None)
}
/// Store 开启字段检查时校验已声明字段,未声明动态属性不在此限制。
pub(crate) fn check_field_write(
&self,
object: ObjectRef,
name: &str,
value: &Value,
) -> Result<(), VmError> {
// 动态未声明字段允许通过;已声明字段按原 owner 的约束验证。
let Some((owner, field)) = self.declared_field(object, name)? else {
return Ok(());
};
@@ -1363,12 +1454,15 @@ impl ObjectStore {
/// NativeTyped allocators can validate their field suffix before any effects.
/// Count is always checked; annotation matching follows the opt-in setting.
/// Record/NativeTyped 构造器在副作用前校验字段后缀;数量始终检查,类型匹配由开关控制。
pub fn check_class_field_arguments(
&self,
definition: ObjectRef,
arguments: &[Value],
) -> Result<(), VmError> {
// 先验证定义/函数载荷,再访问字段表或声明环境。
let data = self.payload::<EndorTypeObject>(definition, "Type")?;
// 字段构造数量始终严格相等,错误发生在逐字段类型检查之前。
if arguments.len() != data.fields.len() {
return Err(VmError::ArgumentCount {
name: data.name.clone(),
@@ -1377,8 +1471,11 @@ impl ObjectStore {
provided: arguments.len(),
});
}
// 可选类型检查开关不改变字段数量规则。
if self.field_type_checks {
// 依照完整继承字段顺序匹配实参,每项还原真实声明层。
for (field, value) in data.fields.iter().zip(arguments) {
// 完整字段表与继承前缀不变量保证声明层存在。
let (owner, field) = self
.declared_field_in_type(Some(definition), &field.name)?
.expect("class field has a declaring type");
@@ -1388,13 +1485,16 @@ impl ObjectStore {
Ok(())
}
/// 声明字段按自身 owner/内建名/声明函数环境解析类型,再执行值匹配。
fn check_field_value(
&self,
owner: ObjectRef,
field: &ClassField,
value: &Value,
) -> Result<(), VmError> {
// 验证类型载荷后才读取其基类或能力列表。
let definition = self.payload::<EndorTypeObject>(owner, "Type")?;
// 自类名优先、其次内建注解,再查声明函数环境,无环境则未知注解。
let expected = if field.type_name == definition.name {
AnnotationType::Nominal(owner)
} else if let Some(primitive) = Self::primitive_annotation(&field.type_name) {
@@ -1404,6 +1504,7 @@ impl ObjectStore {
} else {
return Err(VmError::UnknownAnnotation(field.type_name.clone()));
};
// 类型化能力才需要扫描实例存储,最小数量能力没有遮蔽签名要求。
if !self.matches_annotation(value, expected)? {
return Err(VmError::TypeMismatch {
function: definition.name.clone(),
@@ -1415,25 +1516,33 @@ impl ObjectStore {
Ok(())
}
/// eval 参数/返回与字段契约解析源码注解,返回借用描述符,不 retain 定义。
pub fn annotation_type(
&self,
function: ObjectRef,
name: &str,
receiver: Option<ObjectRef>,
) -> Result<AnnotationType, VmError> {
// 先验证定义/函数载荷,再访问字段表或声明环境。
let data = self.payload::<crate::EndorFunctionObject>(function, "function")?;
// 方法 owner 解析需要代码中的源码声明元数据,函数本身只持有代码引用。
let signature = self
.payload::<crate::EndorCodeObject>(data.code(), "code")?
.code()
.source_signature();
// Bind a method's own class to the definition that actually owns it,
// including inherited methods and old instances after REPL redefinition.
// 只对声明自身 owner 名称且有接收者的场景沿真实类型链查找。
if signature.and_then(|s| s.method_owner.as_deref()) == Some(name)
&& let Some(receiver) = receiver
{
// 从接收者当前名义类型向父类查找实际拥有该源码方法的定义。
let mut current = self.type_of(receiver)?;
// 沿固定基类链逐层读取,不按名称猜测类型。
while let Some(definition) = current {
// 借用继承链类型,要求名称相同且方法表仍持有当前函数。
let payload = self.payload::<EndorTypeObject>(definition, "Type")?;
// 同时检查名称和函数身份,避免 REPL 同名重定义误绑定旧实例。
if payload.name == name
&& payload.methods.values().any(|method| *method == function)
{
@@ -1442,26 +1551,33 @@ impl ObjectStore {
current = payload.base;
}
}
// 内建注解先于普通环境绑定,避免同名用户对象改变内建语义。
if let Some(primitive) = Self::primitive_annotation(name) {
return Ok(primitive);
}
// 普通注解查函数全局及内置空间;Option::or 的参数会先求值,因此内置读取不是惰性。
let value = self
.dict_get_name(data.globals(), name)?
.or(match data.builtins() {
Some(builtins) => self.dict_get_name(builtins, name)?,
None => None,
});
// 普通名称必须指向 Type 或 Trait 载荷,其他值不能充当类型注解。
if let Some(Value::Object(definition)) = value {
// 查询原对象固有属性身份,而不是只查看转发终点。
let payload = self.object(definition)?.payload();
// 识别名义类型,描述符只借用该定义身份。
if payload.as_any().is::<EndorTypeObject>() {
return Ok(AnnotationType::Nominal(definition));
}
// 识别显式能力定义,不以类名字符串替代能力身份。
if payload.as_any().is::<EndorTraitObject>() {
return Ok(AnnotationType::Capability(definition));
}
}
Err(VmError::UnknownAnnotation(name.into()))
}
/// 调用/字段检查把类型验证读取标记为 validation,普通程序读取仍可另行记录。
pub fn matches_annotation(
&self,
value: &Value,
@@ -1471,14 +1587,17 @@ impl ObjectStore {
.with_validation_reads(|| self.matches_annotation_value(value, expected))
}
/// 匹配已解析注解;对象先校验存活,直接类别可同时支持直接值和相应堆载荷。
fn matches_annotation_value(
&self,
value: &Value,
expected: AnnotationType,
) -> Result<bool, VmError> {
// Any 也不能接受失效句柄,先验证对象存活再匹配类别。
if let Value::Object(object) = value {
self.object(*object)?;
}
// 直接类别与名义/能力匹配分开;Type/Function 类别不等于任意可调用对象。
Ok(match expected {
AnnotationType::Any => true,
AnnotationType::Unit => matches!(value, Value::Nil),
@@ -1510,7 +1629,9 @@ impl ObjectStore {
},
})
}
/// 类型错误诊断格式化预期名称;名义/能力定义仍验证句柄和载荷。
pub fn annotation_type_name(&self, expected: AnnotationType) -> Result<String, VmError> {
// 直接类别与名义/能力匹配分开;Type/Function 类别不等于任意可调用对象。
Ok(match expected {
AnnotationType::Any => "Object".into(),
AnnotationType::Unit => "Unit".into(),
@@ -1530,7 +1651,9 @@ impl ObjectStore {
.clone(),
})
}
/// 类型错误诊断显示实际类型,优先有效名义类型,无类型才回退载荷类别。
pub fn value_type_name(&self, value: &Value) -> Result<String, VmError> {
// 直接值显示内建类别;对象优先显示有效名义类型名。
Ok(match value {
Value::Nil => "Unit".into(),
Value::Bool(_) => "Bool".into(),