refactor(aot): 移除UnsafePtr类型支持并优化std容器实现

- 移除UnsafePtr类型声明及相关参数标记功能
- 修改std容器变量访问方式,统一使用_ref后缀引用
- 更新unsafe_cast函数参数验证逻辑,移除UnsafePtr参数检查
- 重构std容器在C++代码中的声明和初始化方式
- 删除相关测试用例及单元测试中的UnsafePtr验证逻辑
- 统一std容器赋值、遍历、删除操作的引用访问模式
pull/1/head
韩天峰 3 months ago
parent 000b6a221d
commit 11acfdf10f
  1. 7
      phpunit/code/std-unsafe-cast-rejects-unsafe-ptr-local-copy.php
  2. 6
      phpunit/code/std-unsafe-cast-requires-unsafe-ptr.php
  3. 11
      phpunit/code/std-unsafe-ptr-argument-requires-container.php
  4. 6
      phpunit/code/std-unsafe-ptr-parameter-cannot-be-reassigned.php
  5. 10
      phpunit/src/ArgInfoTest.php
  6. 32
      phpunit/src/AssignTest.php
  7. 1
      phpunit/src/CompilerBaseApiTest.php
  8. 3
      phpunit/src/PreprocessorTest.php
  9. 1
      src/Php/ArgInfo.php
  10. 108
      src/Php/CompilerBase.php
  11. 38
      src/Php/Parser/StdContainerParser.php
  12. 6
      tests/aot/std-array/007.phpt
  13. 6
      tests/aot/std-array/008.phpt
  14. 12
      tests/aot/std-map/005.phpt
  15. 6
      tests/aot/std-map/006.phpt
  16. 6
      tests/aot/std-unordered-map/005.phpt
  17. 6
      tests/aot/std-unordered-map/006.phpt
  18. 6
      tests/aot/std-vector/006.phpt
  19. 6
      tests/aot/std-vector/007.phpt
  20. 6
      tests/aot/std-vector/008.phpt
  21. 4
      tests/aot/std-vector/009.phpt

@ -1,7 +0,0 @@
<?php
function std_unsafe_cast_rejects_unsafe_ptr_local_copy(UnsafePtr $unsafePtr): void
{
$ptr = $unsafePtr;
$array = std::unsafe_cast(std::array(native_types::type_int, 3), $ptr);
}

@ -1,6 +0,0 @@
<?php
function std_unsafe_cast_requires_unsafe_ptr(mixed $ptr): void
{
$array = std::unsafe_cast(std::array(native_types::type_int, 3), $ptr);
}

@ -1,11 +0,0 @@
<?php
function std_unsafe_ptr_accepts_container_only(UnsafePtr $unsafePtr): void
{
}
function test_std_unsafe_ptr_argument_requires_container(): void
{
$value = 1;
std_unsafe_ptr_accepts_container_only($value);
}

@ -1,6 +0,0 @@
<?php
function std_unsafe_ptr_parameter_cannot_be_reassigned(UnsafePtr $unsafePtr): void
{
$unsafePtr = null;
}

@ -22,7 +22,6 @@ class ArgInfoTest extends TestCase
$this->assertFalse($arg->variadic);
$this->assertFalse($arg->nullable);
$this->assertFalse($arg->property);
$this->assertFalse($arg->unsafePtr);
}
public function testNameAndType(): void
@ -87,15 +86,6 @@ class ArgInfoTest extends TestCase
$this->assertTrue($arg->property);
}
public function testUnsafePtr(): void
{
$arg = new ArgInfo();
$this->assertFalse($arg->unsafePtr);
$arg->unsafePtr = true;
$this->assertTrue($arg->unsafePtr);
}
public function testAllFlagsCombined(): void
{
$arg = new ArgInfo();

@ -22,38 +22,6 @@ class AssignTest extends \BaseTest
);
}
public function testStdUnsafeCastRequiresUnsafePtr()
{
$this->exec(
'std::unsafe_cast() expects second argument to be an UnsafePtr parameter',
'std-unsafe-cast-requires-unsafe-ptr.php'
);
}
public function testStdUnsafeCastRejectsUnsafePtrLocalCopy()
{
$this->exec(
'std::unsafe_cast() expects second argument to be an UnsafePtr parameter',
'std-unsafe-cast-rejects-unsafe-ptr-local-copy.php'
);
}
public function testStdUnsafePtrParameterCannotBeReassigned()
{
$this->exec(
'Cannot re-assign UnsafePtr parameter `$unsafePtr`',
'std-unsafe-ptr-parameter-cannot-be-reassigned.php'
);
}
public function testStdUnsafePtrArgumentRequiresContainer()
{
$this->exec(
'Argument `unsafePtr` must be a std container variable for UnsafePtr parameter',
'std-unsafe-ptr-argument-requires-container.php'
);
}
// === Object value assigned to non-object variable (right side is New_ expr) ===
public function testObjectToInt()

@ -82,7 +82,6 @@ class CompilerBaseApiTest extends TestCase
$this->assertEquals(CompilerBase::TYPE_VAR, $this->compiler->getTypeFromZendType('null'));
$this->assertEquals(CompilerBase::TYPE_VAR, $this->compiler->getTypeFromZendType('callable'));
$this->assertEquals(CompilerBase::TYPE_VAR, $this->compiler->getTypeFromZendType('iterable'));
$this->assertEquals(CompilerBase::TYPE_VAR, $this->compiler->getTypeFromZendType('UnsafePtr'));
}
public function testGetTypeFromZendTypeUnknown(): void

@ -88,12 +88,11 @@ class PreprocessorTest extends TestCase
$this->assertEquals('php::Object obj', $result);
}
public function testGenArgumentDeclarationUnsafePtr(): void
public function testGenArgumentDeclarationVar(): void
{
$arg = new ArgInfo();
$arg->name = 'container';
$arg->type = 'php::Var';
$arg->unsafePtr = true;
$result = $this->invokeMethod('genArgumentDeclaration', $arg);
$this->assertEquals('php::Var container', $result);
}

@ -21,5 +21,4 @@ class ArgInfo
public bool $variadic = false;
public bool $nullable = false;
public bool $property = false;
public bool $unsafePtr = false;
}

@ -168,8 +168,6 @@ class CompilerBase extends \PhpAot\Core\Translator
'callable' => self::TYPE_VAR,
// iterable 类型,可以是数组或者对象
'iterable' => self::TYPE_VAR,
// 编译器符号类型,C++ 层仍使用 php::Var 承载 null zval 中的 value.ptr
'UnsafePtr' => self::TYPE_VAR,
'stream' => self::TYPE_STREAM,
];
protected array $globalHeaders = [
@ -692,7 +690,11 @@ class CompilerBase extends \PhpAot\Core\Translator
case 'Scalar_Float':
case 'Scalar_String':
case 'Expr_Variable':
return $this->parseIdentifier($expr);
$varName = $this->parseIdentifier($expr);
if ($this->isStdContainer($varName)) {
return $varName . '_ref';
}
return $varName;
case 'Scalar_MagicConst_File':
case 'Scalar_MagicConst_Dir':
case 'Scalar_MagicConst_Line':
@ -798,8 +800,8 @@ class CompilerBase extends \PhpAot\Core\Translator
if ($this->hasLocalVar($name)) {
return $this->context->localVars[$name];
}
if ($this->hasLocalVar($name)) {
return $this->globalVars[$name];
if ($this->hasScopeGlobalVar($name)) {
return $this->context->globalVars[$name];
}
return self::TYPE_VAR;
@ -1634,10 +1636,6 @@ class CompilerBase extends \PhpAot\Core\Translator
if ($var === 'this_') {
$this->fatalError($left, 'Cannot re-assign $this');
}
if ($this->isVarExpr($left) and $this->isUnsafePtrParameter($var)) {
$this->fatalError($left, "Cannot re-assign UnsafePtr parameter `\${$var}`");
}
$type = $this->detectTypeOfExpr($right);
if ($this->isVarExpr($left)) {
@ -1761,7 +1759,7 @@ class CompilerBase extends \PhpAot\Core\Translator
$this->fatalError($right, 'Cannot copy std container with different type');
}
return $leftVar . ' = ' . $this->parseStdContainerCopyExpr($right);
return $leftVar . '_ref = ' . $this->parseStdContainerCopyExpr($right);
}
protected function parseAssignRightExpr(Expr $right): string
@ -2665,10 +2663,6 @@ class CompilerBase extends \PhpAot\Core\Translator
if ($param->byRef) {
return self::TYPE_REF;
}
if ($this->isUnsafePtrTypeDecl($param->type)) {
$argInfo->unsafePtr = true;
return self::TYPE_VAR;
}
$class = '';
$type = $this->parseTypeDecl($param->type, self::DECL_TYPE_OF_PARAM, $class);
// stream 是伪类型,实际运行时依然作为 var 处理
@ -3496,10 +3490,6 @@ class CompilerBase extends \PhpAot\Core\Translator
foreach ($args as $i => $arg) {
$argInfo = $this->getArgInfo($arg, $nativeFunc, $i);
if ($argInfo->unsafePtr) {
$argList[] = $this->getUnsafePtrConvertedArg($arg, $argInfo);
continue;
}
if ($argInfo->variadic) {
$argsSlice = array_slice($args, $i);
if (count($argsSlice) === 1 and $argsSlice[0]->unpack) {
@ -3712,7 +3702,7 @@ class CompilerBase extends \PhpAot\Core\Translator
}
$expr = $this->parseIdentifier($arg->value);
if ($this->isVarExpr($arg->value) and $this->isStdContainer($arg->value->name)) {
return $this->convertArrayExpr($expr);
return $this->convertArrayExpr($expr . '_ref');
}
return $expr;
}
@ -4583,6 +4573,13 @@ class CompilerBase extends \PhpAot\Core\Translator
$this->checkVarAssignExpr($arg, $argInfo->type, $type);
if ($argInfo->type === self::TYPE_VAR && $this->isVarExpr($arg->value)) {
$varName = $this->parseIdentifier($arg->value);
if ($this->isStdContainer($varName)) {
return $varName;
}
}
if ($argInfo->type === self::TYPE_OBJECT) {
if ($this->isVarExpr($arg->value)) {
$object = $this->parseVariable($arg->value);
@ -4599,24 +4596,6 @@ class CompilerBase extends \PhpAot\Core\Translator
return $this->convertExprType($expr, $argInfo->type, $type);
}
protected function getUnsafePtrConvertedArg(Node\Arg $arg, ArgInfo $argInfo): string
{
if (!$this->isVarExpr($arg->value)) {
$this->fatalError($arg, "Argument `{$argInfo->name}` must be a std container variable for UnsafePtr parameter");
}
$var = $this->parseVariable($arg->value);
if (!$this->hasVar($var)) {
$this->fatalError($arg, 'Undefined variable `$' . $var . '`');
}
if (!$this->isStdContainer($var)) {
$this->fatalError($arg, "Argument `{$argInfo->name}` must be a std container variable for UnsafePtr parameter");
}
$info = $this->getStdContainerVarInfo($var);
return 'php_create_unsafe_ptr(&' . $var . ', ' . $info['typeId'] . ')';
}
protected function convertExprType(string $expr, $leftType, $rightType): string
{
if ($leftType === self::TYPE_FLOAT or $rightType === self::TYPE_FLOAT) {
@ -4655,7 +4634,11 @@ class CompilerBase extends \PhpAot\Core\Translator
$this->fatalError($var, 'Cannot delete element in std container in foreach loop');
}
$dim = $this->parseIdentifier($var->dim);
if ($this->isStdContainer($array)) {
$lines[] = $array . '_ref.offsetUnset(' . $dim . ');';
} else {
$lines[] = $array . '.offsetUnset(' . $dim . ');';
}
} elseif ($this->isPropertyFetch($var)) {
$object = $this->parseIdentifier($var->var);
$lines[] = $object . '.unsetProperty(' . $this->identifierToStr($var->name, literal: true) . ');';
@ -5211,7 +5194,7 @@ class CompilerBase extends \PhpAot\Core\Translator
protected function parseCastArray(Expr\Cast\Array_ $expr): string
{
return $this->convertArrayExpr($this->parseIdentifier($expr->expr));
return $this->convertArrayExpr($this->parseExpr($expr->expr));
}
protected function hasGlobalVar(string $name): bool
@ -5306,9 +5289,6 @@ class CompilerBase extends \PhpAot\Core\Translator
$this->context->inAssignExpr = false;
if ($this->isVarExpr($expr->var)) {
if ($this->isUnsafePtrParameter($left)) {
$this->fatalError($expr->var, "Cannot re-assign UnsafePtr parameter `\${$left}`");
}
if (!$this->hasVar($left)) {
$this->addLocalVar($left, self::TYPE_REF);
} else {
@ -6210,26 +6190,6 @@ class CompilerBase extends \PhpAot\Core\Translator
}
}
protected function isUnsafePtrTypeDecl(?NodeAbstract $type): bool
{
return $type !== null
and !$type instanceof UnionType
and !$type instanceof NullableType
and $this->parseIdentifier($type) === 'UnsafePtr';
}
protected function isUnsafePtrParameter(string $name): bool
{
if (!$this->functionDef) {
return false;
}
foreach ($this->functionDef->argInfoList as $argInfo) {
if ($argInfo->name === $name) {
return $argInfo->unsafePtr;
}
}
return false;
}
protected function parseParentMethodCall(Expr\StaticCall $expr): string
{
@ -6277,32 +6237,34 @@ class CompilerBase extends \PhpAot\Core\Translator
if ($type === self::TYPE_STD_ARRAY) {
$info = $this->context->stdArrays[$name];
if (isset($info['unsafePtr'])) {
$code .= 'auto &' . $name . ' = php_unsafe_cast<' . $info['decl'] . '>(' . $info['unsafePtr'] . ', ' . $info['typeId'] . ');';
} elseif ($info['bytes'] > self::MAX_BYTES_IN_STACK) {
$code .= "auto {$name}_unique_ptr = std::make_unique<{$info['decl']}>();\n";
$code .= $this->getIndent() . ' auto &' . $name . ' = *' . $name . '_unique_ptr;';
$code .= 'auto &' . $name . '_ref = php_unsafe_cast<' . $info['decl'] . '>(' . $info['unsafePtr'] . ', ' . $info['typeId'] . ');';
} else {
$code .= $info['decl'] . ' ' . $name . '{};';
$containerType = 'php::StdContainerBox<' . $info['decl'] . '>';
$code .= 'php::Var ' . $name . ' = php::Var(new ' . $containerType . '(' . $info['typeId'] . '));' . PHP_EOL;
$code .= $this->getIndent() . 'auto &' . $name . '_ref = ' . $name . '.toBox<' . $containerType . '>()->container;';
}
} elseif ($type === self::TYPE_STD_VECTOR) {
$info = $this->context->stdContainers[$name];
if (isset($info['unsafePtr'])) {
$code .= 'auto &' . $name . ' = php_unsafe_cast<' . $info['decl'] . '>(' . $info['unsafePtr'] . ', ' . $info['typeId'] . ');';
$code .= 'auto &' . $name . '_ref = php_unsafe_cast<' . $info['decl'] . '>(' . $info['unsafePtr'] . ', ' . $info['typeId'] . ');';
} else {
$code .= $info['decl'] . ' ' . $name;
$containerType = 'php::StdContainerBox<' . $info['decl'] . '>';
if ($info['size'] !== null) {
$code .= '(' . $info['size'] . ')';
$boxCtor = 'new ' . $containerType . '(' . $info['typeId'] . ', ' . $info['size'] . ')';
} else {
$code .= '{}';
$boxCtor = 'new ' . $containerType . '(' . $info['typeId'] . ')';
}
$code .= ';';
$code .= 'php::Var ' . $name . ' = php::Var(' . $boxCtor . ');' . PHP_EOL;
$code .= $this->getIndent() . 'auto &' . $name . '_ref = ' . $name . '.toBox<' . $containerType . '>()->container;';
}
} elseif ($type === self::TYPE_STD_MAP || $type === self::TYPE_STD_UNORDERED_MAP) {
$info = $this->context->stdContainers[$name];
if (isset($info['unsafePtr'])) {
$code .= 'auto &' . $name . ' = php_unsafe_cast<' . $info['decl'] . '>(' . $info['unsafePtr'] . ', ' . $info['typeId'] . ');';
$code .= 'auto &' . $name . '_ref = php_unsafe_cast<' . $info['decl'] . '>(' . $info['unsafePtr'] . ', ' . $info['typeId'] . ');';
} else {
$code .= $info['decl'] . ' ' . $name . '{};';
$containerType = 'php::StdContainerBox<' . $info['decl'] . '>';
$code .= 'php::Var ' . $name . ' = php::Var(new ' . $containerType . '(' . $info['typeId'] . '));' . PHP_EOL;
$code .= $this->getIndent() . 'auto &' . $name . '_ref = ' . $name . '.toBox<' . $containerType . '>()->container;';
}
} elseif ($type === self::TYPE_STREAM || $type === self::TYPE_BIGINT || $type === self::TYPE_DECIMAL || $type === self::TYPE_BIGFLOAT) {
$code .= self::TYPE_VAR . ' ' . $name . ';';

@ -169,7 +169,7 @@ trait StdContainerParser
protected function parseStdContainerCopyExpr(NodeAbstract $expr): string
{
if ($this->isVarExpr($expr)) {
return $this->parseVariable($expr);
return $this->parseVariable($expr) . '_ref';
}
if ($this->isArrayDimFetch($expr) and $this->isStdArrayExpr($expr)) {
return $this->parseStdArrayDimFetch($expr);
@ -196,7 +196,7 @@ trait StdContainerParser
$array = $this->parseIdentifier($expr->args[0]->value);
$info = $this->context->stdArrays[$array];
$value = $this->convertStdValueExpr($info, $expr->args[1]->value);
return "{$array}.fill({$value})";
return "{$array}_ref.fill({$value})";
}
protected function getStdArrayInfo(Expr\ArrayDimFetch $expr): ?array
@ -259,7 +259,7 @@ trait StdContainerParser
$this->fatalError($left, 'std::vector append only supports a vector variable');
}
$vector = $this->parseVariable($left->var);
return $vector . '.push_back(' . $this->convertStdValueExpr($info, $right) . ')';
return $vector . '_ref.push_back(' . $this->convertStdValueExpr($info, $right) . ')';
}
if ($left->dim === null) {
$this->fatalError($left, 'std map expects a key');
@ -327,7 +327,8 @@ trait StdContainerParser
$this->fatalError($expr, 'std::array access level exceeds array dimensions');
}
$nesting = [$this->parseVariable($tmp)];
$baseVar = $this->parseVariable($tmp);
$nesting = [$baseVar . '_ref'];
foreach ($dims as $level => $dim) {
$size = $sizes[$level];
if ($this->isScalarInt($dim)) {
@ -338,7 +339,7 @@ trait StdContainerParser
$index = $this->parseExpr($dim);
$nesting[] = '[' . Symbol::safeIndex($this->convertIntExpr($index), $size) . ']';
}
$expr->setAttribute('stdArrayDimFetch', ['var' => $nesting[0], 'accessLevel' => count($dims), 'totalLevel' => count($sizes)]);
$expr->setAttribute('stdArrayDimFetch', ['var' => $baseVar, 'accessLevel' => count($dims), 'totalLevel' => count($sizes)]);
return implode('', $nesting);
}
@ -350,13 +351,13 @@ trait StdContainerParser
$this->context->stdContainers[$container]['locking'] = true;
}
$iterator = $this->genTmpVarName();
$code = "for (auto $iterator = $container.begin(); $iterator != $container.end(); ++$iterator) {" . PHP_EOL;
$code = "for (auto $iterator = {$container}_ref.begin(); $iterator != {$container}_ref.end(); ++$iterator) {" . PHP_EOL;
$this->indentLevel++;
if ($node->keyVar) {
$keyVar = $this->parseIdentifier($node->keyVar);
$this->checkVar($node, $keyVar, $this->getStdContainerKeyType($container));
if ($this->isStdVector($container) or $this->isStdArray($container)) {
$code .= $this->getIndent() . "$keyVar = $iterator - $container.begin();" . PHP_EOL;
$code .= $this->getIndent() . "$keyVar = $iterator - {$container}_ref.begin();" . PHP_EOL;
} else {
$code .= $this->getIndent() . "$keyVar = {$iterator}->first;" . PHP_EOL;
}
@ -424,7 +425,7 @@ trait StdContainerParser
$container = $this->parseVariable($tmp);
$index = $this->parseExpr($dim);
$key = $info['kind'] === 'vector' ? $this->convertIntExpr($index) : $this->convertStdContainerKey($info, $index);
$access = $container . '.offsetGet(' . $key . ')';
$access = $container . '_ref.offsetGet(' . $key . ')';
$expr->setAttribute('stdContainerDimFetch', ['var' => $container, 'accessLevel' => 1, 'totalLevel' => 1]);
return $access;
@ -442,7 +443,7 @@ trait StdContainerParser
$container = $this->parseVariable($expr->var);
$indexExpr = $this->parseExpr($expr->dim);
$index = $info['kind'] === 'vector' ? $this->convertIntExpr($indexExpr) : $this->convertStdContainerKey($info, $indexExpr);
return $container . '.offsetSet(' . $index . ', ' . $value . ')';
return $container . '_ref.offsetSet(' . $index . ', ' . $value . ')';
}
protected function convertStdContainerKey(array $info, string $index): string
@ -563,21 +564,18 @@ trait StdContainerParser
$this->fatalError($expr->args[0]->value, 'std::unsafe_cast() expects first argument to be a std container type expression');
}
if (!$this->isVarExpr($expr->args[1]->value)) {
$this->fatalError($expr->args[1]->value, 'std::unsafe_cast() expects second argument to be an UnsafePtr variable');
$this->fatalError($expr->args[1]->value, 'std::unsafe_cast() expects second argument to be a variable');
}
$unsafePtr = $this->parseVariable($expr->args[1]->value);
if (!$this->hasVar($unsafePtr)) {
$this->fatalError($expr->args[1]->value, 'Undefined variable `$' . $unsafePtr . '`');
}
if (!$this->isUnsafePtrParameter($unsafePtr)) {
$this->fatalError($expr->args[1]->value, 'std::unsafe_cast() expects second argument to be an UnsafePtr parameter');
$sourceVar = $this->parseVariable($expr->args[1]->value);
if (!$this->hasVar($sourceVar)) {
$this->fatalError($expr->args[1]->value, 'Undefined variable `$' . $sourceVar . '`');
}
if ($containerType === 'array') {
$this->addLocalVar($var, self::TYPE_STD_ARRAY);
$this->parseStdArray($var, $typeExpr);
$this->context->stdArrays[$var]['unsafePtr'] = $unsafePtr;
return '// php_unsafe_cast<' . $this->context->stdArrays[$var]['decl'] . '>(' . $unsafePtr . ')';
$this->context->stdArrays[$var]['unsafePtr'] = $sourceVar;
return '// php_unsafe_cast<' . $this->context->stdArrays[$var]['decl'] . '>(' . $sourceVar . ')';
}
if ($containerType === 'vector') {
@ -590,8 +588,8 @@ trait StdContainerParser
$this->addLocalVar($var, self::TYPE_STD_UNORDERED_MAP);
$this->parseStdUnorderedMap($var, $typeExpr);
}
$this->context->stdContainers[$var]['unsafePtr'] = $unsafePtr;
return '// php_unsafe_cast<' . $this->context->stdContainers[$var]['decl'] . '>(' . $unsafePtr . ')';
$this->context->stdContainers[$var]['unsafePtr'] = $sourceVar;
return '// php_unsafe_cast<' . $this->context->stdContainers[$var]['decl'] . '>(' . $sourceVar . ')';
}
protected function parseStdMapKeyType(NodeAbstract $expr, string $owner): string

@ -1,10 +1,10 @@
--TEST--
std array: UnsafePtr unsafe_cast
std array: unsafe_cast
--FILE--
<?php
function std_array_unsafe_ptr_update(UnsafePtr $unsafePtr): void
function std_array_unsafe_ptr_update($source): void
{
$array = std::unsafe_cast(std::array(native_types::type_int, 3), $unsafePtr);
$array = std::unsafe_cast(std::array(native_types::type_int, 3), $source);
var_dump($array[1]);
$array[2] = 9;
}

@ -2,9 +2,9 @@
std array: unsafe_cast type mismatch
--FILE--
<?php
function std_array_unsafe_ptr_type_mismatch(UnsafePtr $unsafePtr): void
function std_array_unsafe_ptr_type_mismatch($source): void
{
$array = std::unsafe_cast(std::array(native_types::type_float, 3), $unsafePtr);
$array = std::unsafe_cast(std::array(native_types::type_float, 3), $source);
}
function main() {
@ -17,4 +17,4 @@ function main() {
}
?>
--EXPECT--
std::unsafe_cast(): UnsafePtr type mismatch
std::unsafe_cast(): std container type mismatch

@ -1,17 +1,14 @@
--TEST--
std map: UnsafePtr unsafe_cast
std map: unsafe_cast
--FILE--
<?php
function std_map_unsafe_ptr_update(UnsafePtr $unsafePtr): void
function std_map_unsafe_ptr_update($source): void
{
$map = std::unsafe_cast(std::map(complex_types::type_str, native_types::type_int), $unsafePtr);
$map = std::unsafe_cast(std::map(complex_types::type_str, native_types::type_int), $source);
var_dump($map["b"]);
$map["c"] = 9;
$GLOBALS['unsafe_ptr'] = $unsafePtr;
var_dump($GLOBALS['unsafe_ptr']);
unset($unsafePtr);
unset($source);
$array = (array)$map;
var_dump(count($array));
@ -29,6 +26,5 @@ function main() {
?>
--EXPECT--
int(7)
NULL
int(3)
int(9)

@ -2,9 +2,9 @@
std map: unsafe_cast type mismatch
--FILE--
<?php
function std_map_unsafe_ptr_type_mismatch(UnsafePtr $unsafePtr): void
function std_map_unsafe_ptr_type_mismatch($source): void
{
$map = std::unsafe_cast(std::map(complex_types::type_str, native_types::type_float), $unsafePtr);
$map = std::unsafe_cast(std::map(complex_types::type_str, native_types::type_float), $source);
}
function main() {
@ -17,4 +17,4 @@ function main() {
}
?>
--EXPECT--
std::unsafe_cast(): UnsafePtr type mismatch
std::unsafe_cast(): std container type mismatch

@ -1,10 +1,10 @@
--TEST--
std unordered map: UnsafePtr unsafe_cast
std unordered map: unsafe_cast
--FILE--
<?php
function std_unordered_map_unsafe_ptr_update(UnsafePtr $unsafePtr): void
function std_unordered_map_unsafe_ptr_update($source): void
{
$map = std::unsafe_cast(std::unordered_map(native_types::type_int, native_types::type_int), $unsafePtr);
$map = std::unsafe_cast(std::unordered_map(native_types::type_int, native_types::type_int), $source);
var_dump($map[2]);
$map[3] = 9;
}

@ -2,9 +2,9 @@
std unordered map: unsafe_cast type mismatch
--FILE--
<?php
function std_unordered_map_unsafe_ptr_type_mismatch(UnsafePtr $unsafePtr): void
function std_unordered_map_unsafe_ptr_type_mismatch($source): void
{
$map = std::unsafe_cast(std::unordered_map(native_types::type_int, native_types::type_float), $unsafePtr);
$map = std::unsafe_cast(std::unordered_map(native_types::type_int, native_types::type_float), $source);
}
function main() {
@ -17,4 +17,4 @@ function main() {
}
?>
--EXPECT--
std::unsafe_cast(): UnsafePtr type mismatch
std::unsafe_cast(): std container type mismatch

@ -1,10 +1,10 @@
--TEST--
std vector: UnsafePtr unsafe_cast
std vector: unsafe_cast
--FILE--
<?php
function std_vector_unsafe_ptr_update(UnsafePtr $unsafePtr): void
function std_vector_unsafe_ptr_update($source): void
{
$vector = std::unsafe_cast(std::vector(native_types::type_int), $unsafePtr);
$vector = std::unsafe_cast(std::vector(native_types::type_int), $source);
var_dump($vector[1]);
$vector[2] = 9;
}

@ -2,9 +2,9 @@
std vector: unsafe_cast type mismatch
--FILE--
<?php
function std_vector_unsafe_ptr_type_mismatch(UnsafePtr $unsafePtr): void
function std_vector_unsafe_ptr_type_mismatch($source): void
{
$vector = std::unsafe_cast(std::vector(native_types::type_float), $unsafePtr);
$vector = std::unsafe_cast(std::vector(native_types::type_float), $source);
}
function main() {
@ -17,4 +17,4 @@ function main() {
}
?>
--EXPECT--
std::unsafe_cast(): UnsafePtr type mismatch
std::unsafe_cast(): std container type mismatch

@ -10,9 +10,9 @@ class StdVectorUnsafeCastOther
{
}
function std_vector_unsafe_ptr_class_type_mismatch(UnsafePtr $unsafePtr): void
function std_vector_unsafe_ptr_class_type_mismatch($source): void
{
$vector = std::unsafe_cast(std::vector(StdVectorUnsafeCastOther::class), $unsafePtr);
$vector = std::unsafe_cast(std::vector(StdVectorUnsafeCastOther::class), $source);
}
function main() {
@ -25,4 +25,4 @@ function main() {
}
?>
--EXPECT--
std::unsafe_cast(): UnsafePtr type mismatch
std::unsafe_cast(): std container type mismatch

@ -5,9 +5,9 @@ std vector: namespaced self class value unsafe_cast
namespace StdVectorUnsafeCastNs {
class Holder
{
public static function update(UnsafePtr $unsafePtr): void
public static function update($source): void
{
$vector = std::unsafe_cast(std::vector(self::class), $unsafePtr);
$vector = std::unsafe_cast(std::vector(self::class), $source);
echo "ok\n";
}

Loading…
Cancel
Save