[php-src] Issue #11466: Class Incorrectly Labeled as Not Available

From: Date: Fri, 16 Jun 2023 19:18:12 +0000
Subject: [php-src] Issue #11466: Class Incorrectly Labeled as Not Available
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-244715@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/11466 Author: Zykaris ### Description I have been under the impression that PHP doesn't require forward-declarations; however, the following code results in a "class not available" fatal error, even though all classes are present: ```php <?php // infant.php class Infant { public int $health = 0; public string $name = ""; } interface Fertile { function spawn() : Infant; } ?> ``` ```php <?php // main.php require_once "infant.php"; class Zergling implements Fertile { public function spawn() : Infantling { return new Infantling(); } } class Infantling extends Infant { } print_r(new Zergling()); ?> ``` ```shell php -f main.php ``` Resulted in this output: ``` Fatal error: Could not check compatibility between Zergling::spawn(): Infantling and Fertile::spawn(): Infant, because class Infantling is not available main.php on line 6 ``` But I expected this output instead: ``` Zergling Object ( ) ``` This single-file version also produces the same error (using a strange pattern of declarations, I know, but I thought it didn't matter): ```php <?php class Zergling implements Fertile { public function spawn() : Infantling { return new Infantling(); } } class Infantling extends Infant { } class Infant { public int $health = 0; public string $name = ""; } interface Fertile { function spawn() : Infant; } print_r(new Zergling()); ?> ``` There are two ways around this error. First, the code from "infant.php" can be manually placed at the top of "main.php" (replacing the require_once statement)--note that this works even though Infantling is still declared after Zergling, as expected of PHP: ```php <?php class Infant { public int $health = 0; public string $name = ""; } interface Fertile { function spawn() : Infant; } class Zergling implements Fertile { public function spawn() : Infantling { return new Infantling(); } } class Infantling extends Infant { } print_r(new Zergling()); ?> ``` Second, declare (or--more accurately--define) Infantling above Zergling: ```php <?php require_once "infant.php"; class Infantling extends Infant { } class Zergling implements Fertile { public function spawn() : Infantling { return new Infantling(); } } print_r(new Zergling()); ?> ``` This last work-around is the simplest--and is what I have been using when this sort of issue arises--but this is an annoying inconsistency. Shouldn't a class either never need to be declared prior to usage (as long as it's included/declared somewhere in the file), or always need to be declared before usage (in which case forward-declarations would be welcome in order to allow freedom in file formatting)? I was under the impression that the former was the case with PHP, but am I mistaken, or is this really a bug? _Note: I believe this problem has been around since PHP 7 (at least). I just finally decided to mention it now._ ### PHP Version PHP 8.2.7 ### Operating System Windows 11

« previous php.bugs (#244715) next »