Thread overview
I know how to fix interactions templates now
Oct 01
jmh530
October 01
It just came to me.
I know how to fix the user-visible problems of templates now.
How to make them debuggable.
Sadly this only benefits the programmer and not the compiler, since the compilers problems come from static polymorphism mostly.

But for the usage of templates we can fix the soup of if constraints and trying to find which overload should have been picked.

I must have been blind.
Shame about there not being a compiler speedup potential in it.

But at least I can now have hope  of being able to debug template based code in the future.
This time however there won't be sneak previews.

I won't make the same mistake twice.

Cheers,

Stefan
October 01
On Thursday, 1 October 2020 at 03:27:45 UTC, Stefan Koch wrote:
> It just came to me.
> I know how to fix the user-visible problems of templates now.
> How to make them debuggable.
> Sadly this only benefits the programmer and not the compiler, since the compilers problems come from static polymorphism mostly.
>
> But for the usage of templates we can fix the soup of if constraints and trying to find which overload should have been picked.
>
> I must have been blind.
> Shame about there not being a compiler speedup potential in it.
>
> But at least I can now have hope  of being able to debug template based code in the future.
> This time however there won't be sneak previews.
>
> I won't make the same mistake twice.
>
> Cheers,
>
> Stefan

Actually.
I just realized I don't care about implementing this at all.
And the idea isn't all that revolutionary ...
So I might as well flesh it out here.

The reason why templates are so bad at being composable, is because template constraints don't compose.

when a template T with constraints(C) yields an valid instance, that proofs the constraints hold.
which implies that for anything using an instance of T the constraints C also hold.

When we compose functions our constraints are coupled to types.
Because templates themselves are (or can be) untyped in both Parameters and "return value".
We can't use those to carry the constraints forward.

Leading us into a case where we have to repeat the same constraints over and over again.

That means all we need to do, is to group constraints (I believe this is what C++ calls concepts? I am not sure about this, perhaps Andrei or Atila could clarify)

I can imagine a nice implementation of this, but since it doesn't solve the performance problem, I am not interested.

I guess a fully polymorphic version of type functions, which is by then an implementation first class types, would fix that.

But again polymorphism is exactly what I want to avoid.

Because once things are polymorphic how do you predict the shape?

October 01
On Thursday, 1 October 2020 at 05:23:51 UTC, Stefan Koch wrote:
> The reason why templates are so bad at being composable, is because template constraints don't compose.
>
> when a template T with constraints(C) yields an valid instance, that proofs the constraints hold.
> which implies that for anything using an instance of T the constraints C also hold.
>
> When we compose functions our constraints are coupled to types.
> Because templates themselves are (or can be) untyped in both Parameters and "return value".
> We can't use those to carry the constraints forward.
>
> Leading us into a case where we have to repeat the same constraints over and over again.
>
Yep.

Right now, constraints are carried forward invisibly through gagged template instantiation via __traits(compiles). Miscompilation *itself* becomes the propagated constraint failure, which is of course horrible.

This is why I want __traits(canInstantiate), so we can at least *enforce* that constraints are manually carried forward by the programmer. If a template passes its constraints, it should also pass semantic2/3 in full. It should never be necessary to gag errors after the constraints.

Body SFINAE is cancer.
October 01
On Thursday, 1 October 2020 at 05:23:51 UTC, Stefan Koch wrote:
> [snip]
>
>
> I can imagine a nice implementation of this, but since it doesn't solve the performance problem, I am not interested.
> [snip]

It's a little unclear to me what you are talking about, but my understanding is that a big interest in stuff like Concepts is about improving error messages, rather than performance per se.
October 01
On Thu, Oct 01, 2020 at 07:39:04AM +0000, FeepingCreature via Digitalmars-d wrote: [...]
> Right now, constraints are carried forward invisibly through gagged template instantiation via __traits(compiles). Miscompilation *itself* becomes the propagated constraint failure, which is of course horrible.
> 
> This is why I want __traits(canInstantiate), so we can at least *enforce* that constraints are manually carried forward by the programmer. If a template passes its constraints, it should also pass semantic2/3 in full. It should never be necessary to gag errors after the constraints.
> 
> Body SFINAE is cancer.

This.  I've spent who knows how many hours trying to decipher template errors precisely because a single misspelled identifier in the wrong place can completely change the chain of template instantiations, leading to a completely unrelated failure in a completely unrelated part of the code, with the original real error gagged so there is almost no clue is to what the problem really is.

I wish there were a better mechanism of deferring to a different template besides all-out error gagging regardless of the nature of the error.  It's one thing to try a different overload when sig constraints fail; it's a whole 'nother can o' worms when sig constraints pass but a typo causes the body to fail.  The worst is when this was triggered from within another function's sig constraints -- then you really have almost no way to trace the source of the error.


T

-- 
There is no gravity. The earth sucks.