<?php
$foo = (int) $bar;
$foo = (integer) $bar;
$foo = (bool) $bar;
$foo = (boolean) $bar;
$foo = (float) $bar;
$foo = (double) $bar;
$foo = (real) $bar;
$foo = (string) $bar;
$foo = (array) $bar;
$foo = (object) $bar;
$foo = (unset) $bar;

$foo = (int) $bar;
$foo = (integer) $bar;
$foo = (bool) $bar;
$foo = (string) $bar;
$foo = ( array ) $bar;

function foo(int $a, string $b, bool $c, array $d, Foo\Bar $e) : int {}
function foo(int $a, string $b, bool $c, array $d, Foo\Bar $e) : Foo\Bar {}
function foo(int $a, Bar $b, bool $c, array $d, Foo\Bar $e) : Bar {}
function foo(callable $a, callable $b, self $c, iterable $d, iterable $e) : float {}

$foo = function (int $a, bool $b) {};
$foo = function (int $a, callable $b) :int{};
$foo = function (bool $a, float $b) use ($foo) : int {};
$foo = function (Foo $a, Foo\Bar $b) use ($foo) : \Foo\Bar {};
$foo = function (bool $a, callable $b) use ($foo) : Bar {};

class Testing {
    public function TestThis(self $a, object $b, parent $c) : void {}
}

function foo(
    ?float $a,
    ? string $b,
    ?iterable $c,
    ?	object $d,
    ?Foo\Bar $e
) : ?Foo\Bar {}

$foo = function (?int $a, ?    callable $b)
    :?int{};

$var = (binary) $string;
$var = (binary)$string;

function unionParamTypesA (bool|array| /* nullability operator not allowed in union */ null $var) {}

function unionParamTypesB (\Package\ClassName | int | \Package\Other_Class | false $var) {}

function unionReturnTypesA ($var): bool|array| /* nullability operator not allowed in union */ null {}

function unionReturnTypesB ($var): \Package\ClassName | int | \Package\Other_Class | false {}

class TypedProperties
{
    protected ClassName $class;
    public int $int;
    private ?bool $bool;
    public self $self;
    protected parent $parent;
    private array $array;
    public float $float;
    protected ?string $string;
    private iterable $iterable;
    public object $object;
    protected mixed $mixed;

    public iterable|false|null $unionTypeA;
    protected self|parent /* comment */ |\Fully\Qualified\ClassName|UnQualifiedClass $unionTypeB;
    private ClassName|/*comment*/float|string|false $unionTypeC;
    public string | array | false $unionTypeD;
}

class ConstructorPropertyPromotionWithTypes {
    public function __construct(protected float|int $x, public ?string &$y = 'test', private mixed $z) {}
}

class ConstructorPropertyPromotionAndNormalParams {
    public function __construct(public int $promotedProp, ?int $normalArg) {}
}

function (): never {
    exit;
};

function intersectionParamTypes (\Package\ClassName&\Package\Other_Class $var) {}

function intersectionReturnTypes ($var): \Package\ClassName&\Package\Other_Class {}
