Skip to content

Commit f7f4c95

Browse files
phpstan-botclaude
andcommitted
Add test cases for template property types to verify TypeCombinator::intersect() preserves generics
Adds test coverage for properties typed with class-level template parameters (e.g. `@var \WeakMap<T, U>|null`) to ensure the intersect call in NewHandler does not lose generic type information when template types are involved. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8c0cec1 commit f7f4c95

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

tests/PHPStan/Analyser/nsrt/bug-11844.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,36 @@ public static function initStatic(): void
6767
}
6868
}
6969
}
70+
71+
/**
72+
* @template T of object
73+
* @template U
74+
*/
75+
class Baz
76+
{
77+
/**
78+
* @var \WeakMap<T, U>|null
79+
*/
80+
private ?\WeakMap $instanceMap = null;
81+
82+
/**
83+
* @var \WeakMap<T, U>|null
84+
*/
85+
private static ?\WeakMap $staticMap = null;
86+
87+
public function initInstance(): void
88+
{
89+
if ($this->instanceMap === null) {
90+
$this->instanceMap = new \WeakMap();
91+
assertType('WeakMap<T of object (class Bug11844Nsrt\Baz, argument), U (class Bug11844Nsrt\Baz, argument)>', $this->instanceMap);
92+
}
93+
}
94+
95+
public static function initStatic(): void
96+
{
97+
if (self::$staticMap === null) {
98+
self::$staticMap = new \WeakMap();
99+
assertType('WeakMap<T of object (class Bug11844Nsrt\Baz, argument), U (class Bug11844Nsrt\Baz, argument)>', self::$staticMap);
100+
}
101+
}
102+
}

tests/PHPStan/Rules/TooWideTypehints/data/bug-11844.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,41 @@ public static function init(): void
104104
}
105105
}
106106
}
107+
108+
/**
109+
* @template T of object
110+
* @template U
111+
*/
112+
class TemplatePropertyCase
113+
{
114+
/**
115+
* @var \WeakMap<T, U>|null
116+
*/
117+
private ?\WeakMap $map = null;
118+
119+
public function init(): void
120+
{
121+
if ($this->map === null) {
122+
$this->map = new \WeakMap();
123+
}
124+
}
125+
}
126+
127+
/**
128+
* @template T of object
129+
* @template U
130+
*/
131+
class StaticTemplatePropertyCase
132+
{
133+
/**
134+
* @var \WeakMap<T, U>|null
135+
*/
136+
private static ?\WeakMap $map = null;
137+
138+
public static function init(): void
139+
{
140+
if (self::$map === null) {
141+
self::$map = new \WeakMap();
142+
}
143+
}
144+
}

0 commit comments

Comments
 (0)