private function traverseCall(\PHPParser_Node $node, LinkedFlowScope $scope)
 {
     assert($node instanceof \PHPParser_Node_Expr_MethodCall || $node instanceof \PHPParser_Node_Expr_FuncCall || $node instanceof \PHPParser_Node_Expr_StaticCall);
     $scope = $this->traverseChildren($node, $scope);
     // Propagate type for constants
     if (NodeUtil::isConstantDefinition($node)) {
         $constantName = $node->args[0]->value->value;
         if ($constant = $this->typeRegistry->getConstant($constantName)) {
             $constant->setPhpType($this->getType($node->args[1]->value));
         }
     }
     // If the assert function is called inside a block node, we are just going to assume
     // that some sort of exception is thrown if the assert fails (and it will not silently
     // be ignored).
     // TODO: This needs to be extracted as a general concept where we can have different
     //       effects for functions/methods. For example, array_pop affects the known item
     //       types of arrays on which it is called.
     if ($node->getAttribute('parent') instanceof BlockNode && NodeUtil::isMaybeFunctionCall($node, 'assert') && isset($node->args[0])) {
         $scope = $this->reverseInterpreter->getPreciserScopeKnowingConditionOutcome($node->args[0]->value, $scope, true);
     }
     $returnType = null;
     if (null !== ($function = $this->typeRegistry->getCalledFunctionByNode($node))) {
         $node->setAttribute('returns_by_ref', $function->isReturnByRef());
         $argValues = $argTypes = array();
         foreach ($node->args as $arg) {
             $argValues[] = $arg->value;
             $argTypes[] = $this->getType($arg);
         }
         if ($function instanceof ContainerMethodInterface) {
             $objType = $function->getContainer();
             $maybeReturnType = $function->getReturnType();
             if (null !== ($restrictedType = $this->methodInterpreter->getPreciserMethodReturnTypeKnowingArguments($function, $argValues, $argTypes))) {
                 $maybeReturnType = $restrictedType;
             }
             $returnType = $this->updateThisReference($node instanceof \PHPParser_Node_Expr_MethodCall ? $node->var : $node->class, $scope->getTypeOfThis(), $objType, $maybeReturnType);
         } else {
             if ($function instanceof GlobalFunction) {
                 if (null !== ($restrictedType = $this->functionInterpreter->getPreciserFunctionReturnTypeKnowingArguments($function, $argValues, $argTypes))) {
                     $returnType = $restrictedType;
                 } else {
                     if (null === $returnType) {
                         $returnType = $function->getReturnType();
                     }
                 }
             } else {
                 throw new \LogicException(sprintf('Unknown function "%s".', get_class($function)));
             }
         }
     }
     $node->setAttribute('type', $returnType ?: $this->typeRegistry->getNativeType('unknown'));
     return $scope;
 }