March 04, 2019
On Monday, 4 March 2019 at 19:03:39 UTC, H. S. Teoh wrote:
> 
>
>  [snip]

Very clear. Good points.
March 04, 2019
On Monday, 4 March 2019 at 15:47:12 UTC, H. S. Teoh wrote:
> This is why I'm starting to think sig constraints are not the genius idea they first appeared to be.

If the implementation actually told you which individual pieces failed (and perhaps even why), I don't think we'd be worried about this.

I have before desired color to be used there: a passing constraint gets highlighted one way, a failing constraint another, and short-circuited constraints get nothing special.

Even without formatting the output, this would very quickly give you a menu of what is and isn't working. And with formatting, it just gets better. (Though I also say I want XML error messages and a dedicated error viewer, so more and less detail is available upon request. But even plain text can give a LOT more actionable info than it does right now.)

Imagine what we'd say if the error message was not:

ooooo.d(4): Error: template std.algorithm.sorting.sort cannot deduce function from argument types !()(FilterResult!(unaryFun, int[])), candidates are:
/home/me/d/dmd2/linux/bin32/../../src/phobos/std/algorithm/sorting.d(1847):
   std.algorithm.sorting.sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r) if ((ss == SwapStrategy.unstable && (hasSwappableElements!Range || hasAssignableElements!Range) || ss != SwapStrategy.unstable &&
asAssignableElements!Range) && isRandomAccessRange!Range && hasSlicing!Range && hasLength!Range)

but rather



ooooo.d(4): Error: template std.algorithm.sorting.sort cannot deduce function from argument types
   !()(FilterResult!(unaryFun, int[])), candidates are:
/home/me/d/dmd2/linux/bin32/../../src/phobos/std/algorithm/sorting.d(1847):
   std.algorithm.sorting.sort([collapsed])(Range r)
      if (
        // passed
        (ss == SwapStrategy.unstable &&
        // passed
        (hasSwappableElements!Range || hasAssignableElements!Range) ||
         // short-circuited
        ss != SwapStrategy.unstable &&
asAssignableElements!Range)
        // ******* FAILED ***********
        && isRandomAccessRange!Range
        // short-circuited, but would fail
        && hasSlicing!Range && hasLength!Range
      )


That tells you everything you need to know.
March 04, 2019
On Monday, 4 March 2019 at 23:03:28 UTC, Adam D. Ruppe wrote:
> On Monday, 4 March 2019 at 15:47:12 UTC, H. S. Teoh wrote:
>> This is why I'm starting to think sig constraints are not the genius idea they first appeared to be.
>
> If the implementation actually told you which individual pieces failed (and perhaps even why), I don't think we'd be worried about this.

Way ahead of you ;)

https://github.com/dlang/DIPs/pull/131
March 04, 2019
On Mon, Mar 04, 2019 at 11:03:28PM +0000, Adam D. Ruppe via Digitalmars-d wrote:
> On Monday, 4 March 2019 at 15:47:12 UTC, H. S. Teoh wrote:
> > This is why I'm starting to think sig constraints are not the genius idea they first appeared to be.
> 
> If the implementation actually told you which individual pieces failed (and perhaps even why), I don't think we'd be worried about this.
[....]
> Imagine what we'd say if the error message was not:
[...]
> but rather
> 
> 
> 
> ooooo.d(4): Error: template std.algorithm.sorting.sort cannot deduce
> function from argument types
>    !()(FilterResult!(unaryFun, int[])), candidates are:
> /home/me/d/dmd2/linux/bin32/../../src/phobos/std/algorithm/sorting.d(1847):
>    std.algorithm.sorting.sort([collapsed])(Range r)
>       if (
>         // passed
>         (ss == SwapStrategy.unstable &&
>         // passed
>         (hasSwappableElements!Range || hasAssignableElements!Range) ||
>          // short-circuited
>         ss != SwapStrategy.unstable &&
> asAssignableElements!Range)
>         // ******* FAILED ***********
>         && isRandomAccessRange!Range
>         // short-circuited, but would fail
>         && hasSlicing!Range && hasLength!Range
>       )
> 
> 
> That tells you everything you need to know.

Yes, this is indeed a big improvement over what we currently have.  It may not be perfect, but it goes a long way from where we are right now. Also, it should be relatively straightforward to implement, and doesn't break any existing code, etc..

Where's the PR for this??? I want it NAO! :-D


T

-- 
A mathematician is a device for turning coffee into theorems. -- P. Erdos
March 04, 2019
On Monday, 4 March 2019 at 23:46:55 UTC, Nicholas Wilson wrote:
> https://github.com/dlang/DIPs/pull/131

Seems overkill to me, though it might be useful in some cases, the compiler already has enough information in current code. It just isn't telling us what it knows.

(that said i prolly wouldn't vote against it, i also don't see a need to change code to improve error messages.)
March 04, 2019
On Mon, Mar 04, 2019 at 11:54:34PM +0000, Adam D. Ruppe via Digitalmars-d wrote:
> On Monday, 4 March 2019 at 23:46:55 UTC, Nicholas Wilson wrote:
> > https://github.com/dlang/DIPs/pull/131
> 
> Seems overkill to me, though it might be useful in some cases, the compiler already has enough information in current code. It just isn't telling us what it knows.
> 
> (that said i prolly wouldn't vote against it, i also don't see a need to change code to improve error messages.)

