feat(stub): 添加对推断PHP文档类型的处理支持

- 在ArgInfo构造函数中添加isInferredPhpDocType参数,默认值为false
- 修改beginArgInfoCompatible方法中的有效类型判断逻辑
- 移除未使用的可变参数代码逻辑
- 更新默认参数类型和返回类型推断处理
- 添加mixed类型函数示例文件
- 修复预处理器中参数类型检查的空值判断问题
- 添加void返回类型的基本测试用例
pull/3/head
韩天峰 2 months ago
parent 785d9c9d6d
commit 215f5cdcac
  1. 9
      examples/mixed.php
  2. 2
      src/Php/Preprocessor.php
  3. 43
      src/gen_stub.php
  4. 16
      tests/aot/basic/return-void.phpt

@ -0,0 +1,9 @@
<?php
function foo(mixed $arg) {
echo __FUNCTION__;
return;
echo __FUNCTION__;
}
var_dump(foo(null));

@ -281,7 +281,7 @@ class Preprocessor extends CompilerBase
$argInfo->byRef = $param->byRef;
$argInfo->variadic = $param->variadic;
$argInfo->property = $param->isPromoted();
if ($param->type and $param->type instanceof NullableType) {
if ($param->type === null || $param->type instanceof NullableType) {
$argInfo->nullable = true;
}
if ($param->type instanceof NullableType or $param->type instanceof UnionType) {

@ -1110,12 +1110,21 @@ class ReturnInfo {
public /* readonly */ ?Type $phpDocType;
public /* readonly */ bool $tentativeReturnType;
public /* readonly */ string $refcount;
private bool $isInferredPhpDocType;
public function __construct(bool $byRef, ?Type $type, ?Type $phpDocType, bool $tentativeReturnType, ?string $refcount) {
public function __construct(
bool $byRef,
?Type $type,
?Type $phpDocType,
bool $tentativeReturnType,
?string $refcount,
bool $isInferredPhpDocType = false
) {
$this->byRef = $byRef;
$this->type = $type;
$this->phpDocType = $phpDocType;
$this->tentativeReturnType = $tentativeReturnType;
$this->isInferredPhpDocType = $isInferredPhpDocType;
$this->setRefcount($refcount);
}
@ -1172,7 +1181,7 @@ class ReturnInfo {
* based on the PHP version. Separate to allow using early returns
*/
private function beginArgInfoCompatible(string $funcInfoName, int $minArgs): string {
$effectiveType = $this->type ?? $this->phpDocType;
$effectiveType = $this->type ?? ($this->isInferredPhpDocType ? null : $this->phpDocType);
if ($effectiveType !== null) {
if (null !== $simpleReturnType = $effectiveType->tryToSimpleType()) {
if ($simpleReturnType->isBuiltin) {
@ -2252,18 +2261,6 @@ OUPUT_EXAMPLE
$code .= $argInfo->toZendInfo();
}
// Add trailing variadic to accept extra callback arguments (e.g. array_all passes value + key)
$hasVariadic = false;
foreach ($this->args as $argInfo) {
if ($argInfo->isVariadic) {
$hasVariadic = true;
break;
}
}
if (!$hasVariadic) {
$code .= "\tZEND_ARG_VARIADIC_INFO(0, _extra_args)\n";
}
$code .= "ZEND_END_ARG_INFO()";
return $code . "\n";
}
@ -4991,7 +4988,11 @@ function parseFunctionLike(
$type = $param->type ? Type::fromNode($param->type) : null;
if ($type === null && !isset($docParamTypes[$varName])) {
$defaultParamType = getMagicMethodDefaultParamType($name, $i);
$type = Type::fromString($defaultParamType ?? 'mixed');
if ($defaultParamType !== null) {
$type = Type::fromString($defaultParamType);
} else {
$docParamTypes[$varName] = 'mixed';
}
}
if ($param->default instanceof Expr\ConstFetch &&
@ -5034,8 +5035,15 @@ function parseFunctionLike(
}
$returnType = $func->getReturnType();
$isInferredReturnType = false;
if ($returnType === null && $docReturnType === null && !$name->isConstructor() && !$name->isDestructor()) {
$docReturnType = getMagicMethodDefaultReturnType($name) ?? 'mixed';
$defaultReturnType = getMagicMethodDefaultReturnType($name);
if ($defaultReturnType !== null) {
$docReturnType = $defaultReturnType;
} else {
$docReturnType = 'mixed';
$isInferredReturnType = true;
}
}
$return = new ReturnInfo(
@ -5043,7 +5051,8 @@ function parseFunctionLike(
$returnType ? Type::fromNode($returnType) : null,
$docReturnType ? Type::fromString($docReturnType) : null,
$tentativeReturnType,
$refcount
$refcount,
$isInferredReturnType
);
return new FuncInfo(

@ -0,0 +1,16 @@
--TEST--
main function
--FILE--
<?php
function foo() {
var_dump(__FUNCTION__);
return;
var_dump(__FUNCTION__);
}
function main()
{
foo();
}
?>
--EXPECT--
string(3) "foo"
Loading…
Cancel
Save