Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type condition lost when intermediary variable is used (PhanUndeclaredMethod) #4854

Open
Krinkle opened this issue May 2, 2024 · 0 comments

Comments

@Krinkle
Copy link

Krinkle commented May 2, 2024

  • Phan 5.4.3
  • php-ast version 1.1.1
  • PHP version used to run Phan: 8.2.14

Minimal test case

Phan demo.

<?php
// @phan-file-suppress PhanUnusedPublicNoOverrideMethodParameter
// @phan-file-suppress PhanUnreferencedPublicMethod
abstract class IThing {}
class Foo extends IThing {
    public function compare($x): bool {
        return true;
    }
}
class Bar extends IThing {
    public function compare($x): bool {
        return false;
    }
}
class Quux extends IThing {
    public function nah($x): bool {
        return true;
    }
}
function compare1(IThing $a, IThing $b): bool {
    if ($a instanceof Foo || $a instanceof Bar) {
        return $a->compare($b);
    }
    return false;
}
function compare2(IThing $a, IThing $b): bool {
    $aHasCompare = ($a instanceof Foo || $a instanceof Bar);
    if ($aHasCompare) {
        return $a->compare($b);
    }
    return false;
}
compare1(new Foo, new Bar);
compare1(new Quux, new Bar);
compare2(new Foo, new Bar);
compare2(new Quux, new Bar);
input:29: PhanUndeclaredMethod Call to undeclared method \IThing::compare

Destilled from downstream example: https://gerrit.wikimedia.org/r/c/mediawiki/libs/less.php/+/1026533

$aHasCompare = ( $a instanceof Less_Tree_Anonymous || $a instanceof Less_Tree_Color
	|| $a instanceof Less_Tree_Dimension || $a instanceof Less_Tree_Keyword
	|| $a instanceof Less_Tree_Quoted || $a instanceof Less_Tree_Unit
);
$bHasCompare = ( $b instanceof Less_Tree_Anonymous || $b instanceof Less_Tree_Color
	|| $b instanceof Less_Tree_Dimension || $b instanceof Less_Tree_Keyword
	|| $b instanceof Less_Tree_Quoted || $b instanceof Less_Tree_Unit
);
if ( $aHasCompare &&
	!( $b instanceof Less_Tree_Quoted || $b instanceof Less_Tree_Anonymous )
) {
	// @phan-suppress-next-line PhanUndeclaredMethod
	return $a->compare( $b );
} elseif ( $bHasCompare ) {
	$res = $b->compare( $a );
	return $res !== null ? -$res : null;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant