Mago 1.14.1
Mago 1.14.1 is a patch release focused on fixing false positives across the analyzer's generics and type inference system. Highlights include proper template inference for spread arguments, template constraint violation detection during class instantiation, correct class-string<T> inference from $object::class, improved array_filter handling for union array types, and fixes for variable definedness tracking in try-catch blocks. The formatter also receives several fixes, and the Docker image now includes git for --staged support.
🐛 Bug Fixes
Analyzer
- Fixed template inference for spread arguments to variadic parameters: Spread arguments like
...$listwhere$listislist<Child>now correctly infer the template type (e.g.,T=Child) instead of falling back to the constraint default (#1368) - Detect template constraint violations during class instantiation: When constructing a generic class like
new ViewTable(models: [new Model()]), the analyzer now correctly reports an error if the inferred type doesn't satisfy the template constraint (e.g.,T of Textable) (#1355) - Fixed
$object::classto inferclass-string<T>for generic parameters: When$objectis typed as a generic parameterT of object,$object::classnow correctly producesclass-string<T>instead of bareclass-string(#1372) - Fixed
method_exists/property_existsnarrowing string tonever: Whenmethod_exists($className, 'method')is used with astringvariable, the variable is now narrowed toclass-stringin the truthy branch instead of being discarded asnever(#1374) - Preserved generic
class-string<T>identity during match exhaustiveness narrowing: Match expressions that compare aclass-string<T>against class constants no longer lose the generic parameter T, preventing false positive return type mismatches (#1375) - Fixed
array_filterreturn type for union array types:array_filternow correctly removes nullable types when the input array comes from amatchexpression or other constructs that produce a union of array types (#1365) - Fixed variable definedness tracking in try-catch with multiple leaving paths: When a catch block has multiple exit paths (e.g.,
throwin one branch andcontinuein another), variables assigned in the try block are now correctly considered defined after the try-catch (#1352) - Fixed false positive for
incompatible-property-hook-parameter-type: The analyzer now uses the effective type (considering@vardocblock narrowing) when checking property hook parameter compatibility (#1342) - Fixed false positive
property-type-coercionfor unresolved generic parameters: When instantiating generic classes without explicit type arguments (e.g.,new WeakMap()), unresolved generic parameters now use placeholder types instead of constraint defaults, preventing false coercion warnings when assigned to typed properties (#1346) - Fixed debug panic from stale by-reference counters: Resolved a debug-mode assertion failure caused by stale by-reference counters during analysis (#1242)
Codex
- Preserved all union members when replacing class-string generic templates: Fixed a bug where
class-string<A>|class-string<B>passed to aclass-string<T>parameter would lose one of the union members during template resolution (#1341, #1344) - Fixed closure/arrow function skipping in incremental builds: Closures and arrow functions are no longer skipped during incremental builds in watch mode, preventing types from becoming unknown references (#1359, #1363)
Formatter
- Preserved parentheses around unbounded constructs in binary expressions: Parentheses around
require,include,print, and similar constructs are now preserved when used in binary expressions (#1348, #1353) - Stabilized chain-breaking heuristic for method chains: Fixed an idempotency issue where method chains with complex arguments could produce different output on repeated formatting passes (#1351, #1371)
- Removed unnecessary parentheses around
newin partial application: The formatter no longer wrapsnewexpressions in unnecessary parentheses when used in array or argument contexts (#1370, #1373)
Linter
- Marked
str-contains/str-starts-withfixers as potentially unsafe: The auto-fixers for these rules are now flagged as potentially unsafe since the transformation may change behavior in edge cases (#1358)
Docker
- Installed
gitin Docker image: The Docker image now includesgit, enabling--stagedoptions for lint and format commands (#1362, #1369)
🙏 Thank You
Contributors
A huge thank you to everyone who contributed code to this release:
- @chrisopperwall-qz — #1363
- @edsrzf — #1358
- @kzmshx — #1353, #1371, #1373
- @marcovmun — #1369
- @npo-mmenke — #1242
Issue Reporters
Thank you to everyone who reported issues that shaped this release:
- @chrisopperwall-qz — #1359
- @dotdash — #1350, #1354
- @dragosprotung — #1352
- @dynasource — #1370
- @giorgiopogliani — #1355
- @JochemKlingeler — #1368
- @KorvinSzanto — #1341
- @marcovmun — #1362
- @zip-fa — #1365, #1366, #1372, #1374, #1375
Full Changelog: 1.14.0...1.14.1