On the subject of error messages

Stanislav Blinov via Digitalmars-d digitalmars-d at puremagic.com
Tue May 16 06:54:56 PDT 2017


On Tuesday, 16 May 2017 at 12:27:30 UTC, Steven Schveighoffer 
wrote:

>> When we have tests using dummy lambdas, are we to expect users 
>> to
>> immediately extract the lambda body, parse it, and figure out 
>> what's wrong?
>
> This is what you have to do today. The task has already been 
> tried by the compiler, and the result is known by the compiler. 
> Just have the compiler tell you.

:) The compiler does not know what I'm checking for with that 
lambda. As far as the compiler is concerned, I'm interested in 
whether it compiles or not. It doesn't care what that means in 
the context of my constraint. Neither should the user.

> The compiler, and by extension your hand-written error 
> checking, cannot know the true intention of the user.

The constraint *is* hand-written error checking. What I'm talking 
about is hand-written human-readable error messages :) It's not 
about knowing user intentions, it's about informing them why they 
made a mistake.

> All it knows is you tried to do something that isn't supported. 
> You have to figure out what is wrong and fix it. If that takes 
> several iterations, that's what it takes. There is no solution 
> that will give you all the answers.

Hold on a second, I think there's a mixup in terminology here. A 
user (caller) of move() is not supposed to be interested in what 
particular evaluation chain caused the constraint to be false. I, 
as an author, declare a contract (constraint). I am not 
interested in user's intentions. I am interested that I'm being 
called correctly. When the user violates the contract, I must 
inform them they did so, by reporting *why* their argument does 
not satisfy me. Not by telling *how* I figured that out (compiler 
output), but by telling *what* is wrong with the argument 
(human-readable error message).

If the user does want to know how the constraint caught their 
mistake, they're free to inspect what the compiler outputs.

That is why (static) asserts have an optional string argument: to 
display a clean an readable error message, instead of just 
dumping some code on the user. The same thing, in my opinion, is 
needed for constraints.

> In your example, the compiler would point at isMovable!S as the 
> issue. Not super-informative, but is all it gives to prevent 
> huge outputs. Then you tell it to print more information, and 
> it would say that false was returned when the m member of type 
> T is being checked, at which point you could get a stack trace 
> of what values were at each level of recursion. Everywhere a 
> boolean evaluated to true in order to get to the point where 
> false is returned would be colored green, every time it was 
> false, it would be colored red, and every time a short circuit 
> happened, it wouldn't be colored.

Or the user could just read a string "This overload cannot be 
called, because argument 1 (struct S) has a destructor and 
non-statically initialized const members". No "then", no printing 
more information, no stack traces. User is informed their type is 
wrong and *why* it is wrong. If they disagree, if they think 
there's a bug in the constraint, or if they're interested in how 
the constraint works, they're free to go through all the hoops 
you describe.

> We can't hand-hold everyone. At some point you have to learn 
> programming and debugging :)

It's not about hand-holding. If I call a function from a foreign 
API, and the call does not compile, I'd want to know why it 
didn't compile, not what the author of the API did to make it not 
compile. I'd want to know what *I* must do to make it compile. 
Preferably without dissecting the API in order to find that out.


More information about the Digitalmars-d mailing list