Skip to content

Variable type is discarded after use as by-reference arg #1953

@muglug

Description

@muglug
function foo(string &$s) : void {
  $i = "goodbye";
}

$a = "hello";
foo($a);
echo $a->bar();

Expected: Cannot call method bar() on string.
Actual: No issue
https://phpstan.org/r/dc07834e-c39e-4ad4-8034-91c22c38cdda

Suggestion: assume the type does not change inside the called function, and add checks when it does e.g.

function foo(string &$s) : void {
  $s = 5;
}

would result in

Variable $s is limited to values of type string because it is passed by reference, int found

To work around this, the developer would add a @param-out annotation

/**
 * @param-out int $s
 */
function foo(string &$s) : void {
  $s = 5;
}

Implementation

At every return statement (including the implicit return at the bottom) the current param types would be checked against the expected byref param types, taking into account any @param-out overrides.

So this would be a bug:

/**
 * @param-out int $s
 */
function foo(string &$s) : void {
  if (rand(0, 1)) {
    return;
  }
  $s = 5;
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions