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
refactor: model static and $this as bounded types in the type system
Add PhpType::StaticType(Atom) and PhpType::ThisType(Atom) variants
that preserve late-static-binding semantics instead of flattening
static/$this to a bare class name. StaticType carries the bound
class ("at least this class or a subclass"), ThisType is more
specific ("the exact runtime instance type").
The subtype chain is ThisType(A) <: StaticType(A) <: Named(A).
Display: static(Foo), $this(Foo) -- shows the bound class.
Production sites updated:
- replace_self(fqn) now delegates to resolve_self_refs_bounded()
so static -> StaticType(fqn) and $this -> ThisType(fqn);
replace_self_with_type(&receiver) is unchanged (preserves full
generic receiver types for accurate chain resolution)
- Subject resolution: $this -> ThisType, static -> StaticType
- First-class callable partial application: preserves static/this
- Template substitution: preserve_static path uses bounded types
- new static() -> StaticType instead of Named
- Diagnostic param checking: resolve_self_refs_bounded() produces
bounded types so class-string<static> is properly validated
Subtype checking updated:
- StaticType(A) <: Named(A) and ThisType(A) <: Named(A)
- ThisType(A) <: StaticType(A)
- base_name(), top_level_class_names(), collect_class_names() all
handle the new variants
Peripheral sites updated:
- return_type_is_mixin_self handles StaticType/ThisType
- is_simple_php_type handles StaticType/ThisType
- Union member deduplication handles StaticType/ThisType
Copy file name to clipboardExpand all lines: docs/CHANGELOG.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -64,7 +64,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
64
64
-**Static method calls resolve return types as accurately as instance calls.**`Foo::bar()` previously missed inference that `$foo->bar()` already had: return types behind a `@phpstan-type` alias, inherited return types substituted through a generic interface or trait, and the `__callStatic()` magic-method fallback. These now resolve the same way for both call styles.
65
65
-**Facade static calls keep concrete method return types.** Static calls on Laravel-style facades now resolve missing methods through `getFacadeAccessor()` and facade `@mixin` targets before falling back to `__callStatic()`, so values like `Driver::details()` keep the concrete provider method return type instead of degrading to the facade's broad magic-call return. Contributed by @calebdw.
66
66
-**`class-string<static>` parameters no longer reject sibling subclass constants.** Static helper calls from a shared base class that pass concrete `::class` constants for sibling subclasses no longer report false argument-type mismatches against `class-string<static>`. Contributed by @calebdw.
67
-
-**`class-string<static>` parameters now diagnose provably invalid class strings.** Passing an unrelated class to a `class-string<static>` parameter is now flagged as a type mismatch instead of being silently accepted. The diagnostic resolves `static` to the declaring class at the call site and checks whether the argument class is in the inheritance hierarchy, so child classes and siblings are still accepted while unrelated classes are rejected. Contributed by @calebdw.
67
+
-**`class-string<static>` parameters now diagnose provably invalid class strings.** Passing an unrelated class to a `class-string<static>` parameter is now flagged as a type mismatch instead of being silently accepted. The diagnostic resolves `static` to the declaring class at the call site and checks whether the argument class is in the inheritance hierarchy, so child classes and siblings are still accepted while unrelated classes are rejected. The type system now models `static` and `$this` as bounded types (`StaticType` and `ThisType`) that preserve late-static-binding semantics instead of flattening to a bare class name. Contributed by @calebdw.
68
68
-**Built-in PHP classes shadowed by vendor polyfills resolve to the real definition.** When an installed package ships a polyfill for a PHP built-in (for example symfony/polyfill-php84's `RoundingMode`), resolution sometimes picked the polyfill's legacy pre-enum declaration instead of the built-in, turning enum cases into plain int constants and reporting false "expects RoundingMode, got int" argument mismatches. Which declaration won could change from one run to the next, making whole-project analysis results nondeterministic. Global names of built-in classes now always resolve to the bundled PHP definition, and classes discovered inside phar archives are indexed in a stable order.
69
69
-**Member name positions no longer suggest classes.** Typing a name after `function`, `const`, or enum `case` (for example `protected function getC`) no longer offers unrelated class names from the project. Property names were already safe because they start with `$`. Contributed by @calebdw.
70
70
-**Null-initialized variables reassigned in an untyped foreach are not stuck as `null`.** When the iterable has no known element type (for example an untyped parameter), the loop value is now treated as `mixed`, so `$x = $value` after `$x = null` participates in post-loop merge and `is_null` early-return narrowing instead of leaving a false `null` type at later call sites. Contributed by @calebdw.
0 commit comments