Skip to content

Commit

Permalink
#2276 - Add support for mixed in return types
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeckerson committed Sep 18, 2021
1 parent cd331d1 commit c0dd5e8
Show file tree
Hide file tree
Showing 12 changed files with 358 additions and 26 deletions.
10 changes: 5 additions & 5 deletions Library/ArgInfoDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class ArgInfoDefinition
/**
* @var string
*/
private string $name = '';
private string $name;

/**
* @var ClassMethodParameters|null
Expand Down Expand Up @@ -61,18 +61,18 @@ class ArgInfoDefinition
/**
* ArgInfoDefinition constructor.
*
* @param $name
* @param string $name
* @param ClassMethod $functionLike
* @param CodePrinter $codePrinter
* @param CompilationContext $compilationContext
* @param false $returnByRef
* @param bool $returnByRef
*/
public function __construct(
$name,
string $name,
ClassMethod $functionLike,
CodePrinter $codePrinter,
CompilationContext $compilationContext,
$returnByRef = false
bool $returnByRef = false
) {
$this->functionLike = $functionLike;
$this->codePrinter = $codePrinter;
Expand Down
2 changes: 1 addition & 1 deletion Library/ClassMethod.php
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ public function areReturnTypesNullCompatible(): bool
*/
public function areReturnTypesIntCompatible(): bool
{
$types = ['int', 'uint', 'char', 'uchar', 'long', 'ulong', 'mixed'];
$types = ['int', 'uint', 'char', 'uchar', 'long', 'ulong'];

foreach ($this->returnTypes as $returnType => $definition) {
if (in_array($returnType, $types)) {
Expand Down
4 changes: 3 additions & 1 deletion Library/Exception/InvalidTypeException.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
* the LICENSE file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Zephir\Exception;

final class InvalidTypeException extends CompilerException
Expand All @@ -19,7 +21,7 @@ final class InvalidTypeException extends CompilerException
* @param string $type
* @param array|null $expression
*/
public function __construct($type, array $expression = null)
public function __construct(string $type, array $expression = null)
{
$message = sprintf(
'Returning type: %s but this type is not compatible with return-type hints declared in the method',
Expand Down
38 changes: 21 additions & 17 deletions Library/Statements/ReturnStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@

namespace Zephir\Statements;

use function Zephir\add_slashes;
use ReflectionException;
use Zephir\CompilationContext;
use Zephir\Exception;
use Zephir\Exception\CompilerException;
use Zephir\Exception\InvalidTypeException;
use Zephir\Expression;
use Zephir\Types;

use function Zephir\add_slashes;

/**
* ReturnStatement.
*
Expand All @@ -28,9 +31,10 @@ final class ReturnStatement extends StatementAbstract
/**
* @param CompilationContext $compilationContext
*
* @throws CompilerException
* @throws Exception
* @throws ReflectionException
*/
public function compile(CompilationContext $compilationContext)
public function compile(CompilationContext $compilationContext): void
{
$statement = $this->statement;

Expand All @@ -50,14 +54,14 @@ public function compile(CompilationContext $compilationContext)
);
}

/*
/**
* Use return member for properties on this
*/
if ('property-access' == $statement['expr']['type']) {
if ('variable' == $statement['expr']['left']['type']) {
if ('this' == $statement['expr']['left']['value']) {
if ('variable' == $statement['expr']['right']['type']) {
/*
/**
* If the property is accessed on 'this', we check if the property does exist.
*/
$property = $statement['expr']['right']['value'];
Expand All @@ -82,7 +86,7 @@ public function compile(CompilationContext $compilationContext)
}
}

/*
/**
* Fetches return_value and tries to return the value directly there.
*/
$variable = $compilationContext->symbolTable->getVariable('return_value');
Expand All @@ -92,13 +96,13 @@ public function compile(CompilationContext $compilationContext)
$expr->setReadOnly(true);
$resolvedExpr = $expr->compile($compilationContext);

/*
/**
* Here we check if the variable returns a compatible type according to its type hints
*/
if ($currentMethod->hasReturnTypes()) {
switch ($resolvedExpr->getType()) {
case Types::T_NULL:
if (false == $currentMethod->areReturnTypesNullCompatible()) {
if (!$currentMethod->areReturnTypesNullCompatible() && !$currentMethod->isMixed()) {
throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
}
break;
Expand All @@ -109,26 +113,26 @@ public function compile(CompilationContext $compilationContext)
case Types::T_ULONG:
case Types::T_CHAR:
case Types::T_UCHAR:
if (false == $currentMethod->areReturnTypesIntCompatible()) {
if (!$currentMethod->areReturnTypesIntCompatible() && !$currentMethod->isMixed()) {
throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
}
break;

case Types::T_BOOL:
if (false == $currentMethod->areReturnTypesBoolCompatible()) {
if (!$currentMethod->areReturnTypesBoolCompatible() && !$currentMethod->isMixed()) {
throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
}
break;

case Types::T_DOUBLE:
if (false == $currentMethod->areReturnTypesDoubleCompatible()) {
if (!$currentMethod->areReturnTypesDoubleCompatible() && !$currentMethod->isMixed()) {
throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
}
break;

case Types::T_STRING:
case Types::T_ISTRING:
if (false == $currentMethod->areReturnTypesStringCompatible()) {
if (!$currentMethod->areReturnTypesStringCompatible() && !$currentMethod->isMixed()) {
throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
}
break;
Expand All @@ -147,26 +151,26 @@ public function compile(CompilationContext $compilationContext)
case Types::T_ULONG:
case Types::T_CHAR:
case Types::T_UCHAR:
if (false == $currentMethod->areReturnTypesIntCompatible()) {
if (!$currentMethod->areReturnTypesIntCompatible() && !$currentMethod->isMixed()) {
throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
}
break;

case Types::T_DOUBLE:
if (false == $currentMethod->areReturnTypesDoubleCompatible()) {
if (!$currentMethod->areReturnTypesDoubleCompatible() && !$currentMethod->isMixed()) {
throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
}
break;

case Types::T_STRING:
case Types::T_ISTRING:
if (false == $currentMethod->areReturnTypesStringCompatible()) {
if (!$currentMethod->areReturnTypesStringCompatible() && !$currentMethod->isMixed()) {
throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
}
break;

case Types::T_BOOL:
if (false == $currentMethod->areReturnTypesBoolCompatible()) {
if (!$currentMethod->areReturnTypesBoolCompatible() && !$currentMethod->isMixed()) {
throw new InvalidTypeException($resolvedExpr->getType(), $statement['expr']);
}
break;
Expand Down Expand Up @@ -314,7 +318,7 @@ public function compile(CompilationContext $compilationContext)
return;
}

/*
/**
* Return without an expression
*/
$codePrinter->output('RETURN_MM_NULL();');
Expand Down
3 changes: 2 additions & 1 deletion ext/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ if test "$PHP_STUB" = "yes"; then
stub/typehinting/testabstract.zep.c
stub/typeinstances.zep.c
stub/typeoff.zep.c
stub/types/mixedtype.zep.c
stub/unknownclass.zep.c
stub/unsettest.zep.c
stub/usetest.zep.c
Expand All @@ -232,7 +233,7 @@ if test "$PHP_STUB" = "yes"; then
stub/13__closure.zep.c "
PHP_NEW_EXTENSION(stub, $stub_sources, $ext_shared,, )
PHP_ADD_BUILD_DIR([$ext_builddir/kernel/])
for dir in "stub stub/bench stub/builtin stub/constructors stub/flow stub/globals stub/globals/session stub/integration/psr stub/integration/psr/http/message stub/interfaces stub/invokes stub/issue2165 stub/mcall stub/namespaces stub/namespaces/a/b stub/oo stub/oo/extend stub/oo/extend/db stub/oo/extend/db/query stub/oo/extend/db/query/placeholder stub/oo/extend/spl stub/oo/scopes stub/ooimpl stub/optimizers stub/properties stub/requires stub/router stub/typehinting"; do
for dir in "stub stub/bench stub/builtin stub/constructors stub/flow stub/globals stub/globals/session stub/integration/psr stub/integration/psr/http/message stub/interfaces stub/invokes stub/issue2165 stub/mcall stub/namespaces stub/namespaces/a/b stub/oo stub/oo/extend stub/oo/extend/db stub/oo/extend/db/query stub/oo/extend/db/query/placeholder stub/oo/extend/spl stub/oo/scopes stub/ooimpl stub/optimizers stub/properties stub/requires stub/router stub/typehinting stub/types"; do
PHP_ADD_BUILD_DIR([$ext_builddir/$dir])
done
PHP_SUBST(STUB_SHARED_LIBADD)
Expand Down
3 changes: 2 additions & 1 deletion ext/config.w32
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ if (PHP_STUB != "no") {
ADD_SOURCES(configure_module_dirname + "/stub/optimizers", "isscalar.zep.c acos.zep.c arraymerge.zep.c asin.zep.c cos.zep.c createarray.zep.c ldexp.zep.c sin.zep.c sqrt.zep.c strreplace.zep.c substr.zep.c tan.zep.c", "stub");
ADD_SOURCES(configure_module_dirname + "/stub/requires", "external3.zep.c", "stub");
ADD_SOURCES(configure_module_dirname + "/stub/router", "exception.zep.c route.zep.c", "stub");
ADD_SOURCES(configure_module_dirname + "/stub/typehinting", "testabstract.zep.c", "stub");
ADD_SOURCES(configure_module_dirname + "/stub/typehinting", "testabstract.zep.c", "stub");
ADD_SOURCES(configure_module_dirname + "/stub/types", "mixedtype.zep.c", "stub");
ADD_FLAG("CFLAGS_STUB", "/D ZEPHIR_RELEASE /Oi /Ot /Oy /Ob2 /Gs /GF /Gy /GL");
ADD_FLAG("CFLAGS", "/D ZEPHIR_RELEASE /Oi /Ot /Oy /Ob2 /Gs /GF /Gy /GL");
ADD_FLAG("LDFLAGS", "/LTCG");
Expand Down
2 changes: 2 additions & 0 deletions ext/stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ zend_class_entry *stub_trytest_ce;
zend_class_entry *stub_typehinting_testabstract_ce;
zend_class_entry *stub_typeinstances_ce;
zend_class_entry *stub_typeoff_ce;
zend_class_entry *stub_types_mixedtype_ce;
zend_class_entry *stub_unknownclass_ce;
zend_class_entry *stub_unsettest_ce;
zend_class_entry *stub_usetest_ce;
Expand Down Expand Up @@ -465,6 +466,7 @@ static PHP_MINIT_FUNCTION(stub)
ZEPHIR_INIT(Stub_TypeHinting_TestAbstract);
ZEPHIR_INIT(Stub_TypeInstances);
ZEPHIR_INIT(Stub_Typeoff);
ZEPHIR_INIT(Stub_Types_MixedType);
ZEPHIR_INIT(Stub_UnknownClass);
ZEPHIR_INIT(Stub_Unsettest);
ZEPHIR_INIT(Stub_UseTest);
Expand Down
1 change: 1 addition & 0 deletions ext/stub.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@
#include "stub/typehinting/testabstract.zep.h"
#include "stub/typeinstances.zep.h"
#include "stub/typeoff.zep.h"
#include "stub/types/mixedtype.zep.h"
#include "stub/unknownclass.zep.h"
#include "stub/unsettest.zep.h"
#include "stub/usetest.zep.h"
Expand Down
130 changes: 130 additions & 0 deletions ext/stub/types/mixedtype.zep.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit c0dd5e8

Please sign in to comment.