private function inferTypeForParameter(AbstractFunction $function, Parameter $param)
 {
     $builder = new UnionTypeBuilder($this->typeRegistry);
     $index = $param->getIndex();
     foreach ($function->getInCallSites() as $site) {
         $args = $site->getArgs();
         if (!isset($args[$index])) {
             continue;
         }
         $builder->addAlternate($args[$index]->getPhpType());
     }
     $newType = $builder->build();
     if (!$newType->isNoType() && !$newType->isUnknownType()) {
         $param->setPhpType($newType);
     }
 }
 private function inferTypesForParameter(Parameter $param, AbstractFunction $function, Clazz $clazz = null)
 {
     if (($type = $param->getPhpType()) && !$type->isUnknownType() && !$type->isNullType() && !$type->isFalse() && !$type->isAllType()) {
         return;
     }
     $allowsNull = $type && $type->isNullType();
     if (null !== ($node = $param->getAstNode())) {
         $type = $this->parser->getTypeFromParamAnnotation($node, $param->getName());
         // Check whether we can use the type of a overridden method.
         // We only do this if we find a parent method that has been defined
         // on an interface (I), or if we find an abstract method (II).
         if (null === $type && $function instanceof Method && null !== $clazz) {
             foreach ($this->findOverriddenMethodsForDocInheritance($function->getName(), $clazz) as $parentMethod) {
                 if (null !== ($docType = $parentMethod->getParamDocType($param->getIndex()))) {
                     $type = $this->parser->getType($docType);
                     break;
                 }
             }
         }
     }
     if (null === $type) {
         $type = $this->registry->getNativeType('unknown');
     } else {
         if ($allowsNull) {
             $type = $this->registry->createNullableType($type);
         }
     }
     $param->setPhpType($type);
     if ($node) {
         $node->setAttribute('type', $type);
     }
 }