Follow-up to #7106.
--opt-report cannot say anything about a function whose call sites were all
removed by an earlier pass. It does not report "moot"; it reports nothing, which
is indistinguishable from "not analysed" and from "analysed and denied".
Mechanism
crates/perry-codegen/src/codegen/mod.rs:2221:
for f in &hir.functions {
let Some(sites) = spec_facts.call_sites.get(&f.id) else {
continue;
};
spec_facts.call_sites is built in
crates/perry-codegen/src/collectors/spec_abi_sites.rs:669 by walking hir.init
and every function body for direct Call expressions. A function whose calls
were inlined (perry-transform's inliner, crates/perry/src/commands/compile/collect_modules.rs:1923)
and then constant-folded by unroll_static_loops (:1946) has no Call left,
so it has no call_sites entry and the loop continues — before any
TypedCloneRejectionReason is constructed. Nothing reaches
record_typed_clone_rejection, so nothing reaches opt_report::deny_named.
Evidence
function compute(x: number): number { return x * 2 + 1; }
let sum = 0;
for (let i = 0; i < 5; i++) { sum = sum + compute(i); }
--opt-report=json --no-link: zero entries. Grow compute's body past
MAX_INLINE_STMTS (10, crates/perry-transform/src/inline/mod.rs:59) and the
same program reports one spec-abi entry.
Ruled out: this is not the should_record_typed_clone_rejection filter at
codegen/mod.rs:106-119. Re-running with
PERRY_NATIVE_REPS_ALL_TYPED_CLONE_REJECTIONS=1, which opens that filter,
produces the identical empty "entries": []. No rejection reason is ever built.
benchmarks/suite/14_closure.ts is the census workload affected.
Why it matters
This is the difference between an instrument that is silent because there was
nothing to say and one that is silent because it never ran — the distinction
#7106 exists to make. Here the right answer is genuinely "moot: no call site
survives, so there is no ABI to specialize", and the report should be able to
say so rather than leaving a reader to infer it.
Ask
Record an entry (an Outcome/tier meaning "not applicable", or a denial with a
rule like no_surviving_call_site) for a function that reaches the decision
loop with no call sites. Cheap: one else arm at codegen/mod.rs:2221.
Related, smaller: the six TypedCloneRejectionReason variants suppressed by
should_record_typed_clone_rejection (NotClosure, ReturnTypeNotF64,
ReturnTypeNotI32, ReturnTypeNotI1, ReturnTypeNotString,
NoReceiverField) belong to the older per-type clone mechanism, which
spec_abi_entry_decision never emits — so that filter is not currently
hiding spec-ABI decisions. Noted here so the next reader does not re-derive it.
Follow-up to #7106.
--opt-reportcannot say anything about a function whose call sites were allremoved by an earlier pass. It does not report "moot"; it reports nothing, which
is indistinguishable from "not analysed" and from "analysed and denied".
Mechanism
crates/perry-codegen/src/codegen/mod.rs:2221:spec_facts.call_sitesis built incrates/perry-codegen/src/collectors/spec_abi_sites.rs:669by walkinghir.initand every function body for direct
Callexpressions. A function whose callswere inlined (
perry-transform's inliner,crates/perry/src/commands/compile/collect_modules.rs:1923)and then constant-folded by
unroll_static_loops(:1946) has noCallleft,so it has no
call_sitesentry and the loopcontinues — before anyTypedCloneRejectionReasonis constructed. Nothing reachesrecord_typed_clone_rejection, so nothing reachesopt_report::deny_named.Evidence
--opt-report=json --no-link: zero entries. Growcompute's body pastMAX_INLINE_STMTS(10,crates/perry-transform/src/inline/mod.rs:59) and thesame program reports one
spec-abientry.Ruled out: this is not the
should_record_typed_clone_rejectionfilter atcodegen/mod.rs:106-119. Re-running withPERRY_NATIVE_REPS_ALL_TYPED_CLONE_REJECTIONS=1, which opens that filter,produces the identical empty
"entries": []. No rejection reason is ever built.benchmarks/suite/14_closure.tsis the census workload affected.Why it matters
This is the difference between an instrument that is silent because there was
nothing to say and one that is silent because it never ran — the distinction
#7106 exists to make. Here the right answer is genuinely "moot: no call site
survives, so there is no ABI to specialize", and the report should be able to
say so rather than leaving a reader to infer it.
Ask
Record an entry (an
Outcome/tier meaning "not applicable", or a denial with arule like
no_surviving_call_site) for a function that reaches the decisionloop with no call sites. Cheap: one
elsearm atcodegen/mod.rs:2221.Related, smaller: the six
TypedCloneRejectionReasonvariants suppressed byshould_record_typed_clone_rejection(NotClosure,ReturnTypeNotF64,ReturnTypeNotI32,ReturnTypeNotI1,ReturnTypeNotString,NoReceiverField) belong to the older per-type clone mechanism, whichspec_abi_entry_decisionnever emits — so that filter is not currentlyhiding spec-ABI decisions. Noted here so the next reader does not re-derive it.