nikic/php-ast

Incorrect returnType representation for `fn() : int => []` (AST_ARROW_FUNC)

TysonAndre opened this issue · 0 comments

Expected: The returnType for AST_ARROW_FUNC is a Node with kind AST_TYPE and flags TYPE_LONG.
Observed: The returnType for AST_ARROW_FUNC is the literal string int. Functions
Cause: I missed some conditionals for AST_CLOSURE that also apply to AST_ARROW_FUNC in ast.c.

No changes to Zend/zend_ast.c have been made in PHP-7.4 since the arrow_functions_v2 RFC was merged.

// 'fn() : int => 1;'      
AST_STMT_LIST [] #1
        0 => AST_ARROW_FUNC [] #1:1
                name => {closure}
                docComment => null
                params => AST_PARAM_LIST [] #1
                stmts => AST_RETURN [] #1
                        expr => 1
                returnType => int
                __declId => 0
// 'fn() : array => [];'
AST_STMT_LIST [] #1
        0 => AST_ARROW_FUNC [] #1:1
                name => {closure}
                docComment => null
                params => AST_PARAM_LIST [] #1
                stmts => AST_RETURN [] #1
                        expr => AST_ARRAY [ARRAY_SYNTAX_SHORT] #1
                returnType => AST_TYPE [TYPE_ARRAY] #1
                __declId => 0
php > var_export(ast\parse_code('<?php fn() : int => 1;', 70));
ast\Node::__set_state(array(
   'kind' => 132,
   'flags' => 0,
   'lineno' => 1,
   'children' => 
  array (
    0 => 
    ast\Node::__set_state(array(
       'kind' => 71,
       'flags' => 0,
       'lineno' => 1,
       'children' => 
      array (
        'name' => '{closure}',
        'docComment' => NULL,
        'params' => 
        ast\Node::__set_state(array(
           'kind' => 136,
           'flags' => 0,
           'lineno' => 1,
           'children' => 
          array (
          ),
        )),
        'stmts' => 
        ast\Node::__set_state(array(
           'kind' => 279,
           'flags' => 0,
           'lineno' => 1,
           'children' => 
          array (
            'expr' => 1,
          ),
        )),
        'returnType' => 'int',
        '__declId' => 0,
      ),
       'endLineno' => 1,
    )),
  ),
))

The php interpreter seems to be processing the return type correctly - it allows real ints and throws for non-ints

php > $f = fn() : int => [];
php > $f();

Warning: Uncaught TypeError: Return value of {closure}() must be of the type int, array returned in php shell code:1
Stack trace:
#0 php shell code(1): {closure}()
#1 {main}
  thrown in php shell code on line 1