github carthage-software/mago 1.7.0
Mago 1.7.0

13 hours ago

Mago 1.7.0

This release introduces new type system features, improved type inference for built-in functions, a new linter rule, and numerous bug fixes for the analyzer, formatter, and type system. A significant internal effort also went into reducing dependencies and binary size.

✨ Features

Type System

  • uppercase-string and non-empty-uppercase-string types: Full support for these PHPDoc types in type syntax, codex, and analyzer. This resolves cascading errors when these types were previously unrecognized (#1057)

Analyzer

  • Return type providers for min() and max(): These functions now return precise types based on their arguments (#1074)

  • array_filter() callback parameter type inference: The analyzer now respects the mode argument (ARRAY_FILTER_USE_KEY, ARRAY_FILTER_USE_BOTH) when inferring closure parameter types, fixing incorrect mixed inference for callback parameters (#1031)

  • Switch statement fallthrough analysis: The analyzer now correctly recognizes that non-terminating code paths in a case block fall through to the next case. A case with a conditional return followed by a case that always returns is no longer flagged as missing-return-statement (#1081)

Linter

  • no-redundant-isset rule: New rule that detects redundant arguments in isset() calls. For example, in isset($a, $a['key'], $a['key']['nested']), the first two checks are redundant because isset on a nested access implicitly checks all parent accesses (#769)

CLI

  • --ignore-baseline flag: New flag for lint and analyze commands that temporarily ignores the baseline file, useful for reviewing and fixing baselined issues (#1076)

⚡ Performance

  • Reduced AST size: Optimized AST node representation to reduce memory usage during parsing
  • Leaner binary: Removed 7 third-party dependencies (reqwest, openssl, num_cpus, strum_macros, derivative, strsim, bitflags, async-walkdir), replacing them with standard library equivalents or manual implementations. reqwest/openssl were replaced with ureq/rustls for a significantly smaller and faster-compiling binary

🐛 Bug Fixes

Analyzer

  • Unused method false positives: Methods referenced in literal arrays ([$this, 'method']) and string callbacks ('ClassName::method') are now correctly tracked as used (#1069, #1044)
  • Property/constant access type expansion: Property access and constant access expressions now have their types properly expanded, fixing incorrect type inference (#1071)
  • Non-optional list items in array merge: Fixed an issue where non-optional list items were incorrectly skipped during array merging

Codex

  • @psalm-require-extends support in traits: Methods, properties, and class constants inherited from required parent classes via @psalm-require-extends or @phpstan-require-extends are now properly resolved in traits, eliminating false non-existent-property, non-existent-class-constant, and unknown-ref errors (#1064, #1068, #1070)
  • Enum types in generic comparator: Fixed incorrect type comparison when enums implement generic interfaces, resolving false invalid-return-type errors (#1061)
  • Platform-aware constant types: Predefined constants like PHP_INT_SIZE, PHP_INT_MAX, and PHP_FLOAT_DIG now use platform-aware range/union types instead of host-specific literal values. PHP_INT_SIZE > 4 is no longer flagged as a redundant comparison (#1084)

Formatter

  • Assignment alignment leaking into nested arrays: When align-assignment-like is enabled, the alignment context from consecutive variable assignments no longer leaks into nested array key-value pairs (#1082)

Linter

  • prefer-first-class-callable with reference captures: Skip suggesting first-class callable syntax when the callee variable is captured by reference in a closure's use clause, as the two forms have different semantics (#1067, #1063) by @kzmshx

Prelude (Type Stubs)

  • array_walk generics: Fixed generic templates for array_walk to properly infer callback parameter types (#1066, #1045) by @ddanielou
  • array_splice type precision: Improved type definitions for array_splice to preserve list<T> types and correctly handle non-array replacement arguments (#1072, #1080)
  • Sorting functions type precision: Enhanced type definitions for sorting functions (usort, uasort, uksort, etc.) to preserve non-empty array types (#1083)

🏗️ Internal

  • Replaced reqwest + openssl with ureq + rustls in self-update module
  • Replaced num_cpus with std::thread::available_parallelism()
  • Replaced bitflags with manual bit flag implementations
  • Removed derivative, strum_macros, strsim, and async-walkdir dependencies
  • Improved array inference logic in codex

🙏 Thank You

Contributors

A huge thank you to everyone who contributed code to this release:

Issue Reporters

Thank you to everyone who reported issues and requested features that shaped this release:


Full Changelog: 1.6.0...1.7.0

Don't miss a new mago release

NewReleases is sending notifications on new releases.