digitalmars.D - Help from the compiler when debugging failing template constraints - a
- Atila Neves (54/54) Sep 28 2015 I've mentioned this many times before: template constraints are
- Jack Stouffer (9/11) Sep 28 2015 Absolutely. The tedious hunt down with pragma(msg) needs to go.
- Steven Schveighoffer (4/49) Sep 29 2015 Yes. I also prefer that the compiler do this. I've definitely run into
- Dmitry Olshansky (5/29) Sep 29 2015 Certainly the first one.
- Atila Neves (4/9) Oct 14 2015 Huh, I thought this'd get more interest. I guess I have weird
- Artur Skawina via Digitalmars-d (5/11) Oct 14 2015 No, it's probably just that the people interested in this would
- Atila Neves (13/29) Oct 14 2015 There can't be a "proper" solution without a language change,
- Artur Skawina via Digitalmars-d (24/36) Oct 14 2015 Yes, I'm just pointing out that the lack of discussion is not
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (4/6) Oct 14 2015 I would be intersted in seeing a detailed analysis on the
- deadalnix (3/10) Oct 14 2015 No virtual dispatch, no downcast possible, no dynamic typeid, ...
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (14/26) Oct 14 2015 Does this mean that static inheritance for structs can be done as
- Atila Neves (6/26) Oct 15 2015 All I want from static inheritance is exactly what's made
I've mentioned this many times before: template constraints are like unittest blocks with asserts in D: great that they're built-in easy to use. But when they fail, there's no help in figuring out why. I've had many a debugging session (with pragma(msg) of course, since my bugs were of the compile-time variety and there's no debugger for that) due to failing to satisfy a template constraint that I thought I'd implemented the correct functions for. It'd be nice if the compiler told me why. I did a PR a while back with an idea from Adam's book but it didn't work in the context of Phobos and interfaces. I've come up with a PR (https://github.com/D-Programming-Language/phobos/pull/3677) that will let users type this: models!(MyStruct, isInputRange) struct MyStruct { ... } Or this: struct MyStruct { ... static assert(models!(MyStruct, isInputRange)); } When the template constraint isn't satisfied, the compiler will dutifully tell you why. The only requirement is that there be a checkXXX function for an isXXX template constraint. I've updated the original PR for `isInputRange` to make the above code possible. I chose the name `models` because I just got back from CppCon and concepts might have tainted my brain. It's unfortunate to have to specify the type in the UDA version, but it's what the language as it is now will allow me to do. I created an input range, verified it compiled, then added a 't' to the end of `front`. With `models` I got this for both UDA and static assert versions: /home/atila/coding/d/dlang/phobos/std/range/primitives.d(182): Error: template std.range.primitives.front cannot deduce function from argument types !()(Foo), candidates are: /home/atila/coding/d/dlang/phobos/std/range/primitives.d(2219): std.range.primitives.front(T)(T[] a) if (!isNarrowString!(T[]) && !is(T[] == void[])) /home/atila/coding/d/dlang/phobos/std/range/primitives.d(2247): std.range.primitives.front(T)(T[] a) if (isNarrowString!(T[])) /home/atila/coding/d/dlang/phobos/std/traits.d-mixin-6771(6771): Error: template instance std.range.primitives.checkInputRange!(Foo) error instantiating concepts.d(81): instantiated from here: models!(Foo, isInputRange) Failed: ["dmd", "-unittest", "-main", "-v", "-o-", "concepts.d", "-I."] With `static assert(isInputRange!Foo)`, I get this: concepts.d(87): Error: static assert (isInputRange!(Foo)) is false Failed: ["dmd", "-unittest", "-main", "-v", "-o-", "concepts.d", "-I."] I prefer the first one. How about you? Atila
Sep 28 2015
On Monday, 28 September 2015 at 20:25:21 UTC, Atila Neves wrote:I prefer the first one. How about you? AtilaAbsolutely. The tedious hunt down with pragma(msg) needs to go. One thing your example doesn't show is the next step after the static assert fails: copy all of the asserts from the isWhatEver code an write a pragma(msg) for each of those to find where the problem is. I believe that the error messages should be of the same quality as the error messages when a class doesn't conform to an interface, but this is a good start.
Sep 28 2015
On 9/28/15 4:25 PM, Atila Neves wrote:I've mentioned this many times before: template constraints are like unittest blocks with asserts in D: great that they're built-in easy to use. But when they fail, there's no help in figuring out why. I've had many a debugging session (with pragma(msg) of course, since my bugs were of the compile-time variety and there's no debugger for that) due to failing to satisfy a template constraint that I thought I'd implemented the correct functions for. It'd be nice if the compiler told me why. I did a PR a while back with an idea from Adam's book but it didn't work in the context of Phobos and interfaces. I've come up with a PR (https://github.com/D-Programming-Language/phobos/pull/3677) that will let users type this: models!(MyStruct, isInputRange) struct MyStruct { ... } Or this: struct MyStruct { ... static assert(models!(MyStruct, isInputRange)); } When the template constraint isn't satisfied, the compiler will dutifully tell you why. The only requirement is that there be a checkXXX function for an isXXX template constraint. I've updated the original PR for `isInputRange` to make the above code possible. I chose the name `models` because I just got back from CppCon and concepts might have tainted my brain. It's unfortunate to have to specify the type in the UDA version, but it's what the language as it is now will allow me to do. I created an input range, verified it compiled, then added a 't' to the end of `front`. With `models` I got this for both UDA and static assert versions: /home/atila/coding/d/dlang/phobos/std/range/primitives.d(182): Error: template std.range.primitives.front cannot deduce function from argument types !()(Foo), candidates are: /home/atila/coding/d/dlang/phobos/std/range/primitives.d(2219): std.range.primitives.front(T)(T[] a) if (!isNarrowString!(T[]) && !is(T[] == void[])) /home/atila/coding/d/dlang/phobos/std/range/primitives.d(2247): std.range.primitives.front(T)(T[] a) if (isNarrowString!(T[])) /home/atila/coding/d/dlang/phobos/std/traits.d-mixin-6771(6771): Error: template instance std.range.primitives.checkInputRange!(Foo) error instantiating concepts.d(81): instantiated from here: models!(Foo, isInputRange) Failed: ["dmd", "-unittest", "-main", "-v", "-o-", "concepts.d", "-I."] With `static assert(isInputRange!Foo)`, I get this: concepts.d(87): Error: static assert (isInputRange!(Foo)) is false Failed: ["dmd", "-unittest", "-main", "-v", "-o-", "concepts.d", "-I."] I prefer the first one. How about you?Yes. I also prefer that the compiler do this. I've definitely run into this before: http://forum.dlang.org/post/m4mdsk$bgs$1 digitalmars.com -Steve
Sep 29 2015
On 28-Sep-2015 23:25, Atila Neves wrote:I've mentioned this many times before: template constraints are like unittest blocks with asserts in D: great that they're built-in easy to use. But when they fail, there's no help in figuring out why.[snip]I created an input range, verified it compiled, then added a 't' to the end of `front`. With `models` I got this for both UDA and static assert versions: /home/atila/coding/d/dlang/phobos/std/range/primitives.d(182): Error: template std.range.primitives.front cannot deduce function from argument types !()(Foo), candidates are: /home/atila/coding/d/dlang/phobos/std/range/primitives.d(2219): std.range.primitives.front(T)(T[] a) if (!isNarrowString!(T[]) && !is(T[] == void[])) /home/atila/coding/d/dlang/phobos/std/range/primitives.d(2247): std.range.primitives.front(T)(T[] a) if (isNarrowString!(T[])) /home/atila/coding/d/dlang/phobos/std/traits.d-mixin-6771(6771): Error: template instance std.range.primitives.checkInputRange!(Foo) error instantiating concepts.d(81): instantiated from here: models!(Foo, isInputRange) Failed: ["dmd", "-unittest", "-main", "-v", "-o-", "concepts.d", "-I."] With `static assert(isInputRange!Foo)`, I get this: concepts.d(87): Error: static assert (isInputRange!(Foo)) is false Failed: ["dmd", "-unittest", "-main", "-v", "-o-", "concepts.d", "-I."] I prefer the first one. How about you? AtilaCertainly the first one. -- Dmitry Olshansky
Sep 29 2015
On Monday, 28 September 2015 at 20:25:21 UTC, Atila Neves wrote:I've mentioned this many times before: template constraints are like unittest blocks with asserts in D: great that they're built-in easy to use. But when they fail, there's no help in figuring out why. [...]Huh, I thought this'd get more interest. I guess I have weird priorities! :P Atila
Oct 14 2015
On 10/14/15 10:26, Atila Neves via Digitalmars-d wrote:On Monday, 28 September 2015 at 20:25:21 UTC, Atila Neves wrote:No, it's probably just that the people interested in this would prefer a /proper/ solution, hence don't consider ad hoc hacks to be cost effective, but actually counterproductive. arturI've mentioned this many times before: template constraints are like unittest blocks with asserts in D: great that they're built-in easy to use. But when they fail, there's no help in figuring out why. [...]Huh, I thought this'd get more interest. I guess I have weird priorities! :P
Oct 14 2015
On Wednesday, 14 October 2015 at 12:42:23 UTC, Artur Skawina wrote:On 10/14/15 10:26, Atila Neves via Digitalmars-d wrote:There can't be a "proper" solution without a language change, which is unlikely. Personally, I'd prefer struct MyStruct: static isInputRange { ... } to: models!(MyStruct, isInputRange) struct MyStruct { ... } But the latter is possible today and the former is unlikely to ever get approved. My original plan was to write a DIP for "static inheritance", I changed to this PR because I'm 90% sure the DIP would go nowhere and the PR makes things a lot better. AtilaOn Monday, 28 September 2015 at 20:25:21 UTC, Atila Neves wrote:No, it's probably just that the people interested in this would prefer a /proper/ solution, hence don't consider ad hoc hacks to be cost effective, but actually counterproductive. arturI've mentioned this many times before: template constraints are like unittest blocks with asserts in D: great that they're built-in easy to use. But when they fail, there's no help in figuring out why. [...]Huh, I thought this'd get more interest. I guess I have weird priorities! :P
Oct 14 2015
On 10/14/15 15:32, Atila Neves via Digitalmars-d wrote:On Wednesday, 14 October 2015 at 12:42:23 UTC, Artur Skawina wrote:Yes, I'm just pointing out that the lack of discussion is not necessarily caused by the lack of interest and that the subject is not a low priority one. When a /proper/ solution is available (ie `possible`, even if not `likely`), discussing partial solutions (aka hacks) that have a significant cost will (rightly) be seen as counterproductive. Given the microscopic size of the D community it only takes a few people to reach that conclusion to result in ~zero constructive feedback. IOW it's not a "weird priorities" issue; it's a pragmatic pro-status-quo-choice issue. Another example of this kind would be the ownership/lifetime approach. Of the three options: [A] `ignoring it by-design` (C-like), [B] `dealing with only a subset`, and [C] `handling it properly`, the middle [B] option is the worst one. This leads to very little serious feedback to [B] proposals, and even less to [C] (since it "won't happen"). That doesn't change the reality that the only viable alternatives are either [A] or [C], because [B] has a cost comparable (if not ultimately even higher than) [C], but does not have [C]'s benefit (safety). IOW "feedback amount" can not be used as a proxy for "interest", and there often is no meaningful feedback->result correlation. There are too many other (meta) factors involved. arturOn 10/14/15 10:26, Atila Neves via Digitalmars-d wrote:There can't be a "proper" solution without a language change, which is unlikely.On Monday, 28 September 2015 at 20:25:21 UTC, Atila Neves wrote:No, it's probably just that the people interested in this would prefer a /proper/ solution, hence don't consider ad hoc hacks to be cost effective, but actually counterproductive.I've mentioned this many times before: template constraints are like unittest blocks with asserts in D: great that they're built-in easy to use. But when they fail, there's no help in figuring out why. [...]Huh, I thought this'd get more interest. I guess I have weird priorities! :P
Oct 14 2015
On Wednesday, 14 October 2015 at 13:32:54 UTC, Atila Neves wrote:ever get approved. My original plan was to write a DIP for "static inheritance",I would be intersted in seeing a detailed analysis on the difference between inheritance and "alias this" over the first struct member.
Oct 14 2015
On Wednesday, 14 October 2015 at 20:12:52 UTC, Ola Fosheim Grøstad wrote:On Wednesday, 14 October 2015 at 13:32:54 UTC, Atila Neves wrote:No virtual dispatch, no downcast possible, no dynamic typeid, ...ever get approved. My original plan was to write a DIP for "static inheritance",I would be intersted in seeing a detailed analysis on the difference between inheritance and "alias this" over the first struct member.
Oct 14 2015
On Thursday, 15 October 2015 at 01:08:18 UTC, deadalnix wrote:On Wednesday, 14 October 2015 at 20:12:52 UTC, Ola Fosheim Grøstad wrote:Does this mean that static inheritance for structs can be done as syntax sugar using "alias this" with no semantic changes and get the same semantics as with a class? E.g.: struct MySub : MySuper { } translates into struct MySub { MySuper __super; this(...){ __super.__ctor; ...} ~this(...){ ...; __super.__dtor;} alias __super this; }On Wednesday, 14 October 2015 at 13:32:54 UTC, Atila Neves wrote:No virtual dispatch, no downcast possible, no dynamic typeid, ...ever get approved. My original plan was to write a DIP for "static inheritance",I would be intersted in seeing a detailed analysis on the difference between inheritance and "alias this" over the first struct member.
Oct 14 2015
On Thursday, 15 October 2015 at 06:46:25 UTC, Ola Fosheim Grøstad wrote:On Thursday, 15 October 2015 at 01:08:18 UTC, deadalnix wrote:All I want from static inheritance is exactly what's made possible by the `models` PR. I guess I'll write that DIP after all. AtilaOn Wednesday, 14 October 2015 at 20:12:52 UTC, Ola Fosheim Grøstad wrote:Does this mean that static inheritance for structs can be done as syntax sugar using "alias this" with no semantic changes and get the same semantics as with a class? E.g.: struct MySub : MySuper { } translates into struct MySub { MySuper __super; this(...){ __super.__ctor; ...} ~this(...){ ...; __super.__dtor;} alias __super this; }[...]No virtual dispatch, no downcast possible, no dynamic typeid, ...
Oct 15 2015