Effect Inference (slice 5)¶
Mighty effects describe observable authority and runtime behavior (spec §9). Slice 5 ships the inference + validation pipeline.
Pipeline¶
Effect inference runs inside sdust_types::items::check_typed after
expression typing settles, before the side tables are handed to the
borrow checker.
Algorithm¶
- Per-fn pass: walk every fn body and record:
- Effect set from syntactic constructs:
arena ...→allocspawn ...,target!Msg(...),target?Msg(...),detach→spawnexpr @ duration→timeunsafe { ... }→unsafehtml"..."template →alloc- Map literal →
alloc - Method receivers/path-callees prefixed by
fs.,net.,clock.,dom.,model.→ corresponding cap effect. - Container method names (
push,pop,insert,encode,collect,clone,to_string) →alloc.
-
Callee list (fn-by-name calls).
-
Fixpoint: until no set changes (bounded at 32 iterations), for each fn, union the callee fns' inferred and declared effect sets.
-
Public-fn discipline: if
pub fn's inferred set is non-empty, verify the declaredeffect ...clause is a superset. ElseMT4001 effect_undeclaredwith the missing effects listed. -
Profile gate: if
mighty.tomldeclaresprofile = "core", anypub fnwithallocin its inferred set triggersMT4002 alloc_in_core.
Limitations¶
- Capability effects use a path-prefix heuristic on the receiver
expression, not a typed dispatch. A bound
let alias = net; alias.get(...)would not contributenettoday. Refinement: post-v0.1. - Recursion via dynamic dispatch (
dyn Traitmethod calls) does NOT propagate effects through the dyn (slice 5 keepsdyneffect-free to avoid pessimistic over-tagging). - Inferred effect names exposed today:
alloc,net,fs,time,dom,model,spawn,unsafe. The spec also listsio,rand,block— those are reserved for slice 6.
Side table¶
TypedPackage.fn_effects: HashMap<FnId, Vec<EffectId>> — every fn's
inferred effects in deterministic order. Consumers (LSP, codegen,
docs) read from here.
v0.3 (A65) tightening¶
v0.3 didn't touch the inference algorithm itself. The strict-scope
revisions in crates/mty-types/src/check.rs (see docs/internals/
typeck.md#scope-aware-permissivestrict-policy-v03--a65) and the
Sendable check at message-send sites (see
docs/internals/sendable.md) interact with effects only insofar as
MT3011 / MT4031 now fire alongside the existing MT4001 / MT4002.
The conformance corpus gains two new effect-checking cases —
effect_checking/04_undeclared_alloc (positive MT4001) and
effect_checking/05_strict_core_profile (case-shape for the MT4002
positive fire under profile = "core", with the positive assertion
running through the dedicated core_profile_rejects_alloc unit
test until the harness supports per-case mighty.toml overrides).