Skip to content

Conversation

@b1rdex
Copy link
Contributor

@b1rdex b1rdex commented Jan 31, 2021

@ondrejmirtes
Copy link
Member

Hi, could you achieve the same behaviour by modifying IsAFunctionTypeSpecifyingExtension instead? The ImpossibleCheckTypeHelper is there to course-correct mainly "weird" information from extensions, so making the fix in IsAFunctionTypeSpecifyingExtension might be a little harder, but much more correct. Thanks.

@b1rdex
Copy link
Contributor Author

b1rdex commented Feb 7, 2021

If I understand IsAFunctionTypeSpecifyingExtension correctly, it's used to set a type of $object var. Should I implement DynamicFunctionReturnTypeExtension also or what?

@ondrejmirtes
Copy link
Member

@b1rdex Nope, just the logic of IsAFunctionTypeSpecifyingExtension needs to be modified, there's a general dynamic return type extension for type-specifying functions.

@b1rdex
Copy link
Contributor Author

b1rdex commented Feb 9, 2021

So I finally learned the thing:

return $this->typeSpecifier->create( $node, new ConstantBooleanType(false), $context );

sets the function return type to false. That's what we need... But it won't generate any error message. How do I test it? I tried

if (is_a(Bar::class, Foo::class)) { dumpType(is_a(Bar::class, Foo::class)); }

and it dumps false w/o any errors reported on max level. Also, looks like the type specifying works only in conditional context – I tried

if ($a = is_a(Bar::class, Foo::class)) { dumpType($a); }

and it dumps true which is impossible.

@staabm
Copy link
Contributor

staabm commented May 13, 2022

@ondrejmirtes I think we can close this one as well then

@staabm
Copy link
Contributor

staabm commented May 13, 2022

If I understand IsAFunctionTypeSpecifyingExtension correctly, it's used to set a type of $object var. Should I implement DynamicFunctionReturnTypeExtension also or what?

So I finally learned the thing:

return $this->typeSpecifier->create(	$node,	new ConstantBooleanType(false),	$context ); 

just posting the anwser here, since I also worked thru this recently:

the cited code is not correct. instead it works like this:

  • the actual type needs to be set like in
    return $this->typeSpecifier->create(
    $node->getArgs()[0]->value,
    $this->isAFunctionTypeSpecifyingHelper->determineType($objectOrClassType, $classType, $allowString, true),
    $context,
    false,
    $scope,
    );
  • the returned type is then combined with the previous type in
    if ($scope !== null) {
    if ($context->true()) {
    $resultType = TypeCombinator::intersect($scope->getType($expr), $type);
    } elseif ($context->false()) {
    $resultType = TypeCombinator::remove($scope->getType($expr), $type);
    }
    }
  • and the combination of the scope-type with the type-specified type is taken into account in
    $isAlways = $this->getHelper()->findSpecifiedType(
    $scope,
    $functionCall,
    );
    if ($isAlways === null) {
    return ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getReturnType();
    }
    return new ConstantBooleanType($isAlways);
@ondrejmirtes
Copy link
Member

Implemented a different way here: #1311

@b1rdex b1rdex deleted the bug4371 branch May 16, 2022 05:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants