March 14, 2013
On Thu, 14 Mar 2013 15:57:59 -0700
"H. S. Teoh" <hsteoh@quickfur.ath.cx> wrote:
> 
> In fact, now that I think of it, templates in general suffer from this problem: when you write template X(T) { ... }, pretty much anything goes in the template body, even outright ridiculous things that won't compile for *any* template arguments. But more commonly, the template body may assume things about T that don't apply across all types T. You may assume that T is mutable, or that T has a certain member, etc..
> 
> What if templates were modified so that assumptions about T have to be stated up front? We don't necessarily have to introduce typeclasses as a separate thing, but we could have the compiler reject template bodies that try to access internals of T that aren't stated up front. E.g.:
> 

C#'s generics work that way. I always liked that. The only problem is
that MS never bothered to provide a constraint for "can do
arithmetic" (like they have for "can be compared", ie
IComparable) so you can't do a basic thing like "a + b" generically.

March 14, 2013
On Thu, 14 Mar 2013 17:54:52 -0400
Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>
> it's not like we claim to support input ranges and
> then call .save against them.

Although this is getting OT, we do kind of do that in a way:

It's very common for a range to be a struct rather than a class. In fact, std.range/algorithm has generally been considered to work better with struct ranges with class ranges being a secondary thought.

And yet, due the the nature of structs, all it takes to effectively ".save" an InputRange (or at least attempt to) is this:

struct MyInputRange {...}
void foo(R)(R r) if(isInputRange!R) {
    auto s = r;
}
...
foo(MyInputRange());

That implicitly does the equivalent of ".save" on a mere InputRange *twice*. The result, of course, is completely dependent on the input range in question.

March 15, 2013
On Thursday, 14 March 2013 at 23:52:59 UTC, Nick Sabalausky wrote:
> On Thu, 14 Mar 2013 17:54:52 -0400
> Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>
>> it's not like we claim to support input ranges and
>> then call .save against them.
>
> Although this is getting OT, we do kind of do that in a way:
>
> It's very common for a range to be a struct rather than a class. In
> fact, std.range/algorithm has generally been considered to work
> better with struct ranges with class ranges being a secondary thought.
>
> And yet, due the the nature of structs, all it takes to effectively
> ".save" an InputRange (or at least attempt to) is this:
>
> struct MyInputRange {...}
> void foo(R)(R r) if(isInputRange!R) {
>     auto s = r;
> }
> ...
> foo(MyInputRange());
>
> That implicitly does the equivalent of ".save" on a mere InputRange
> *twice*. The result, of course, is completely dependent on the input
> range in question.

Passing range by value is completely undefined, which is IMO a big weak spot of ranges.
March 15, 2013
On Thursday, 14 March 2013 at 17:53:42 UTC, Andrei Alexandrescu wrote:
> On 3/14/13 1:37 PM, deadalnix wrote:
>> On Thursday, 14 March 2013 at 17:07:16 UTC, Andrei Alexandrescu wrote:
>>> Very simple. Traditionally there's two crucial epochs known as
>>> compilation time and run time. (There's some minor distinctions like
>>> link time etc.) The whole notion of concepts and other type systems
>>> for templates is predicated on three crucial epochs: library
>>> compilation time, library user compilation time, and run time. The
>>> logic goes, someone writes a generic library and wants to distribute
>>> it to users. Users shouldn't ever see bugs caused by e.g. typos in the
>>> library.
>>>
>>
>> I'm not sure if you are thinking I'm really stupid here.
>
> Being wrong doesn't make one stupid.
>

I may be wrong, but certainly not because I don't make the difference between compile time and run time.

> Template constraints are D's solution to that issue. I agree it's not perfect, but I think dollar for dollar it's better than concepts.
>

No they aren't, because it would only skip the top most lines and replace the error by something like impossible to find method blah.

With something like concept, I'd have something like in case of eroneous template :
file:line: Error: concept Blah don't have member blah.

Or in the case of unmatched constraint :
file:line: Error: template Blah except a concept argument of meta-type Foo, Bar given.

And in both cases you can avoid the dreaded wall of error.
March 15, 2013
On 3/14/2013 10:25 PM, deadalnix wrote:
> On Thursday, 14 March 2013 at 17:53:42 UTC, Andrei Alexandrescu wrote:
>> Template constraints are D's solution to that issue. I agree it's not perfect,
>> but I think dollar for dollar it's better than concepts.
>>
>
> No they aren't, because it would only skip the top most lines and replace the
> error by something like impossible to find method blah.
>
> With something like concept, I'd have something like in case of eroneous template :
> file:line: Error: concept Blah don't have member blah.

D also allows you to build custom error messages.

March 15, 2013
15-Mar-2013 01:58, Andrei Alexandrescu пишет:
> On 3/14/13 4:37 PM, Dmitry Olshansky wrote:
>> Point taken. That doesn't detract us from:
>> a) fixing issues with -cov
>
> Yes please (are there bugzilla entries etc)?

template powerup(T) //usable as template mixin too
{
	//imagine more constraints
	static if(size_t.sizeof == 4)
		alias bleh = blah;
	else
		alias bleh = oldBlah;
	//...
}

Now first mixin template don't get counted at all (even code within).
Then declarations are ignored and you'll never know which ones were ever looked at.

>
>> It counts time a LOC is executed. Would nice to add instantations
>> counter (determined at compile time) as well so as to see if
>> declarations are all covered. That + CTFE-only counted as 0.
>
> Not getting this. Example?
>
See above.

>> b) unifying template fuzzy testing in Phobos
>>
>> We have lots of these wheels reinvented across Phobos alone.
>
> Like those dummy ranges in std.algorithm?

Yes. We might as well provide a good hardy set of these as std.testing.mockup or smth like that.

>
>> c) prototyping other higher-level tools to aid debugging generic code
>
> Yeppers!

It seems like a good application for DSL + CTFE. Even if CTFE is too inefficient ATM for large tests a standalone tool could be prototyped with exactly same D code.

Now that I'm saying it I'll probably prototype one just for fun :)

>
>
> Andrei


-- 
Dmitry Olshansky
March 15, 2013
On 3/14/2013 11:36 PM, Dmitry Olshansky wrote:
> 15-Mar-2013 01:58, Andrei Alexandrescu пишет:
>> On 3/14/13 4:37 PM, Dmitry Olshansky wrote:
>>> Point taken. That doesn't detract us from:
>>> a) fixing issues with -cov
>>
>> Yes please (are there bugzilla entries etc)?
>
> template powerup(T) //usable as template mixin too
> {
>      //imagine more constraints
>      static if(size_t.sizeof == 4)
>          alias bleh = blah;
>      else
>          alias bleh = oldBlah;
>      //...
> }
>
> Now first mixin template don't get counted at all (even code within).
> Then declarations are ignored and you'll never know which ones were ever looked at.

-cov only counts executable lines. The above are not executable - I don't see any way to make them work with -cov.

March 15, 2013
15-Mar-2013 10:47, Walter Bright пишет:
> On 3/14/2013 11:36 PM, Dmitry Olshansky wrote:
>> 15-Mar-2013 01:58, Andrei Alexandrescu пишет:
>>> On 3/14/13 4:37 PM, Dmitry Olshansky wrote:
>>>> Point taken. That doesn't detract us from:
>>>> a) fixing issues with -cov
>>>
>>> Yes please (are there bugzilla entries etc)?
>>
>> template powerup(T) //usable as template mixin too
>> {
>>      //imagine more constraints
>>      static if(size_t.sizeof == 4)
>>          alias bleh = blah;
>>      else
>>          alias bleh = oldBlah;
>>      //...
>> }
>>
>> Now first mixin template don't get counted at all (even code within).
>> Then declarations are ignored and you'll never know which ones were
>> ever looked at.
>
> -cov only counts executable lines. The above are not executable - I
> don't see any way to make them work with -cov.
>

The information can be trivially collected during semantic analysis of declarations.

How to merge this compile-time info with run-time one as in -cov is a another question. I'd try outputting some table into object file (special section etc.) and then -cov would use it to mark non-executable code.

-- 
Dmitry Olshansky
March 15, 2013
On 03/15/2013 12:18 AM, monarch_dodra wrote:
> On Thursday, 14 March 2013 at 20:57:57 UTC, Timon Gehr wrote:
>> ...
>>
>> Challenge accepted. Clearly the Phobos developers do not instantiate
>> their templates before shipping them. :o)
>>
>> The following breaks most of std.range, and most of std.algorithm
>> could likely be broken too, but I am too lazy to investigate.
>
> All this breakage is just one and the same bug.
> ...

Even if you count all bugs of the same kind as one bug, there are at least two.


March 15, 2013
On Friday, 15 March 2013 at 06:51:15 UTC, Dmitry Olshansky wrote:
> 15-Mar-2013 10:47, Walter Bright пишет:
>> On 3/14/2013 11:36 PM, Dmitry Olshansky wrote:
>>> 15-Mar-2013 01:58, Andrei Alexandrescu пишет:
>>>> On 3/14/13 4:37 PM, Dmitry Olshansky wrote:
>>>>> Point taken. That doesn't detract us from:
>>>>> a) fixing issues with -cov
>>>>
>>>> Yes please (are there bugzilla entries etc)?
>>>
>>> template powerup(T) //usable as template mixin too
>>> {
>>>     //imagine more constraints
>>>     static if(size_t.sizeof == 4)
>>>         alias bleh = blah;
>>>     else
>>>         alias bleh = oldBlah;
>>>     //...
>>> }
>>>
>>> Now first mixin template don't get counted at all (even code within).
>>> Then declarations are ignored and you'll never know which ones were
>>> ever looked at.
>>
>> -cov only counts executable lines. The above are not executable - I
>> don't see any way to make them work with -cov.
>>
>
> The information can be trivially collected during semantic analysis of declarations.
>
> How to merge this compile-time info with run-time one as in -cov is a another question. I'd try outputting some table into object file (special section etc.) and then -cov would use it to mark non-executable code.

We need to do something like this. Without some kind of "instantiation coverage", it's practically impossible to be confident that your D templates are
correct. Actually I'm not certain that it needs to be the same file as -cov.
I mean, you might want to check that you have 100% template instantiation coverage, before you do your runtime tests.

It can be interesting to know that a line in a function template is instantiated 10 times, and run 3 times, whereas another line is run 857 times, but only instantiated once.