Skip to content

[ Typechecker ] Typechecker forgets to analyze the second iteration of a loop that is inside a loop #9852

Description

@lexidor

Describe the bug
When inside the inner loop, the later assignment to $previous is ignored.

Standalone code, or other way to reproduce the problem

use namespace HH\Lib\{PseudoRandom, Vec};

<<__EntryPoint>>
function repro()[defaults]: void {
  $indeterminate_loop = Vec\fill(PseudoRandom\int(0, 100), true);
  $indeterminate_loop_2 = Vec\fill(PseudoRandom\int(0, 100), true);

  foreach ($indeterminate_loop as $_) {
    $previous = null;

    // On the second iteration of this loop, $previous is `true`.
    foreach ($indeterminate_loop_2 as $_) {
      takes_null($previous);
      $previous = true;
    }
  }
}

function takes_null(null $_)[]: void {}

Steps to reproduce the behavior:

  1. Typecheck with hh_client 2026.06.05
  2. Observe No errors!
  3. Invoke with hhvm
  4. Observe TypeError, bool cannot be passed where null is expected

Expected behavior

When analyzing the inner loop the typechecker should assume the loop can run more than once.

Actual behavior

root@2e29e99892c2:/mnt/project# hh_client 
No errors!
root@2e29e99892c2:/mnt/project# hhvm repro.hack 

Fatal error: Uncaught TypeError: Argument 1 passed to takes_null() must be an instance of null, bool given in /mnt/project/repro.hack:13
Stack trace:
#0 (): repro()
#1 {main}

Environment

  • Operating system

Debian GNU/Linux 13 (trixie)

  • Installation method

docker pull hersheltheodorelayton/hhvm-full:26.06.05

  • HHVM Version
HipHop VM 26.6.5 (rel) (non-lowptr)
Compiler: heads/hhvm-oss-20260605-vec-slice-0-gb983bd51b1256cd8c3fed53b2eb9970870723e50
Repo schema: 2cfae41f53ce07c231d45e895efa412f7abc7be3
hackc-c74a4d6e4f97e2c15841c0fbf374c44811ed4799-26.6.5

Additional context
N/A

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions