Mago 1.58.0 adds opt-in dead-catch checks, a prefer-self rule, and extension throw-type providers, cuts analysis overhead, and fixes type narrowing and PHP formatting.
Note
Support Mago
Does your company use Mago? Please consider sponsoring its development so we can keep fixing bugs and shipping releases.
Sponsor Mago ❤️
✨ Features
Analyzer
- Dead catches: adds opt-in checks for catches with no known matching throws. (#2503, #2525, 18315f6)
- Enum throws: avoids
ValueErrorfor known-validBackedEnum::from()arguments. (#2544, #2565, 5bcf444)
Linter
- Prefer self: adds an opt-in rule to replace references to the enclosing class with
self. (#2528, aba4df1) - Extension rules: accepts enabled, level, and exclude settings under
[linter.rules]. (#2530, f2b479c)
🐛 Bug Fixes
Analyzer
- Named arguments: honors class-level
@no-named-argumentstags. (#2514, a33b014) - Mixed array keys: reports
mixed-array-indexfor keys whose type is mixed. (#2522, 4b19550) - Nullsafe guards: narrows receivers through guards and falsy
??fallbacks. (#2515, #2563, 83a0bfd, 891c463) - Do-while loops: preserves initial types when by-reference calls update loop variables. (#2523, b6a24d9)
- Diagnostics: clarifies class resolution, member access, and type-check messages. (#2541, 43f0a1a)
- Redundant nullsafe calls: reports unnecessary
?->on method calls. (#2547, ba38156) - Iterable guards: narrows iterable values to
Traversableafter type checks. (#2550, dd17cfb) - Match assignments: preserves subject types and evaluates assignment subjects once. (8a19e98)
- Shape unions: removes shapes with required keys after a failed key-existence check. (#2557, 5ffc5d2)
- Nested array guards: keeps required keys when narrowing nested shapes. (#2577, 221fd63)
- Type switches: narrows variables in
get_class()andgettype()switch cases. (#2558, eba91e1) - Callable guards: fixes narrowing of callable objects and strings in type checks. (#2552, #2560, 0e1d212, abea0ad)
- Conditional assignments: keeps assignments scoped to each analysis pass. (#2561, 64a2323)
- Short-circuit assignments: tracks reassignment and narrowing across logical chains. (#2571, #2562, c8358f1, 001666b)
- Array membership: fixes strict checks and unsafe narrowing after negated
in_array(). (#2573, #2574, d5ca2a6, c16337a) - Known array keys: resolves literal keys in
isset()andempty()guards. (#2575, #2585, 9671d89, f8f46a6) - Numeric-string keys: normalizes integer-like string keys in array guards. (#2578, d7dae70)
- Loose null checks: preserves falsy strings when comparing nullable strings with null. (#2579, ff5df16)
- Negated isset: does not treat nullable keys as missing after a failed check. (#2554, #2576, fb8de05)
- Switch transfers: preserves nested breaks, continues, and finally control flow. (#2569, #2570, b6e8259)
- Empty foreach loops: skips unreachable loop bodies for known empty arrays. (#2572, 6bdf6c6)
- Switch coverage: detects impossible cases and unreachable defaults. (#2553, 204f678)
Codex
- Large unions: expands types beyond 64 members without leaving unresolved references. (#2518, 51f2762)
- Traversable templates: keeps caller templates instead of widening them to their bounds. (#2520, 735d59d)
- Class strings: handles leading backslashes when comparing literal class names. (#2533, 1a28236)
- Iterable arguments: rejects excess generic arguments on iterable types. (#2543, 1c3eba0)
- Mixed array keys: treats explicit mixed key types as
array-key. (#2545, c4d7f9a)
PHPDoc
Formatter
- Preserved breaks: keeps argument-list and binary-expression layouts stable across passes. (#2524, e665c18)
- Instanceof calls: preserves required parentheses around calls used as class expressions. (#2584, 7562fff)
- Clone chains: keeps parentheses so member chains clone the intended object. (#2588, 4681219)
- Dynamic classes: preserves required parentheses in
new (self::MAP[$key])()and related forms. (#2587, 0c7c2b5)
Linter
- Deprecated casts: shows the cast as written in the source. (7823faf)
Parser
- Incomplete code: recovers unfinished control heads without misleading lint reports. (81367b8)
Prelude
- Class interfaces: drops
falsefromclass_implements()results for object inputs. (#2513, f7af709) - Class-name maps: gives SPL class inspection helpers associative return types. (#2531, 5ea84ce)
- SoapVar: makes the
typeNameconstructor argument optional. (#2519, 245ee75) - Class checks: accepts mixed inputs for
is_a()andis_subclass_of(). (#2549, bfe814f)
Composer
📖 Documentation
Analyzer
Extensions
- Rule settings: documents configuration for extension linter rules. (#2530, f2b479c)
- Throw providers: adds PHP SDK examples and reference entries. (#2527, #2542, 53611ac)
🏗️ Internal
Analyzer
Codex
CLI
- Embedded prelude: compresses prelude data and encodes each shared word once. (7be3117)
- Shutdown: skips allocator teardown after flushing command output. (b85d25e)
Database
- Loading: cuts serial pipeline work and line-table allocations. (f8531a2, fa3a5c9)
- Path matching: adds opt-in Git-ignore handling and shared directory matching APIs. (7e72b4a)
Reporting
- Parallel output: streams rendered issues in order. (8036e42)
Parser
- Parsing work: skips detached whitespace and needless control-flow walks. (b142e5f)
Word
- String interning: uses parking_lot mutexes for shared string tables. (cd49bc3)
Names
🧩 Extension Protocol
Analyzer
Update the PHP SDK to 1.58.0 when upgrading Mago. Custom analyzer workers must use MANA 2.1; MANA 2.0 workers are not compatible. The linter protocol is unchanged.
🙏 Thank You
Contributors
Thank you to everyone who contributed to this release:
- @alfredbez: #2513, #2514, #2515, #2518, #2519, #2522, #2531, #2533, #2541, #2543, #2545, #2546, #2547, #2549
- @alfredbez: #2550, #2552, #2553, #2557, #2558, #2560, #2561, #2562, #2564, #2571, #2573, #2575, #2578, #2579
- @AnnaDamm: #2525, #2542, #2565, #2570
- @shadowhand: #2521
Issue Reporters
Thank you to everyone who reported issues that shaped this release:
- @amateescu: #2530
- @AnnaDamm: #2503, #2527, #2544, #2569
- @Double-Ramzi: #2585
- @dragosprotung: #2520
- @mathroc: #2584
- @matthewnessworthy: #2524
- @maximal: #2528
- @MichaelOwenDyer: #2563
- @mytskine: #2523
- @vishnub1626: #2587, #2588
Full Changelog: 1.57.0...1.58.0