Yeah, I think the DIP would be a welcome improvement, but OTOH Adam's idea already works without needing to change existing code, because the compiler already knows what it knows.

Given that programmers tend to be lazy (why spend the time writing elaborate sig constraints when I could be working on the function body where the real work is done), having the compiler able to emit useful information *without help from the programmer* is a big plus.

An even bigger plus is that it can be done today with just a little change in the compiler.


T

-- 
Amateurs built the Ark; professionals built the Titanic.
March 05, 2019
On Tuesday, 5 March 2019 at 00:03:39 UTC, H. S. Teoh wrote:
> On Mon, Mar 04, 2019 at 11:54:34PM +0000, Adam D. Ruppe via Digitalmars-d wrote:
>> On Monday, 4 March 2019 at 23:46:55 UTC, Nicholas Wilson wrote:
>> > https://github.com/dlang/DIPs/pull/131
>> 
>> Seems overkill to me, though it might be useful in some cases, the compiler already has enough information in current code. It just isn't telling us what it knows.
>> 
>> (that said i prolly wouldn't vote against it, i also don't see a need to change code to improve error messages.)
>
> Yeah, I think the DIP would be a welcome improvement, but OTOH Adam's idea already works without needing to change existing code, because the compiler already knows what it knows.

You still need to change the compiler, which is very hard because ...

> Given that programmers tend to be lazy (why spend the time writing elaborate sig constraints when I could be working on the function body where the real work is done), having the compiler able to emit useful information *without help from the programmer* is a big plus.
>
> An even bigger plus is that it can be done today with just a little change in the compiler.

... the problem (from the perspective of issuing a nice error) is that you can arbitrarily compose logic which makes sorting the what from the chaff extremely difficult and that signal to noise is very important (ever used -verrors=spec ?). Believe me I tried, saw a suggestion by aliak in a Phobos PR thread and thought that would make things so much easier, and thus arose that DIP.

The DIP also allows you to give a message if a particular subcontract failed. IMO they are much easier to look at (no need to match parens and keep track of && and ||'s .

March 04, 2019
On 3/4/2019 9:19 AM, H. S. Teoh wrote:
> No, I think the original reasoning was that allowing arbitrary boolean
> clauses in sig constraints is more expressive than allowing only a
> subset of expressions (e.g., implementsTrait!T).

That's correct. For example, you could have a constraint that required an odd integer.

Use of `static if` and `pragma(msg)` can be used to generate custom error messages:

    static if (!isInputRange(r)) pragma(msg, r, " must be an Input Range");

This is ultimately far more powerful than anything the compiler can come up with, because it can be about the user's context, not the compiler's.
March 04, 2019
On Tue, Mar 05, 2019 at 12:44:25AM +0000, Nicholas Wilson via Digitalmars-d wrote:
> On Tuesday, 5 March 2019 at 00:03:39 UTC, H. S. Teoh wrote:
[...]
> > Given that programmers tend to be lazy (why spend the time writing elaborate sig constraints when I could be working on the function body where the real work is done), having the compiler able to emit useful information *without help from the programmer* is a big plus.
> > 
> > An even bigger plus is that it can be done today with just a little change in the compiler.
> 
> ... the problem (from the perspective of issuing a nice error) is that you can arbitrarily compose logic which makes sorting the what from the chaff extremely difficult and that signal to noise is very important (ever used -verrors=spec ?). Believe me I tried, saw a suggestion by aliak in a Phobos PR thread and thought that would make things so much easier, and thus arose that DIP.

Well, if you're looking for a perfect solution, then yes this will be very complicated and hairy to implement.

But to take care of the most common case, all we have to do is to assume that sig constraints are of the form (A && B && C && ...).  The compiler only needs to report which of these top level conjuncts failed.  If a sig constraint isn't of this form, then fallback to reporting the entire constraint as failed, i.e., treat it as the case (A) (single-argument conjunction).

It's not a perfect solution, but having this is already a lot better than the current pessimal state of things.  Your DIP represents an improvement over this most basic step, but IMO we should at least have this basic step first.  Don't let the perfect become the enemy of the good yet again.


T

-- 
Amateurs built the Ark; professionals built the Titanic.
March 05, 2019
On Tuesday, 5 March 2019 at 01:07:08 UTC, Walter Bright wrote:
> Use of `static if` and `pragma(msg)` can be used to generate custom error messages:
>
>     static if (!isInputRange(r)) pragma(msg, r, " must be an Input Range");

That doesn't work if you need to overload against it because then you will cause a matches multiple template error.

> This is ultimately far more powerful than anything the compiler can come up with, because it can be about the user's context, not the compiler's.

That power and flexibility does however severely limit the compiler's ability to provide sensible error messages, 99.9% of constraints are in CNF because thats the only  reasonable way to compose and perform overload specialisation.

The DIP covers all the cases.