DIP83

From D Wiki
Revision as of 17:22, 1 October 2015 by Nordlow (talk | contribs)
Jump to: navigation, search
Title: Configurable Assert Diagnostics
DIP: 83
Version: 1
Status: Draft
Created: 2015-10-01
Last Modified: 2015-10-1
Author: Per Nordlöw
Links:

Abstract

Allow for assert's to do pretty printing of its failing expression when flagged for in call to compiler. Printing is configurable via specific sets of (template) function overloads.

Rationale

Typically added/modified by the developer by changing the D compilation flags (DFLAGS) to calls to rdmd, dub, scons etc upon failure with -unittest for a specific failing module. This will be more convenient than explicitly adding the prints of the left-hand-side expression lhs and righ-hand-side expression rhs of assert expression in the failing unittest.

Description

This DIP proposes to add library-level-configurable diagnostics to failing calls to assert(expr) typically called from within unittest-blocks.

This diagnostics is activated only when DMD is called with a specific command line flag, say -unittest=verbose.

If DMD is called with this flag it will then rewrite assert expression (AssertExpr in dmd source) such as

assert(lhs == rhs)

with

assertBinOp(A_FILE, A_LINE, A_COLUMN, "==")(lhs == rhs, lhs, rhs)

where

assertBinOp(string file, uint line, uint column, string op)(E, L, R)(lazy E expression, lazy L lhs, lazy R rhs)

and similarly for unary expressions.

The default implementation of assertBinOp (preferrably defined somewhere in druntime) would be D code that mimics the current behaviour of assert(expression) by throwing an AssertExpression if cast(bool)expression is false (dont know about the behaviour of nothrow/@nogc discussed above though). The Phobos-developer can then do what he likes with the information he needs in the extra arguments in specific templated overloads of assertBinOp.

This specific behaviour could be extendable by adding (typically templated) overloads of assertBinOp for specific sets of types (concepts).

In this way D would get the extendability we want in testing-frameworks such as std.experimental.unittests without adding a new assert-overload-set and without sacrifycing default memory usage in DMD/Phobos unittests.

Further, this solution enables the possibility to provide fancy diagnostics behaviour in assertBinOp for failing array/range or aggregate (struct or class) comparisons. This diagnostics could also have different pretty printing backends such as HTML.

For example a failing

assert([1,2,3] == [1,2,4]);

could pretty-print

([1,2,3][2] being 3) != ([1,2,4][2] being 4)

or for aggregates a failing

struct A { int x, y; }
auto a = A(1,2);
auto b = A(1,3);
assert(a == b);

could pretty-print

(a.y being 2) != (b.y being 3)

Parts of the solution list at

https://issues.dlang.org/show_bug.cgi?id=5547#c3

including rewriting/expansion of AssertExpr could probably reused.

Impact

Copyright

This document has been placed in the Public Domain.