fix(resolver): stop corrupting single-segment `use const` imports

parseUse rebuilt the imported constant name by splitting on the last
backslash, but strrpos() returns false for a single-segment name:
`use const PHP_EOL;` registered the import as `\HP_EOL`
(substr($id, false + 1) drops the first character), and the compiled
program failed at runtime with `Undefined constant "HP_EOL"`.

$id is already the fully qualified constant name, so store it directly.
For multi-segment imports the removed recomposition produced the same
value, so their behavior is unchanged.
master
Alessio Giacobbe 2 days ago
parent b493ac79c5
commit 96ab6a53ef
No known key found for this signature in database
  1. 10
      src/Resolver/DeclarationSymbolTrait.php
  2. 28
      tests/compiler/namespace/use-const-single-segment.phpt

@ -80,11 +80,11 @@ trait DeclarationSymbolTrait
if ($type === Node\Stmt\Use_::TYPE_FUNCTION) {
$this->useFunctions[$alias] = $id;
} elseif ($type === Node\Stmt\Use_::TYPE_CONSTANT) {
$lastIndex = strrpos($id, '\\');
$cn = substr($id, $lastIndex + 1);
$ns = substr($id, 0, $lastIndex);
$fullName = $ns . '\\' . $cn;
$this->useConstants[$alias] = $fullName;
// $id is already the fully qualified constant name. Splitting
// and re-joining it on `\` corrupted single-segment imports:
// `use const PHP_EOL;` resolved to `\HP_EOL` because
// strrpos() returns false when there is no separator.
$this->useConstants[$alias] = $id;
} else {
$idLower = strtolower($id);
if ($idLower === 'native_types') {

@ -0,0 +1,28 @@
--TEST--
use const with a single-segment (global) constant name
--FILE--
<?php
namespace App {
use const PHP_EOL;
const ANSWER = 42;
function hello(): string
{
return "hello" . PHP_EOL;
}
}
namespace {
use const App\ANSWER;
function main(): void
{
echo \App\hello();
echo ANSWER, "\n";
}
}
?>
--EXPECT--
hello
42
Loading…
Cancel
Save