Infer conservative read-only source effects for method contracts
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
| --- | --- |
|
||||
| [lib.rs](lib.rs) | 包边界、对象类型/ObjectStore 公开导出(含Trait/MethodRequirement/TypedMethodRequirement/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定义、强类型签名边与声明约束、实例方法遮蔽检查和宿主缓存依赖名、原生构造委托、统一源码/原生/绑定方法参数区间查询与能力验证、声明环境托管边、字段构造/写入检查与标记为校验读取的注解解析/匹配 |
|
||||
| [types.rs](types.rs) | 托管名义类型、显式 Object/Type 引导、继承查询、受管方法表/接收者绑定、类字段、显式/类型化Trait定义、强类型签名边与声明约束、实例方法遮蔽检查和宿主缓存依赖名、原生构造委托、统一源码/原生/绑定方法参数区间和已知效果查询与能力验证、声明环境托管边、字段构造/写入检查与标记为校验读取的注解解析/匹配 |
|
||||
| [contracts.rs](contracts.rs) | 方法参数逆变/返回协变、名义/能力/联合包含关系、祖先方法更新的后代检查、动态注解调用前复查、类型化能力替换/返回约束与临时递归验证集合 |
|
||||
| [native.rs](native.rs) | NativeContext、CallArity/CallSignature 类型、Delegated/固定效果元数据、调用前检查、签名类型强边、上下文原生函数、作用域语言函数工厂、显式能力声明入口、函数标记、根与非递归委托调用 |
|
||||
| [changes.rs](changes.rs) | 合并变更批次、变更键与有界通知额度 |
|
||||
@@ -16,7 +16,7 @@
|
||||
| [store.rs](store.rs) | ObjectStore、空堆创建、字段检查配置/属性写入屏障、详细读取区域结果、逐线程临时能力检查集合、对象操作、retain/release 和回收入口、弱 Function 类型配置与分配分类 |
|
||||
| [store_builtins.rs](store_builtins.rs) | 载荷校验、代码/函数工厂、Dict/Cell 操作及键语义 |
|
||||
| [instruction.rs](instruction.rs) | Opcode、Instruction、wordcode 编解码、MakeFunction/比较参数与跳转读取接口 |
|
||||
| [code.rs](code.rs) | CodeLayout、EndorCode/EndorCodeObject、可选源码签名、共享不可变代码和操作数/控制流/栈验证 |
|
||||
| [code.rs](code.rs) | CodeLayout、EndorCode/EndorCodeObject、可选源码签名、保守只读字节码证明、共享不可变代码和操作数/控制流/栈验证 |
|
||||
| [error.rs](error.rs) | 对象、代码与执行共用的 VmError(含TraitViolation、OverrideViolation、UnknownAnnotation、TypeMismatch),避免反向依赖 core |
|
||||
|
||||
对象操作变更同步 [对象模型](../../../docs/runtime/objects.md),内置载荷同步 [基本对象](../../../docs/runtime/builtins.md)。新增操作码需要同时修改本包 instruction.rs/code.rs 和 core 的 eval.rs 分派,见 [字节码 VM](../../../docs/runtime/bytecode.md)。
|
||||
|
||||
@@ -106,6 +106,40 @@ impl EndorCode {
|
||||
self.signature.as_ref()
|
||||
}
|
||||
|
||||
/// Conservative proof over validated instructions. Local assignment is not
|
||||
/// automatically pure: shared-reference assignment may update its old value.
|
||||
/// Unknown calls and writes remain unknown, even when they could be safe for
|
||||
/// a particular invocation. New opcodes require an explicit audit here.
|
||||
pub fn is_statically_read_only(&self) -> bool {
|
||||
self.instructions.iter().all(|decoded| {
|
||||
matches!(
|
||||
decoded.instruction.opcode,
|
||||
Opcode::Nop
|
||||
| Opcode::LoadConst
|
||||
| Opcode::LoadFast
|
||||
| Opcode::DeleteFast
|
||||
| Opcode::LoadGlobal
|
||||
| Opcode::PopTop
|
||||
| Opcode::Copy
|
||||
| Opcode::Swap
|
||||
| Opcode::PushNull
|
||||
| Opcode::ReturnValue
|
||||
| Opcode::JumpForward
|
||||
| Opcode::JumpBackward
|
||||
| Opcode::PopJumpIfFalse
|
||||
| Opcode::PopJumpIfTrue
|
||||
| Opcode::ToBool
|
||||
| Opcode::UnaryNot
|
||||
| Opcode::CompareOp
|
||||
| Opcode::LoadDeref
|
||||
| Opcode::LoadClosure
|
||||
| Opcode::LoadAttr
|
||||
| Opcode::BuildMap
|
||||
| Opcode::MakeFunction
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn with_location(
|
||||
mut self,
|
||||
name: impl Into<String>,
|
||||
|
||||
@@ -170,7 +170,7 @@ impl ObjectStore {
|
||||
parameters,
|
||||
variadic: None,
|
||||
returns: resolve(&signature.return_type)?.into(),
|
||||
effect: None,
|
||||
effect: self.call_effect(function)?,
|
||||
}))
|
||||
}
|
||||
fn own_method(
|
||||
@@ -303,7 +303,7 @@ impl ObjectStore {
|
||||
CallEffect::External | CallEffect::Delegated => true,
|
||||
};
|
||||
if !compatible {
|
||||
return Err(invalid("override expands native effects"));
|
||||
return Err(invalid("override expands known effects"));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@@ -485,6 +485,33 @@ impl ObjectStore {
|
||||
Ok(signature)
|
||||
}
|
||||
|
||||
/// Known whole-call effect, after unwrapping bound receivers. Delegated
|
||||
/// native wrappers and source code with unproved operations remain unknown.
|
||||
/// This query does not execute code or freeze dynamic globals/call targets.
|
||||
pub fn call_effect(&self, function: ObjectRef) -> Result<Option<crate::CallEffect>, VmError> {
|
||||
let mut current = function;
|
||||
loop {
|
||||
let payload = self.object(current)?.payload();
|
||||
if let Some(bound) = payload.as_any().downcast_ref::<BoundMethod>() {
|
||||
current = bound.function;
|
||||
continue;
|
||||
}
|
||||
if let Some(source) = payload
|
||||
.as_any()
|
||||
.downcast_ref::<crate::EndorFunctionObject>()
|
||||
{
|
||||
return Ok(self
|
||||
.payload::<crate::EndorCodeObject>(source.code(), "code")?
|
||||
.code()
|
||||
.is_statically_read_only()
|
||||
.then_some(crate::CallEffect::ReadOnly));
|
||||
}
|
||||
return Ok(self.native_signature(current)?.and_then(|signature| {
|
||||
(signature.effect != crate::CallEffect::Delegated).then_some(signature.effect)
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
/// Unified source/native positional interval, after any bound receivers.
|
||||
/// None means no published native metadata (including generic Type construction).
|
||||
pub fn call_arity(&self, function: ObjectRef) -> Result<Option<crate::CallArity>, VmError> {
|
||||
|
||||
Reference in New Issue
Block a user