eclipse-pdt / pdt

PHP Development Tools project (PDT)
https://eclipse.org/pdt
Eclipse Public License 2.0
188 stars 46 forks source link

Missing error on unpacking variable other than array or Traversables #222

Open the-liquid-metal opened 1 year ago

the-liquid-metal commented 1 year ago

Bug Description Missing error on unpacking variable other than array or Traversables.

Eclipse environment Version: 2023-06 (4.28.0) Build id: 20230608-1333 PDT: 8.0.0.202306050832

System

To Reproduce Steps to reproduce the behavior: copy-paste this script to the IDE

<?php
declare(strict_types=1);

namespace ns1\ns2;

use closure;
use stdClass;
use Traversable;

class Test47 implements Traversable {}

class MyClass {
    public array   $propArray = [];
    public null    $propNull = null;
    public int     $propInt = 10;
    public float   $propFloat = 20.34;
    public bool    $propBool = false;
    public string  $propString = "Hello";
    public object  $propObject;
    public closure $propClosure;
    /**
     * @var callable
     */
    public $propCallable;
    public Traversable $propTraversable;

    public static function statFunc() {
        echo "from statFunc\n";
    }
    public function __construct() {
        $this->propObject = new stdClass;
        $this->propCallable = [self::class, "statFunc"];
    }
}

function returnArray(): array {
    return [];
}

function returnNull(): null{
    return null;
}

function returnInt(): int {
    return 10;
}

function returnFloat(): float{
    return 20.34;
}

function returnBool(): bool {
    return false;
}

function returnString(): bool {
    return false;
}

function returnObject(): object {
    return new MyClass;
}

function returnClosure(): closure {
    return fn($a) => $a;
}

function returnCallable(): callable {
    return [MyClass::class, "statFunc"];
}

function returnTraversable(): Traversable {
    return new Test47;
}

$myInst = new MyClass;

function testUnpacking($par1, $par2, $par3) {
    echo $par1, $par2, $par3, "\n";
}

// --- array value ------------------------------------------------------------
$var1a = [1,2,3];
$var1b = [10,20,30, ...$var1a]; // OK
testUnpacking(...$var1a);       // OK

$var1c = returnArray();
$var1d = [10,20,30, ...$var1c]; // OK
testUnpacking(...$var1c);       // OK

$var1e = $myInst->propArray;
$var1f = [10,20,30, ...$var1e]; // OK
testUnpacking(...$var1e);       // OK

// --- null value -------------------------------------------------------------
$var2a = null;
$var2b = [10,20,30, ...$var2a]; // this statement must trigger error
testUnpacking(...$var2a);       // this statement must trigger error

$var2c = returnNull();
$var2d = [10,20,30, ...$var2c]; // this statement must trigger error
testUnpacking(...$var2c);       // this statement must trigger error

$var2e = $myInst->propNull;
$var2f = [10,20,30, ...$var2e]; // this statement must trigger error
testUnpacking(...$var2e);       // this statement must trigger error

// --- undefined variable -----------------------------------------------------
$var3b = [10,20,30, ...$var3a]; // this statement must trigger error
testUnpacking(...$var3a);       // this statement must trigger error

// --- boolean value ----------------------------------------------------------
$var4a = false;
$var4b = [10,20,30, ...$var4a]; // this statement must trigger error
testUnpacking(...$var4a);       // this statement must trigger error

$var4c = returnBool();
$var4d = [10,20,30, ...$var4c]; // this statement must trigger error
testUnpacking(...$var4c);       // this statement must trigger error

$var4e = $myInst->propBool;
$var4f = [10,20,30, ...$var4e]; // this statement must trigger error
testUnpacking(...$var4e);       // this statement must trigger error

// --- int value --------------------------------------------------------------
$var5a = 10;
$var5b = [10,20,30, ...$var5a]; // this statement must trigger error
testUnpacking(...$var5a);       // this statement must trigger error

$var5c = returnInt();
$var5d = [10,20,30, ...$var5c]; // this statement must trigger error
testUnpacking(...$var5c);       // this statement must trigger error

$var5e = $myInst->propInt;
$var5f = [10,20,30, ...$var5e]; // this statement must trigger error
testUnpacking(...$var5e);       // this statement must trigger error

// --- float value ------------------------------------------------------------
$var6a = 20.34;
$var6b = [10,20,30, ...$var6a]; // this statement must trigger error
testUnpacking(...$var6a);       // this statement must trigger error

$var6c = returnFloat();
$var6d = [10,20,30, ...$var6c]; // this statement must trigger error
testUnpacking(...$var6c);       // this statement must trigger error

$var6e = $myInst->propFloat;
$var6f = [10,20,30, ...$var6e]; // this statement must trigger error
testUnpacking(...$var6e);       // this statement must trigger error

// --- string value -----------------------------------------------------------
$var7a = "Hello";
$var7b = [10,20,30, ...$var7a]; // this statement must trigger error
testUnpacking(...$var7a);       // this statement must trigger error

