Skip to content

--opt-report: a function whose call sites were all inlined away never enters the spec-ABI decision loop, so the report cannot say "moot" #7111

Description

@proggeramlug

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions