Page MenuHomePhabricator

The $description in the Wikimedia\Assert methods should be callable|string
Open, Needs TriagePublic

Description

It's often the case that the message you would *like* to include if an assert were ever to fail is rather costly to construct. In that case it's best to pass a closure which will only construct it if the assert were to fail.

The Wikimedia\Assert class does support doing this now:

	public static function invariant( $condition, $description ) {
		if ( !$condition ) {
			throw new InvariantException( "Invariant failed: $description" );
		}
	}

Since $description is not type checked, the caller can provide anything which will string-ify to the description. For example:

class LazyString {
  private $f;
  public __construct(callable $f) { $this->f = f; }
  public __tostring() { return $this->f(); }
}

Used like:

Assert::invariant($cond, new LazyString(function() use ($bigfoo) { return "Big foo is obviously bad: " . json_encode($bigfoo); }));

At a minimum to sanction this the phpdoc for Assert::invariant (&etc) should say @param string|object $description instead of @param string $description.

But to be even nicer to allow @param string|callable and invoke it. In some other programming languages, if $description is not a string the assertion library will call the equivalent of var_export($description, TRUE) to stringify it (and any other trailing varargs), which lets the common case (where describing some complicated datastructure is too costly to do on every assertion test) look like:

Assert::invariant($cond, "That big complicated datastructure is b0rked!", $bigComplicatedDataStructure);

with, of course, the serialization of $bigComplicatedDataStructure not occurring unless the assertion actually failed.