$var7c = returnString();
$var7d = [10,20,30, ...$var7c]; // this statement must trigger error
testUnpacking(...$var7c);       // this statement must trigger error

$var7e = $myInst->propString;
$var7f = [10,20,30, ...$var7e]; // this statement must trigger error
testUnpacking(...$var7e);       // this statement must trigger error

// --- object value -----------------------------------------------------------
$var8a = new MyClass;
$var8b = [10,20,30, ...$var8a]; // this statement must trigger error
testUnpacking(...$var8a);       // this statement must trigger error

$var8c = returnObject();
$var8d = [10,20,30, ...$var8c]; // this statement must trigger error
testUnpacking(...$var8c);       // this statement must trigger error

$var8e = $myInst->propObject;
$var8f = [10,20,30, ...$var8e]; // this statement must trigger error
testUnpacking(...$var8e);       // this statement must trigger error

// --- closure value ----------------------------------------------------------
$var9a = fn($a) => $a*10;
$var9b = [10,20,30, ...$var9a]; // this statement must trigger error
testUnpacking(...$var9a);       // this statement must trigger error

$var9c = returnClosure();
$var9d = [10,20,30, ...$var9c]; // this statement must trigger error
testUnpacking(...$var9c);          // this statement must trigger error

$var9e = $myInst->propClosure;
$var9f = [10,20,30, ...$var9e]; // this statement must trigger error
testUnpacking(...$var9e);       // this statement must trigger error

// --- callable value ---------------------------------------------------------
$var10a = returnCallable();
$var10b = [10,20,30, ...$var10a]; // this statement must trigger error
testUnpacking(...$var10a);        // this statement must trigger error

$var10c = $myInst->propCallable;
$var10d = [10,20,30, ...$var10c]; // this statement must trigger error
testUnpacking(...$var10c);        // this statement must trigger error

// --- closure value ----------------------------------------------------------
$var11a = new Test47;
$var11b = [10,20,30, ...$var11a]; // OK
testUnpacking(...$var11a);        // OK

$var11c = returnTraversable();
$var11d = [10,20,30, ...$var11c]; // OK
testUnpacking(...$var11c);        // OK

$var11e = $myInst->propTraversable;
$var11f = [10,20,30, ...$var11e]; // OK
testUnpacking(...$var11e);        // OK

// ----------------------------------------------------------------------------

function test(
    array       $argArray,
    null        $argNull,
    int         $argInt,
    float       $argFloat,
    bool        $argBool,
    string      $argString,
    object      $argObject,
    closure     $argClosure,
    callable    $argCallable,
    Traversable $propTraversable,
    ) {
        $var1 = [10,20,30, ...$argArray];    // OK
        testUnpacking(...$argArray);         // OK

        $var2 = [10,20,30, ...$argNull];     // this statement must trigger error
        testUnpacking(...$argNull);          // this statement must trigger error

        $var3 = [10,20,30, ...$argInt];      // this statement must trigger error
        testUnpacking(...$argInt);           // this statement must trigger error

        $var4 = [10,20,30, ...$argFloat];    // this statement must trigger error
        testUnpacking(...$argFloat);         // this statement must trigger error

        $var5 = [10,20,30, ...$argBool];     // this statement must trigger error
        testUnpacking(...$argBool);          // this statement must trigger error

        $var6 = [10,20,30, ...$argString];   // this statement must trigger error
        testUnpacking(...$argString);        // this statement must trigger error

        $var7 = [10,20,30, ...$argObject];   // this statement must trigger error
        testUnpacking(...$argObject);        // this statement must trigger error

        $var8 = [10,20,30, ...$argClosure];  // this statement must trigger error
        testUnpacking(...$argClosure);       // this statement must trigger error

        $var9 = [10,20,30, ...$argCallable]; // this statement must trigger error
        testUnpacking(...$argCallable);      // this statement must trigger error

        $var10 = [10,20,30, ...$propTraversable]; // OK
        testUnpacking(...$propTraversable);       // OK

        var_dump($var1, $var2, $var3, $var4, $var5, $var6, $var7, $var8, $var9, $var10);
}

var_dump($var1a, $var1b, $var1c, $var1d, $var1e, $var1f);
var_dump($var2a, $var2b, $var2c, $var2d, $var2e, $var2f);
var_dump($var3b);
var_dump($var4a,  $var4b,  $var4c,  $var4d,  $var4e,  $var4f);
var_dump($var5a,  $var5b,  $var5c,  $var5d,  $var5e,  $var5f);
var_dump($var6a,  $var6b,  $var6c,  $var6d,  $var6e,  $var6f);
var_dump($var7a,  $var7b,  $var7c,  $var7d,  $var7e,  $var7f);
var_dump($var8a,  $var8b,  $var8c,  $var8d,  $var8e,  $var8f);
var_dump($var9a,  $var9b,  $var9c,  $var9d,  $var9e,  $var9f);
var_dump($var10a, $var10b, $var10c, $var10d);
var_dump($var11a, $var11b, $var11c, $var11d, $var11e, $var11f);