This release introduces a major architectural overhaul with the new mago-database crate, significantly improving performance and laying a better foundation for future development. The type analyzer also receives substantial improvements, fixing several key bugs related to generic and loop variable inference.
🚀 Features & Major Changes
- New mago-database Crate: The legacy
mago-source
crate has been completely replaced by the newmago-database
crate. This is a significant architectural improvement that provides a cleaner, more performant, and thread-safe foundation for file management. It introduces a clear distinction between a mutableDatabase
for building the file set and an immutable, cheap-to-cloneReadDatabase
for high-speed concurrent analysis. - Template Inference from Default Parameters: The type analyzer can now infer generic template types from the default values of optional parameters. If you call a generic function but omit an argument that has a default, Mago will now correctly resolve the template based on that default value's type.
🐛 Bug Fixes
This release includes numerous fixes to the type analyzer and formatter, improving accuracy and correctness.
Analyzer
- Redefined Loop Variables: Fixed a critical bug where variable types redefined inside a loop (especially with a
break
) were not correctly propagated to the parent scope. This resolves many false positive "dead code" and "redundant condition" errors. (Closes #264) - @return
static<...>
Generics: The analyzer now correctly respects generic type parameters in@return static<T, U>
docblocks. This fixes incorrect type inference in methods that transform a collection's generic types, like map. (Closes #266) - Nested Array Access: The
possibly_undefined
state is now correctly propagated through nested array access (e.g.,$arr[$key1][$key2]
). This eliminates false positive "redundant null coalesce" (??
) errors. (Closes #267) ::class
on Generic object: Correctly infers the type of$variable::class
asclass-string
when$variable
is a genericobject
, instead of incorrectly resolving tomixed
. (Closes #271)
Formatter
- Script-Terminating Statements: Fixed an issue where extra newlines were added after statements that exit PHP mode (e.g.,
endif ?>
). The logic for removing trailing?>
has also been corrected to avoid removing it when required. (Closes #272) - Member Access Formatting: Corrected the eligibility score calculation for member access expressions to improve formatting decisions. (Closes #236)
Other
count()
Stub: The return type for the built-incount()
function has been refined to be more precise for empty vs. non-empty arrays. (Closes #269)- Type System: The internal
any
type has been removed in favor ofmixed
to reduce confusion and align with standard PHP behavior.
🎉 Acknowledgements
A special thank you to the following community members for their detailed bug reports, which were invaluable for this release:
Full Changelog: 1.0.0-alpha.3...1.0.0-alpha.4