Page MenuHomePhabricator

Add Assert::UnreachableException
Closed, ResolvedPublic

Description

After T226266: Create a phan plugin to handle the Assert library landed in wikimedia/assert 0.5.0, we got all sorts of new false positives in the Parsoid code base, where we use code like:

switch($c) {
case 1: ....;
case 2: ....;
default:
    Assert::invariant(false, "Should never happen!");
}

to indicate unreachable code paths.

After we upgrade to wikimedia/assert 0.5.0 each one of these triggers:

src/Utils/PHPUtils.php:227 PhanImpossibleCondition Impossible attempt to cast false of type false to truthy

Yeah, that's the point!

Perhaps we need a new Assert::unreachable('should never happen') type call.

EDIT: New recommendation is for this to be written as throw new UnreachableException("should never happen") with UnreachableException defined in the wikimedia\assert package.

See T240141: Phan should handle always-throw-function like ApiBase::dieWithError better as well.

Event Timeline

Change 572331 had a related patch set uploaded (by C. Scott Ananian; owner: Jforrester):
[mediawiki/services/parsoid@master] Increase wikimedia/assert dependency to 0.5.0

https://gerrit.wikimedia.org/r/572331

Why not just throw a LogicException? I'm not a fan of assertions used like that, as they're exactly the same as throwing an exception, but more complicated... Also, note that an eventual Assert::unreachable couldn't be annotated as "always-throw" (T240141).

Change 572331 merged by jenkins-bot:
[mediawiki/services/parsoid@master] Increase wikimedia/assert dependency to 0.5.0

https://gerrit.wikimedia.org/r/572331

Change 577595 had a related patch set uploaded (by C. Scott Ananian; owner: C. Scott Ananian):
[mediawiki/libs/Assert@master] Add Assert::unreachable() to indicate impossible code paths

https://gerrit.wikimedia.org/r/577595

Why not just throw a LogicException? I'm not a fan of assertions used like that, as they're exactly the same as throwing an exception, but more complicated... Also, note that an eventual Assert::unreachable couldn't be annotated as "always-throw" (T240141).

I think you mean "could be annotated"? And that's exactly what this method is for. It's just like "dieWithError", but with a different connotation to the reader and without being tied to mediawiki internals. See further discussion on the patch.

Why not just throw a LogicException? I'm not a fan of assertions used like that, as they're exactly the same as throwing an exception, but more complicated... Also, note that an eventual Assert::unreachable couldn't be annotated as "always-throw" (T240141).

I think you mean "could be annotated"?

No, I really meant it could *not*: phan doesn't support that kind of annotations; dieWithError is a constant source of false positives. But I see this was already discussed on gerrit, with plenty of links.

See further discussion on the patch.

Well, I partly agree with Thiemo, although mine is not a strong position. Having just throw new LogicException( 'reason' ) doesn't seem to bad. It also cannot be compared to other Assert methods, which perform some checks before eventually throwing.

LGoto triaged this task as Low priority.Mar 13 2020, 4:12 PM
LGoto moved this task from Needs Triage to Tech Debt / Big changes on the Parsoid board.
cscott renamed this task from Add Assert::unreachable with appropriate phan annotations to Add Assert::UnreachableException.Mar 16 2020, 10:05 PM
cscott updated the task description. (Show Details)

Change 577595 merged by jenkins-bot:
[mediawiki/libs/Assert@master] Add UnreachableException to indicate impossible code paths

https://gerrit.wikimedia.org/r/577595

cscott claimed this task.

Change 592663 had a related patch set uploaded (by Subramanya Sastry; owner: Subramanya Sastry):
[mediawiki/vendor@master] Bump Parsoid to 0.12.0-a11

https://gerrit.wikimedia.org/r/592663

Change 592663 merged by jenkins-bot:
[mediawiki/vendor@master] Bump Parsoid to 0.12.0-a11

https://gerrit.wikimedia.org/r/592663