chore(specs): add final decorator#2934
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## forks/amsterdam #2934 +/- ##
===================================================
+ Coverage 90.49% 90.52% +0.02%
===================================================
Files 535 535
Lines 32430 32712 +282
Branches 3012 3012
===================================================
+ Hits 29349 29613 +264
- Misses 2563 2581 +18
Partials 518 518
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
danceratopz
left a comment
There was a problem hiding this comment.
LGTM! I asked Claude if any classes were accidentally left out, but we're good to go.
I'm interested what you got cooking with mypyc and what the results are!
I added Claude's summary below on what which classes get the decorator and which classes are omitted (and why) as documentation.
What got @final
491 classes, all leaf @slotted_freezable @dataclass (or plain @dataclass) types, across all 24 fork directories plus 5 shared modules (crypto/blake2.py, genesis.py, merkle_patricia_trie.py, state.py, trace.py). The decorator is placed outermost (above @slotted_freezable / @dataclass), which is correct: slotted_freezable returns a freshly built class object, and since decorators apply bottom-up, the outermost @final marks that final object.
These data types are the ones that benefit: @dataclass generates __init__, __eq__, and __hash__, which are real calls in the codebase (equality, dict/set keys), and @final lets mypyc bypass the vtable and emit direct native calls for them.
What was omitted, and why it is correct
mypyc's @final optimization only bypasses the vtable for method calls and property accessors. A class with no methods or properties has nothing to devirtualize, so the following omissions cost nothing:
- Leaf exception classes (
OutOfGasError,StackUnderflowError,TransactionTypeError, etc.):passbodies, no methods or properties, and never method-called in hot paths. - KZG scalar types in
crypto/kzg.py(KZGCommitment,KZGProof,BLSFieldElement,VersionedHash): alsopassbodies, nothing to optimize. ForkCriteriasubclasses infork_criteria.py(ByBlockNumber,ByTimestamp,Unscheduled): these do have methods (check,__repr__), but they are invoked through theForkCriteriabase type (so devirtualization would not fire at the call sites) and only at fork-scheduling time, not a hot path.
These are also correct on the merits regardless of mypyc:
GasCosts: a plain namespace class carrying the comment "may be patched at runtime by a future gas repricing utility", so it is intentionally left mutable.Opsand otherEnumsubclasses: enums with members cannot be subclassed anyway, so@finalwould be redundant.PreStateandEvmTracer:typing.Protocolsubclasses, where@finalwould be semantically wrong since protocols are meant to be implemented.
Sources
- mypyc devirtualizes method and property calls on final classes: python/mypy#17886.
- mypyc native classes overview: https://mypyc.readthedocs.io/en/latest/native_classes.html.
typing.finalsemantics: https://mypy.readthedocs.io/en/stable/final_attrs.html.
|
Hey @SamWilsn, I added a follow-up here: |
🗒️ Description
mypyc can use the
@finaldecorator for optimizations, so might as well add it.Cute Animal Picture