You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/CHANGELOG.md
+3Lines changed: 3 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -61,6 +61,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
61
61
62
62
### Fixed
63
63
64
+
-**`class-string<T>` static method dispatch.** When a variable is typed as `class-string<Foo>` (via `@param` or `@template` bound), calling static methods on it (e.g. `$class::from()`, `$class::cases()`) now resolves the return type correctly. The `static` return type substitutes to the bound class, so `$class::from('x')->name` resolves and `foreach ($class::cases() as $item)` gives `$item` the correct type.
65
+
-**`@var` docblock annotations no longer leak across class and method boundaries.** When the cursor was inside a nested block (foreach, if, while), a `@var` annotation for a same-named variable in a completely different class could bleed into the current scope, producing wrong type information. The backward docblock scanner now correctly detects sibling scopes regardless of nesting depth.
66
+
64
67
-**PHPStan `*` wildcard in generic type arguments.** Type strings like `Relation<TRelatedModel, *, *>` now parse correctly instead of falling back to an unparsed blob. Previously, `mago-type-syntax` rejected the `*` token, causing the entire type to be treated as a single unknown class name (e.g. `Class 'Relation<TRelatedModel, *, *>|string' not found`). The `*` wildcard is now replaced with `mixed` before parsing, matching PHPStan's semantics. Member references like `Foo::*` and constant patterns like `int-mask-of<self::FOO_*>` are not affected.
65
68
-**Closure parameter inference from function-level `@template` bindings.** Functions like `array_any`, `array_all`, and `array_find` that declare `@template` parameters bound through an array parameter and used in a `callable` parameter now infer concrete types for untyped closure arguments. For example, `array_any($this->items, fn($item) => $item->name !== '')` where `$this->items` is `array<int, Product>` now resolves `$item` as `Product`. Previously `$item` was unresolved, producing false-positive `unresolved_member_access` diagnostics. This also fixes a related issue where `@param` tags in phpstorm-stubs that omit the parameter name (e.g. `@param callable(TValue, TKey): bool` without `$callback`) failed to enrich the parameter's type hint, preventing callable parameter type extraction.
66
69
-**Property chain arguments in template substitution.** Expressions like `$this->items` or `$obj->prop` passed as arguments to templated functions now resolve their type for template binding. Previously only bare variables (e.g. `$items`) were resolved, so `array_any($this->items, fn($x) => ...)` could not infer the element type even when the property had a fully substituted generic type.
| T23 |[`class-string<T>` static method dispatch](todo/type-inference.md#t23-class-stringt-static-method-dispatch)| Medium | Medium |
26
+
27
27
| H10 |[`return.unusedType` — remove unused type from return union](todo/phpstan-actions.md#h10-returnunusedtype--remove-unused-type-from-return-union)| Medium | Medium |
28
28
| H6 |`return.type` — update return type to match actual returns | Medium | Medium |
0 commit comments