Skip to content

Audition 0.2.0

Latest

Choose a tag to compare

@github-actions github-actions released this 18 Jul 23:44
  • Class-level memoization fixes recognize both idioms (@x ||=
    and return @x if defined?(@x)) and apply freeze-on-memoize,
    the Rails-core pattern: the memoization stays exactly as
    written and only the memoized value becomes shareable
    (.freeze, or Ractor.make_shareable for containers).
    Ractor.store_if_absent remains the fallback for initializers
    with blocks and invalidated caches, emitted as an indented
    do..end block when the value spans lines.
  • Frozen memoization is recognized as a pattern, not punished:
    the class-level-state check and the runtime sweep downgrade
    class state that holds only shareable values to an info note
    telling you to warm the cache at boot. Info notes no longer
    taint the verdict; a target with only info findings is
    ready.
  • --dry-run previews render touching edits as a single hunk
    instead of repeating a line in two half-applied states.
  • Battle-tested against i18n; its full suite passes after
    --fix-unsafe. Five fixer bugs found and fixed in the process:
    autoload conversion keeps the registration and appends the
    eager require at the end of the file (converting in
    registration order broke mutually referencing files); the
    conversion is withheld for files guarded by rescue LoadError
    or resolving outside the target (optional dependencies);
    require hoisting moved to the unsafe tier (eager loading is not
    behavior-preserving for context-sensitive files);
    shareable_constant_value is only inserted when every constant
    is a literal all the way down (Racc parser tables are array
    literals full of locals and raise at load otherwise), and the
    insertion ignores doc comments that merely look like magic
    comments; caches with nil invalidation convert to
    Ractor.current[key] ||=, preserving reset semantics where
    store_if_absent would cache the nil forever.
  • Battle-tested against five more gems (multi_json, jwt, tzinfo,
    addressable, public_suffix); every suite passes after
    --fix-unsafe except two public_suffix assertions that inspect
    the moved ivar itself. Six more fixer bugs found and fixed:
    edits are spliced by byte offset (multibyte sources, such as
    addressable's Unicode tables, were corrupted by
    character-indexed splicing); containers holding sync primitives
    classify as sync primitives and get no wrap
    (Ractor.make_shareable on multi_json's Hash of Mutexes raised
    at load); memoized values that are not provably strings get
    Ractor.make_shareable instead of .freeze (freezing a
    memoized adapter Class froze the class object); ternaries of
    string literals classify as strings so they keep a plain
    parenthesized .freeze; shareable_constant_value requires
    bare literals (a frozen literal is a method call and raises at
    assignment, as jwt's NAMED_CURVES showed); empty-container
    memo accumulators (@x ||= {} registries) and rescue-guarded
    requires (tzinfo's optional tzinfo-data) are left for humans.
  • New checks trained on the Rails core ractorization effort
    (documented in docs/rails_core_best_practices.md): Hash.new
    with a default proc (the block survives .freeze), in-place
    mutation of screaming-case constants (RENDERERS << key), and
    define_method with a literal block (the method carries an
    unshareable Proc). Class-level state advice now teaches the
    Rails copy-on-write idiom: rebuild and refreeze on write, and
    compute per-subclass values in the inherited hook.