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) : self { $var = self::functionCall(); $var = self::class; $var = $obj instanceof self; $var = new self; } } function foo() { // Nested in global function to ensure nested code is not skipped over. $anon = new class extends AnonClassIsAlwaysFinal { public function unionType(): int|self|false { $var = self::$prop; $var = self::CONSTANT; $var = $obj instanceof // Comment. self; $var = new self(); } }; } 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|self|false { $var = self::$prop; $var = self::CONSTANT; $var = $obj instanceof // Comment. self; $var = new self::$className; } }; } } enum FinalByDesign { public function typedMethod(): self|ArrayAccess { $var = self::functionCall(); $var = self::class; $var = $obj instanceof self; $var = new self; } } final class ArrowFunctionsAreOpen { public function foobar() { $arrow = static fn(): self => new self(); } } final class DNFReturnType { public function hasDNF() : (A&self)|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;