Represent nullable and union native contracts with traced alternatives

This commit is contained in:
2026-10-22 14:00:48 +08:00
parent 680caf81e3
commit 6b4cce1fee
12 changed files with 229 additions and 81 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
| 文件 | 职责 |
| --- | --- |
| [lib.rs](lib.rs) | 包边界、对象类型/ObjectStore 公开导出(含Trait/MethodRequirement/SourceSignature/AnnotationType/CallArity/CallSignature/CallEffect/ReadAccess)与独立存储 rustdoc 示例 |
| [lib.rs](lib.rs) | 包边界、对象类型/ObjectStore 公开导出(含Trait/MethodRequirement/SourceSignature/AnnotationType/CallArity/CallSignature/CallType/CallEffect/ReadAccess)与独立存储 rustdoc 示例 |
| [object.rs](object.rs) | Value、CompareOp、ObjectPayload(含显式函数标记)、ObjectHeader、EndorObject、Record、可发布数量元数据的 NativeFunction |
| [types.rs](types.rs) | 托管名义类型、显式 Object/Type 引导、继承查询、受管方法表/接收者绑定、类字段、显式Trait定义/声明/方法参数约束、原生构造委托、统一源码/原生/绑定方法参数区间查询与能力验证、声明环境托管边、字段构造/写入检查与标记为校验读取的注解解析/匹配 |
| [native.rs](native.rs) | NativeContext、CallArity/CallSignature 类型与效果元数据、调用前检查、签名类型强边、上下文原生函数、作用域语言函数工厂、显式能力声明入口、函数标记、根与非递归委托调用 |
+2 -2
View File
@@ -36,8 +36,8 @@ pub use error::VmError;
pub use heap::{ObjectRef, ReadAccess, WeakObjectRef};
pub use instruction::{DecodedInstruction, Instruction, Opcode};
pub use native::{
CallArity, CallEffect, CallSignature, ContextNativeFunction, NativeCallable, NativeContext,
NativeResult,
CallArity, CallEffect, CallSignature, CallType, ContextNativeFunction, NativeCallable,
NativeContext, NativeResult,
};
pub use number::{
EndorDecimal, EndorInteger, EndorNumber, EndorNumberObject, EndorRational, EndorReal,
+91 -49
View File
@@ -59,14 +59,91 @@ pub enum CallEffect {
External,
}
/// Resolved native value contract. A union is flat, nonempty and preserves
/// all definition edges even when an earlier alternative already matches.
#[derive(Debug, Clone)]
pub enum CallType {
Single(crate::AnnotationType),
Union(Vec<crate::AnnotationType>),
}
impl From<crate::AnnotationType> for CallType {
fn from(value: crate::AnnotationType) -> Self {
Self::Single(value)
}
}
impl CallType {
pub fn nullable(value: crate::AnnotationType) -> Self {
Self::Union(vec![value, crate::AnnotationType::Unit])
}
fn alternatives(&self) -> &[crate::AnnotationType] {
match self {
Self::Single(value) => std::slice::from_ref(value),
Self::Union(values) => values,
}
}
pub fn references(&self) -> impl Iterator<Item = ObjectRef> + '_ {
self.alternatives()
.iter()
.copied()
.filter_map(crate::AnnotationType::reference)
}
pub fn is_any(&self) -> bool {
self.alternatives()
.iter()
.any(|value| matches!(value, crate::AnnotationType::Any))
}
pub fn validate(&self, store: &ObjectStore) -> Result<(), VmError> {
if self.alternatives().is_empty() {
return Err(VmError::InvalidArgument("empty native union type"));
}
for value in self.alternatives() {
match *value {
crate::AnnotationType::Nominal(reference) => {
store.payload::<crate::EndorTypeObject>(reference, "Type")?;
}
crate::AnnotationType::Capability(reference) => {
store.payload::<crate::EndorTraitObject>(reference, "Trait")?;
}
_ => {}
}
}
Ok(())
}
pub fn check(
&self,
store: &ObjectStore,
name: &str,
position: String,
value: &Value,
) -> Result<(), VmError> {
self.validate(store)?;
for expected in self.alternatives() {
if store.matches_annotation(value, *expected)? {
return Ok(());
}
}
let names = self
.alternatives()
.iter()
.map(|expected| store.annotation_type_name(*expected))
.collect::<Result<Vec<_>, _>>()?;
Err(VmError::TypeMismatch {
function: name.into(),
position,
expected: names.join(" | "),
actual: store.value_type_name(value)?,
})
}
}
/// Immutable native contract, including an explicit receiver where applicable.
/// Missing fixed slots are covered by variadic; optionality comes from arity.
#[derive(Debug, Clone)]
pub struct CallSignature {
pub arity: CallArity,
pub parameters: Vec<crate::AnnotationType>,
pub variadic: Option<crate::AnnotationType>,
pub returns: crate::AnnotationType,
pub parameters: Vec<CallType>,
pub variadic: Option<CallType>,
pub returns: CallType,
pub effect: CallEffect,
}
impl CallSignature {
@@ -77,19 +154,18 @@ impl CallSignature {
) -> Self {
Self {
arity: CallArity::exact(parameters.len()),
parameters,
parameters: parameters.into_iter().map(CallType::from).collect(),
variadic: None,
returns,
returns: returns.into(),
effect,
}
}
pub fn references(&self) -> impl Iterator<Item = ObjectRef> + '_ {
self.parameters
.iter()
.copied()
.chain(self.variadic)
.chain([self.returns])
.filter_map(crate::AnnotationType::reference)
.chain(self.variadic.as_ref())
.chain([&self.returns])
.flat_map(CallType::references)
}
pub fn validate(&self, store: &ObjectStore) -> Result<(), VmError> {
self.arity.validate()?;
@@ -101,19 +177,10 @@ impl CallSignature {
for expected in self
.parameters
.iter()
.copied()
.chain(self.variadic)
.chain([self.returns])
.chain(self.variadic.as_ref())
.chain([&self.returns])
{
match expected {
crate::AnnotationType::Nominal(reference) => {
store.payload::<crate::EndorTypeObject>(reference, "Type")?;
}
crate::AnnotationType::Capability(reference) => {
store.payload::<crate::EndorTraitObject>(reference, "Trait")?;
}
_ => {}
}
expected.validate(store)?;
}
Ok(())
}
@@ -134,16 +201,9 @@ impl CallSignature {
let expected = self
.parameters
.get(index)
.copied()
.or(self.variadic)
.or(self.variadic.as_ref())
.ok_or(VmError::InvalidArgument("incomplete native signature"))?;
self.check_value(
store,
name,
format!("parameter {}", index + 1),
value,
expected,
)?;
expected.check(store, name, format!("parameter {}", index + 1), value)?;
}
Ok(())
}
@@ -153,25 +213,7 @@ impl CallSignature {
name: &str,
value: &Value,
) -> Result<(), VmError> {
self.check_value(store, name, "return".into(), value, self.returns)
}
fn check_value(
&self,
store: &ObjectStore,
name: &str,
position: String,
value: &Value,
expected: crate::AnnotationType,
) -> Result<(), VmError> {
if !store.matches_annotation(value, expected)? {
return Err(VmError::TypeMismatch {
function: name.into(),
position,
expected: store.annotation_type_name(expected)?,
actual: store.value_type_name(value)?,
});
}
Ok(())
self.returns.check(store, name, "return".into(), value)
}
}