Hi Larry,

> At least some of those would need to be included initially to justify the RFC.

I’m not sure optimization needs to be the justification here. A
language-enforced purity contract could be useful on its own, and
inlining does not require purity.

PHP already has
[`zend_try_inline_call()`](https://github.com/php/php-src/blob/267c6dc694aa9e5a4c76e5a2ee8938e5be2149d3/Zend/Optimizer/optimize_func_calls.c#L79-L137),
which removes eligible calls to user functions that return constants,
without any attribute. It is limited, but expanding inlining does not
depend on adding `#[Pure]`.

Whim (which is partly my experiment for trying these language ideas)
also inlines eligible calls by default. It has two attributes to
influence that decision:

- 
[`#[Whim\Marker\AlwaysInline]`](https://github.com/carthage-software/whim/blob/c159232651a7b9bc6588af2dffafdcdbc556164b/lib/src/Marker/AlwaysInline.whim)
relaxes some limits; it requests inlining but does not guarantee it.
- 
[`#[Whim\Marker\NeverInline]`](https://github.com/carthage-software/whim/blob/c159232651a7b9bc6588af2dffafdcdbc556164b/lib/src/Marker/NeverInline.whim)
prevents inlining.

The [inliner checks the function’s
bytecode](https://github.com/carthage-software/whim/blob/c159232651a7b9bc6588af2dffafdcdbc556164b/crates/optimizer/src/passes/inline_leaf_calls/leaf.rs#L40-L98),
and even [allows output
instructions](https://github.com/carthage-software/whim/blob/c159232651a7b9bc6588af2dffafdcdbc556164b/crates/optimizer/src/passes/inline_leaf_calls/leaf.rs#L177).
Inlining a function that prints something still needs to print it at
the same point in execution.

You can see [this example in the
playground](https://play.whim.sh/s/d61fb693-970d-48c7-9d9a-ea268f5d783e),
the “optimized bytecode” tab shows no function calls because Whim
inlines both the pure `sum()` and the impure `greet()`, then folds the
arithmetic and string concatenations, without any attributes.

Purity can help other optimizations, such as reusing results or
evaluating calls with constant arguments, depending on the exact
contract. But that is a separate case from inlining.

Enforcing purity can also have a cost. As Pedro notes, known call
targets may allow compile-time checks, while dynamic calls whose
targets we cannot prove need runtime checks. Those checks might be
cheap, and some could be removed, but we should measure that rather
than assume `#[Pure]` makes calls cheaper.

Personally, I think having the language enforce that promise,
including for dynamic calls, could be a useful benefit even when
static analysis tools support similar annotations. Whether the
restrictions and runtime cost are worth it is a different question. I
just would not make inlining a condition for accepting it, since we
can improve that independently for both pure and impure code.

Cheers,
Seifeddine.

Reply via email to