new static(); } /* * OK, not used in a final class. */ abstract class ValidUseOfStaticInAbstract { public function usingStatic($param) : static { $var = static::functionCall(); $var = static::class; $var = $obj instanceof static; $var = new static; $var = new static::$className; } } class ValidUseOfStaticInConcrete extends Foo { public function unionType(): int|static|false { $var = static::$prop; $var = static::CONSTANT; $var = new static(); } } interface NeverFinal { public function typedMethod(): static|ArrayAccess; } /* * Unnecessary use of static for late static binding. */ final class FinalClass { public function usingStatic($param) : static { $var = static::functionCall(); $var = static::class; $var = $obj instanceof static; $var = new static; } } function foo() { // Nested in global function to ensure nested code is not skipped over. $anon = new class extends AnonClassIsAlwaysFinal { public function unionType(): int|static|false { $var = static::$prop; $var = static::CONSTANT; $var = $obj instanceof // Comment. static; $var = new static(); } }; } class NonFinalClassWithNesting { function foo() { // Nested in non-final class to ensure nested code is not skipped over. $anon = new class extends AnonClassIsAlwaysFinal { public function unionType(): int|static|false { $var = static::$prop; $var = static::CONSTANT; $var = $obj instanceof // Comment. STATIC; $var = new static::$className; } }; } } enum FinalByDesign { public function typedMethod(): static|ArrayAccess { $var = static::functionCall(); $var = static::class; $var = $obj instanceof static; $var = new static; } } final class ArrowFunctionsAreOpen { public function foobar() { $arrow = static fn(): static => new static(); } } final class DNFReturnType { public function hasDNF() : (A&static)|null {} } // Live coding. This has to be the last test in the file. class LiveCoding extends Foo { public static function bar(): static {} function baz() { $var = $obj instanceof static;