digitalmars.D - You know how I was saying in my DConf talk...
- Ethan (34/34) Jul 23 2019 ...that I come up across metaprogramming problems that can't be
- JN (9/15) Jul 23 2019 That's how metaprogramming oriented languages are. Every language
- Ethan (5/8) Jul 23 2019 Perhaps you're not familiar with MSVC's template error messages
- Timon Gehr (6/52) Jul 23 2019 This shouldn't happen (the anonymous scope is an implementation detail
- Timon Gehr (4/5) Jul 23 2019 Just noticed that the linked issue conflates both problems. I don't
- Ethan (24/30) Jul 23 2019 The entire point of that code I posted and the bug report I made
- Ethan (4/4) Jul 23 2019 On Wednesday, 24 July 2019 at 01:06:18 UTC, Ethan wrote:
- Ethan (12/17) Jul 23 2019 https://issues.dlang.org/show_bug.cgi?id=20079
- Adam D. Ruppe (5/10) Jul 23 2019 Those are by design and it is a fairly useful design too. The
- Ethan (14/18) Jul 23 2019 https://dlang.org/spec/template-mixin.html
- Adam D. Ruppe (9/11) Jul 23 2019 That page never claims it is a replacement for C macros, and it
- Timon Gehr (21/39) Jul 23 2019 This behavior is by design (for the better or worse, but those are not
- Timon Gehr (2/9) Jul 23 2019 https://github.com/dlang/dmd/pull/10214
- Ethan (2/3) Jul 24 2019 Thank you.
- Timon Gehr (3/9) Jul 24 2019 No problem, sorry for screwing this up in the first place. Does the
- Ethan (3/5) Jul 25 2019 I'll let you know when either I can compile DMD again, or the
- Timon Gehr (7/18) Jul 23 2019 As I am sure you are aware, this practice is called confirming a bug
- Kagamin (13/17) Jul 26 2019 The compiler on run.dlang.org provides plenty of context:
- Ethan (12/24) Jul 26 2019 Simple use cases like my example are not the problem.
- FeepingCreature (5/17) Jul 26 2019 I would like to voice a very enthusiastic recommendation for
- Ethan (66/71) Jul 26 2019 Honestly, hot take/opinion time here. But every time I hear
- FeepingCreature (17/29) Jul 26 2019 Fair enough. When I hit a situation like that, I do take the time
- Kagamin (4/10) Jul 27 2019 Isn't your complaint that the assert is not helpful? If it was
- Ethan (37/40) Jul 27 2019 No, the complaint is that DMD withheld error information in favor
- Kagamin (7/18) Jul 27 2019 Again, in this example the compiler does provide context that
- Ethan (8/12) Jul 27 2019 Your definition of context is incomplete.
- Kagamin (7/7) Jul 27 2019 When a function is compiled in incorrect environment it's likely
- Ethan (8/9) Jul 27 2019 Is that proving my point? I think it is. It appears you implied a
- Bastiaan Veelo (5/7) Jul 27 2019 If continuing is desired, would a `static if` combined with
- Ethan (9/14) Jul 27 2019 I was considering making that point myself. The static assert
- Bastiaan Veelo (23/38) Jul 27 2019 Tossing in a `version` may produce a helpful idiom, if
- John Colvin (7/19) Jul 28 2019 How would you propose changing the compiler such that you got the
...that I come up across metaprogramming problems that can't be easily Googled and making bug reports for is hard? https://issues.dlang.org/show_bug.cgi?id=20072 I tried upgrading to 2.087.0 and got blindsided by an error that looks something like: no property `somevar` for type `some.Type`, did you mean `some.Type.__anonymous.somevar`? Writing some entirely unrelated code earlier using 2.086.1 got a similar error and finally twigged me to the fact that it is actually static foreach problem. This highlights one of the other things I don't like when errors like this happens: D's quality of error messages is still not great. They've most definitely improved since DDMD happened, but they still seem predicated on the idea that people aren't going to be doing a lot of metaprogramming and provide almost no context when you're deep down the meta hole. At least now that I know what the hey is going on, I can actually work at upgrading to 2.087.0 with a workaround, but that legit was going to block me from ever upgrading. live code link: https://run.dlang.io/is/PBKQ80 example code direct: import std.meta : AliasSeq; import std.traits : moduleName; string generateFor( string objectName )() { return "struct " ~ objectName ~ "{ }"; } alias StructNames = AliasSeq!( "StructOne", "StructTwo", "StructThree" ); static foreach( Name; StructNames ) { mixin( generateFor!Name ); } pragma( msg, moduleName!StructOne );
Jul 23 2019
On Tuesday, 23 July 2019 at 18:36:19 UTC, Ethan wrote:This highlights one of the other things I don't like when errors like this happens: D's quality of error messages is still not great. They've most definitely improved since DDMD happened, but they still seem predicated on the idea that people aren't going to be doing a lot of metaprogramming and provide almost no context when you're deep down the meta hole.That's how metaprogramming oriented languages are. Every language that has advanced metaprogramming like C++ or D sooner or later ends up in template spaghetti. Sure, the error messages are nice for simple templates, and performance is nice too, but once you have several generic types and then use them together, good luck, both on errors and compilation speed time. Oh and autocomplete breaks too because most of the code doesn't exist until build time.
Jul 23 2019
On Tuesday, 23 July 2019 at 19:56:44 UTC, JN wrote:That's how metaprogramming oriented languages are. Every language that has advanced metaprogramming like C++ or D sooner or later ends up in template spaghetti.Perhaps you're not familiar with MSVC's template error messages of late? Those things are tight. It's not an unsolvable problem. It's just not a problem that will serve a lot of people right now.
Jul 23 2019
On 23.07.19 20:36, Ethan wrote:...that I come up across metaprogramming problems that can't be easily Googled and making bug reports for is hard? https://issues.dlang.org/show_bug.cgi?id=20072 I tried upgrading to 2.087.0 and got blindsided by an error that looks something like: no property `somevar` for type `some.Type`, did you mean `some.Type.__anonymous.somevar`? Writing some entirely unrelated code earlier using 2.086.1 got a similar error and finally twigged me to the fact that it is actually static foreach problem. This highlights one of the other things I don't like when errors like this happens: D's quality of error messages is still not great. They've most definitely improved since DDMD happened, but they still seem predicated on the idea that people aren't going to be doing a lot of metaprogramming and provide almost no context when you're deep down the meta hole. At least now that I know what the hey is going on, I can actually work at upgrading to 2.087.0 with a workaround, but that legit was going to block me from ever upgrading. live code link: https://run.dlang.io/is/PBKQ80 example code direct: import std.meta : AliasSeq; import std.traits : moduleName; string generateFor( string objectName )() { return "struct " ~ objectName ~ "{ }"; } alias StructNames = AliasSeq!( "StructOne", "StructTwo", "StructThree" ); static foreach( Name; StructNames ) { mixin( generateFor!Name ); } pragma( msg, moduleName!StructOne );This shouldn't happen (the anonymous scope is an implementation detail and `__traits(parent, ...)` shouldn't return it, especially not for symbols that are not even `static foreach` loop variables). Is there already an issue for this? Also, this code compiles neither with 2.086.1 nor 2.087.0. Do you have an example that demonstrates a regression?
Jul 23 2019
On 24.07.19 02:51, Timon Gehr wrote:Is there already an issue for this?Just noticed that the linked issue conflates both problems. I don't think that the visibility bug is the same as the `__traits(parent, ...)` one.
Jul 23 2019
On Wednesday, 24 July 2019 at 00:51:35 UTC, Timon Gehr wrote:This shouldn't happen (the anonymous scope is an implementation detail and `__traits(parent, ...)` shouldn't return it, especially not for symbols that are not even `static foreach` loop variables). Is there already an issue for this? Also, this code compiles neither with 2.086.1 nor 2.087.0. Do you have an example that demonstrates a regression?The entire point of that code I posted and the bug report I made is *to illustrate* that static foreach is broken. *OF COURSE* it shouldn't happen. And it shouldn't be this hard for an end user to work out what the problem is. 2.086.1 and 2.087.0 are the versions I've been developing on. Take the code, run it in prior DMDs. You'll find where it broke. I legit just pasted it in to godbolt and clicked on prior LDCs, it's been there as long as LDC has supported static foreach (ldc 1.6.0 based on dmd 2.076.1) Herringway on IRC even made a version without dependencies: static foreach( Name; [""] ) { struct StructOne {} } struct Z { static foreach( Name; [""] ) { struct StructOne {} } } pragma(msg, __traits(parent, StructOne).stringof); pragma(msg, __traits(parent, Z.StructOne).stringof);
Jul 23 2019
On Wednesday, 24 July 2019 at 01:06:18 UTC, Ethan wrote:It's 4am and I was planning on having a major feature finished 8 hours ago, but I've been running in to static foreach and mixin bugs all day.
Jul 23 2019
On Wednesday, 24 July 2019 at 01:10:34 UTC, Ethan wrote:On Wednesday, 24 July 2019 at 01:06:18 UTC, Ethan wrote:https://issues.dlang.org/show_bug.cgi?id=20079 https://issues.dlang.org/show_bug.cgi?id=20080 ........and when trying to get to sleep, I decided to try forward declarations for the functions I was having issues with in mixins. And finally hit upon what I think are the root problems I've been having. Mixin templates have been broken in one way or another since I started using D in 2012. This static foreach bug I've found just seems to highlight to me that the method of defining a separate scope and importing in to the parent after the fact just plain doesn't work.It's 4am and I was planning on having a major feature finished 8 hours ago, but I've been running in to static foreach and mixin bugs all day.
Jul 23 2019
On Wednesday, 24 July 2019 at 02:12:53 UTC, Ethan wrote:On Wednesday, 24 July 2019 at 01:10:34 UTC, Ethan wrote: but I've been running in to static foreach andThose are by design and it is a fairly useful design too. The presence of a name in the outer scope overrides the same name from the mixin. This allows easy selective customizing of a mixin template as you use it.mixin bugs all day.https://issues.dlang.org/show_bug.cgi?id=20079 https://issues.dlang.org/show_bug.cgi?id=20080
Jul 23 2019
On Wednesday, 24 July 2019 at 03:01:33 UTC, Adam D. Ruppe wrote:Those are by design and it is a fairly useful design too. The presence of a name in the outer scope overrides the same name from the mixin. This allows easy selective customizing of a mixin template as you use it.https://dlang.org/spec/template-mixin.html 3. Unlike a template instantiation, a template mixin's body is evaluated within the scope where the mixin appears, not where the template declaration is defined. It is analogous to cutting and pasting the body of the template into the location of the mixin into a nested scope. It is useful for injecting parameterized ‘boilerplate’ code, as well as for creating templated nested functions, which is not possible with template instantiations. So which one is it? Is it copy/paste and a replacement for parameterised C macros as sold, or is it something else? The spec here reeks of following the implementation instead of being clearly thought out. And it's far from the first time I've made this point.
Jul 23 2019
On Wednesday, 24 July 2019 at 03:11:02 UTC, Ethan wrote:So which one is it? Is it copy/paste and a replacement for parameterised C macros as sold, or is it something else?That page never claims it is a replacement for C macros, and it said it is "analogous" to copy/paste, not identical to it, then goes on to describe specific behaviors. The details of names appear later on: https://dlang.org/spec/template-mixin.html#mixin_scope including the overriding behavior of locals, conflicts with multiple mixins, and more. So, yes, it is something else.
Jul 23 2019
On 24.07.19 04:12, Ethan wrote:On Wednesday, 24 July 2019 at 01:10:34 UTC, Ethan wrote:This behavior is by design (for the better or worse, but those are not compiler bugs). You'd need to alias the mixin-template-local symbols into the current scope, or use string mixins instead of template mixins.On Wednesday, 24 July 2019 at 01:06:18 UTC, Ethan wrote:https://issues.dlang.org/show_bug.cgi?id=20079 https://issues.dlang.org/show_bug.cgi?id=20080 ...It's 4am and I was planning on having a major feature finished 8 hours ago, but I've been running in to static foreach and mixin bugs all day.........and when trying to get to sleep, I decided to try forward declarations for the functions I was having issues with in mixins. And finally hit upon what I think are the root problems I've been having. Mixin templates have been broken in one way or another since I started using D in 2012. This static foreach bug I've found just seems to highlight to me that the method of defining a separate scope and importing in to the parent after the fact just plain doesn't work.mixin templates are _designed_ that way, but `static foreach` doesn't work like this. The additional scopes are introduced for the purpose of containing the `static foreach` loop variable symbols, the symbols generated by `static foreach` themselves are _not_ treated like template mixins, they are inserted into the symbol table of the enclosing scope, but they need to be analyzed in the inner scope so the `static foreach` loop variable is visible. The `static foreach` implementation explicitly skips scopes containing `static foreach` loop variables (the __anonymous in the error messages) when determining parent symbols, so there is something weird going on. I'm trying to look into this, but I don't have that much time and for some reason the compiler doesn't build on my machine right now (linker errors)... I have no idea what's up with the visibility problems, as I haven't worked on that part of DMD's code, but probably there is a bad interaction between the code that checks for symbol visibility and `static foreach` loop variable scopes.
Jul 23 2019
On 24.07.19 05:10, Timon Gehr wrote:The `static foreach` implementation explicitly skips scopes containing `static foreach` loop variables (the __anonymous in the error messages) when determining parent symbols, so there is something weird going on. I'm trying to look into this, but I don't have that much time and for some reason the compiler doesn't build on my machine right now (linker errors)...https://github.com/dlang/dmd/pull/10214
Jul 23 2019
On Wednesday, 24 July 2019 at 03:56:44 UTC, Timon Gehr wrote:https://github.com/dlang/dmd/pull/10214Thank you.
Jul 24 2019
On 24.07.19 16:21, Ethan wrote:On Wednesday, 24 July 2019 at 03:56:44 UTC, Timon Gehr wrote:No problem, sorry for screwing this up in the first place. Does the patch solve all of your `static foreach`-related problems?https://github.com/dlang/dmd/pull/10214Thank you.
Jul 24 2019
On Thursday, 25 July 2019 at 00:15:22 UTC, Timon Gehr wrote:No problem, sorry for screwing this up in the first place. Does the patch solve all of your `static foreach`-related problems?I'll let you know when either I can compile DMD again, or the next point release comes out.
Jul 25 2019
On 24.07.19 03:06, Ethan wrote:On Wednesday, 24 July 2019 at 00:51:35 UTC, Timon Gehr wrote:As I am sure you are aware, this practice is called confirming a bug report. Not all of the issues you opened are in fact compiler bugs. Some of them are you misunderstanding the language specification. I asked whether you can demonstrates a regression because you said the problem arose when you updated compilers, but it seems it's because some deprecation period ended.This shouldn't happen (the anonymous scope is an implementation detail and `__traits(parent, ...)` shouldn't return it, especially not for symbols that are not even `static foreach` loop variables). Is there already an issue for this? Also, this code compiles neither with 2.086.1 nor 2.087.0. Do you have an example that demonstrates a regression?The entire point of that code I posted and the bug report I made is *to illustrate* that static foreach is broken. *OF COURSE* it shouldn't happen. ...
Jul 23 2019
On Tuesday, 23 July 2019 at 18:36:19 UTC, Ethan wrote:They've most definitely improved since DDMD happened, but they still seem predicated on the idea that people aren't going to be doing a lot of metaprogramming and provide almost no context when you're deep down the meta hole.The compiler on run.dlang.org provides plenty of context: /dlang/dmd/linux/bin64/../../src/phobos/std/traits.d(482): Error: local scope __anonymous is not a variable /dlang/dmd/linux/bin64/../../src/phobos/std/traits.d(580): Error: template instance `std.traits.parentOf!(StructOne)` error instantiating onlineapp.d(16): instantiated from here: moduleName!(StructOne) onlineapp.d(16): while evaluating pragma(msg, moduleName!(StructOne)) It provides instantiation stack and all line numbers where error occurs.
Jul 26 2019
On Friday, 26 July 2019 at 10:33:29 UTC, Kagamin wrote:The compiler on run.dlang.org provides plenty of context: /dlang/dmd/linux/bin64/../../src/phobos/std/traits.d(482): Error: local scope __anonymous is not a variable /dlang/dmd/linux/bin64/../../src/phobos/std/traits.d(580): Error: template instance `std.traits.parentOf!(StructOne)` error instantiating onlineapp.d(16): instantiated from here: moduleName!(StructOne) onlineapp.d(16): while evaluating pragma(msg, moduleName!(StructOne)) It provides instantiation stack and all line numbers where error occurs.Simple use cases like my example are not the problem. There's an error I was getting the other day that doesn't give a line number, just a file. Another one starts with "COMPILE". Both of those required unrolling code and tinkering to work out what was wedged in their bonnet. And of course I have no idea how to reproduce them either because they're deep in mixins in templated functions in templates in mixins. I do not write normal code in D. But down in my meta rabbit hole is where all of D's real ultimate power is.
Jul 26 2019
On Friday, 26 July 2019 at 12:56:07 UTC, Ethan wrote:There's an error I was getting the other day that doesn't give a line number, just a file. Another one starts with "COMPILE". Both of those required unrolling code and tinkering to work out what was wedged in their bonnet. And of course I have no idea how to reproduce them either because they're deep in mixins in templated functions in templates in mixins. I do not write normal code in D. But down in my meta rabbit hole is where all of D's real ultimate power is.I would like to voice a very enthusiastic recommendation for Dustmite for reducing programs to tests. Since it just requires a pass/fail test, it's easy to write a shellscript that checks that DMD's output matches a specific pattern, such as "COMPILE:.*".
Jul 26 2019
On Friday, 26 July 2019 at 13:02:21 UTC, FeepingCreature wrote:I would like to voice a very enthusiastic recommendation for Dustmite for reducing programs to tests. Since it just requires a pass/fail test, it's easy to write a shellscript that checks that DMD's output matches a specific pattern, such as "COMPILE:.*".Honestly, hot take/opinion time here. But every time I hear someone say "Dustmite" my immediate reaction is "Well I guess D isn't ready for production code." Let's have a for real example. I have a static assert in my receive function. If it detects that you've defined a message but haven't provided an implementation for receiving that message, it'll helpfully tell you exactly what you need to do. to generate correct message responses for an entire class of messages dealing with creating/syncing/deleting objects. Inside these functions, of course I write errors. Outside of {} braces, I almost never write any given line of code once. Things I haven't imported, typos, whatever. Nothing ever compiles first time. So I hit compile expecting to see what kind of problems are going on now. My static assert fires saying that this message isn't defined, compile stops dead in its tracks. I sit there going "what the Zod" for twenty minutes, double checking template definitions, rewriting template declarations, before I finally decide to go in to my send function and comment out the static assert and just let the compiler error on the receive call. Errors start showing up as normal in my templated functions. So what's going on here? Internally, the compiler knows my templated function won't compile. It knows there's an error. It knows the symbol can't be defined. But instead of giving me the errors for what's going on there first, it sees my static assert and jumps off a rather tall cliff taking everything it knows with it. Now, I could Dustmite my project. Which currently sits at 73 .d the moment, but I autogenerate a bunch of it and depenency properties are responsible for a ton of pointless bloat - but that's a digression.) Throw in Binderoo as well since I can't use off somewhere I won't touch and let it run for potentially days finding a minimal reproducible set. Or maybe I could spend the time to isolate and work out what makes the compiler do these weird things. Or I could do what I do daily in a production environment - fix or workaround the bug and get on trying to meet a deadline. I'll take door number three thanks. That potential customer isn't going to care how many bug reports I write, especially since I inevitably come across something a couple of hours later that should be Dustmited... Dustmote... Dusted. Whatever. I don't have that much CPU power to spare. Now. I know that's also a counter-productive viewpoint to have. "I got a bug!" Great, submit a bug report with a reproducible case. "I don't have the time!" Who else but me, right? But the overall point I started making at the start of this post is that door number three point. Get D in to a production environment, people aren't going to engage in jolly community co-operation. They want to get their job done, meet their goals/targets, get paid, eat, and generally just complain to their co-workers about the latest weird <yeah, imagine I broke the white-collar forum protocol here> that D is doing. Like every other colleague you've ever known using every other language you've ever used professionally. Wrapping up. Short of ye olde corporate "sign this NDA and get the keys to my codebase" approach to look at, I'm not sure what the middle ground is.
Jul 26 2019
On Friday, 26 July 2019 at 15:02:43 UTC, Ethan wrote:Now, I could Dustmite my project. Which currently sits at 73 .d at the moment, but I autogenerate a bunch of it and depenency properties are responsible for a ton of pointless bloat - but that's a digression.) Throw in Binderoo as well since I can't all off somewhere I won't touch and let it run for potentially days finding a minimal reproducible set. Or maybe I could spend the time to isolate and work out what makes the compiler do these weird things. Or I could do what I do daily in a production environment - fix or workaround the bug and get on trying to meet a deadline.Fair enough. When I hit a situation like that, I do take the time to dustmite things down and file a bug (and PR, if possible), but I am very much blessed to have a boss who understands that if you hit a bug, you can't really expect things to improve if you don't file a report, and that my coworkers have patience for me to wander off on a bug filing/fixing tangent. On the other hand, a lot of our longstanding pain points with D have actually gotten fixed, and none of that would have happened if there hadn't been bug reports. If you're long-term committed to a language, chances are that bug will show up again and waste hours of your time again. At some point it becomes cheaper to just file and fix it, instead of spending weeks of a new coworker's onboarding time getting them up to speed on all the D issues you've learnt to sidestep. And no, this does not exactly say good things about D for production use...
Jul 26 2019
On Friday, 26 July 2019 at 15:02:43 UTC, Ethan wrote:I have a static assert in my receive function. If it detects that you've defined a message but haven't provided an implementation for receiving that message, it'll helpfully tell you exactly what you need to do. comment out the static assert and just let the compiler error on the receive call.Isn't your complaint that the assert is not helpful? If it was helpful and told exactly what you need to do, why do you need to remove it and debug?
Jul 27 2019
On Saturday, 27 July 2019 at 09:14:54 UTC, Kagamin wrote:Isn't your complaint that the assert is not helpful?No, the complaint is that DMD withheld error information in favor of my static assert.If it was helpful and told exactly what you need to do, why do you need to remove it and debug?Because DMD withheld error information in favor of my static assert. So. Since I clearly didn't contextualise this properly. The static assert itself is in a mixin template. It is used in four objects currently - two different kinds of clients, and the server receivers that limit what they can do. This is why the static assert was added in the first place - an error would happen, DMD would report the error location as being inside a mixin without context as to where the mixin was invoked, and I'd be left wondering which part of my code I overlooked this time. Messages themselves are implemented in a mixin template. Mix them all in to the same class. Normally, these messages will compile, throw the error, and then the static assert will tell you the handy information. In this case, I wasn't getting the error messages and no idea of why the static assert was firing. This just plain appears to be a static assert problem in general. Probably by design, except the spec doesn't mention that static assert is dependent on scope resolution order. Here's an example without templates that illustrates what I'm referring to. Move the static assert inside main() and you get the behavior I was expecting. https://run.dlang.io/is/rjTRks -- void broken() { doesntexist(); } int main( string[] args ) { broken(); } static assert( false, "so here's a static assert" );
Jul 27 2019
On Saturday, 27 July 2019 at 11:24:11 UTC, Ethan wrote:https://run.dlang.io/is/rjTRks -- void broken() { doesntexist(); } int main( string[] args ) { broken(); } static assert( false, "so here's a static assert" );Again, in this example the compiler does provide context that assert fails at line 11. Function bodies are compiled at a later stage and it doesn't make sense to compile them if top level declarations failed to compile, if `doesntexist` only failed to compile and its every usage is reported as an error, it will be a very big amount of errors, which isn't helpful.
Jul 27 2019
On Saturday, 27 July 2019 at 16:36:35 UTC, Kagamin wrote:Again, in this example the compiler does provide context that assert fails at line 11. Function bodies are compiled at a later stage and it doesn't make sense to compile them if top level declarations failed to compileYour definition of context is incomplete. I cannot think of a single programmer that wants to hit compile every time they fix one single compiler error just to find another single compile error. Stopping at one static assert is undesired behavior in a production environment. If this behavior is by design, it's terrible design.
Jul 27 2019
When a function is compiled in incorrect environment it's likely to report induced errors, and those are very confusing. Do programmers want to hunt for induced errors? When the compiler is invoked in console and first prints the relevant error and then lots of induced errors, they will scroll the relevant error out of sight, the fact that stacks are printed inside out is a little unwieldy too.
Jul 27 2019
On Saturday, 27 July 2019 at 18:59:20 UTC, Kagamin wrote:SomethingIs that proving my point? I think it is. It appears you implied a programmer will hunt for the correct error message given a complete output. Which the current static assert functionality is not making possible. Either that or you're arguing that reducing the context of an error message is helpful to someone. Which, hey, I've got news for you.
Jul 27 2019
On Saturday, 27 July 2019 at 16:59:36 UTC, Ethan wrote:Stopping at one static assert is undesired behavior in a production environment.If continuing is desired, would a `static if` combined with `pragma (msg, ...)` not be more appropriate than `static assert`? This can probably go into a ct function like `static_check`. Bastiaan.
Jul 27 2019
On Saturday, 27 July 2019 at 22:19:20 UTC, Bastiaan Veelo wrote:If continuing is desired, would a `static if` combined with `pragma (msg, ...)` not be more appropriate than `static assert`? This can probably go into a ct function like `static_check`. Bastiaan.I was considering making that point myself. The static assert here is kinda useless, a pragma( msg ) won't stop compilation. This is in that weird <non-PC word> area that people keep bringing up. The recommended course of development with templates is to static assert with your own handy error message. The reality is that you lose vital information about why that template is not instantiating unless you litter your code with static ifs and pragma( msg )s.
Jul 27 2019
On Saturday, 27 July 2019 at 22:22:57 UTC, Ethan wrote:On Saturday, 27 July 2019 at 22:19:20 UTC, Bastiaan Veelo wrote:Tossing in a `version` may produce a helpful idiom, if compilation should continue during lib dev and stop during lib usage: ``` import std; void my_static_assert(alias condition, string message)() { version(continue_past_assert) { static if (!condition) pragma(msg, message); } else { static assert(condition, message); } } void main() { my_static_assert!(false, "fix your mistake"); writeln("Hello D"); } ``` https://run.dlang.io/is/5NqYj7If continuing is desired, would a `static if` combined with `pragma (msg, ...)` not be more appropriate than `static assert`? This can probably go into a ct function like `static_check`. Bastiaan.I was considering making that point myself. The static assert here is kinda useless, a pragma( msg ) won't stop compilation. This is in that weird <non-PC word> area that people keep bringing up. The recommended course of development with templates is to static assert with your own handy error message. The reality is that you lose vital information about why that template is not instantiating unless you litter your code with static ifs and pragma( msg )s.
Jul 27 2019
On Saturday, 27 July 2019 at 16:59:36 UTC, Ethan wrote:On Saturday, 27 July 2019 at 16:36:35 UTC, Kagamin wrote:How would you propose changing the compiler such that you got the "right" amount of errors, without any spurious ones? IIRC the current design "poisons" anything derived from an error to minimise error spam. In D it's very easy for one little typo to invalidate vast amounts of code, which leads to massive cascading errors.Again, in this example the compiler does provide context that assert fails at line 11. Function bodies are compiled at a later stage and it doesn't make sense to compile them if top level declarations failed to compileYour definition of context is incomplete. I cannot think of a single programmer that wants to hit compile every time they fix one single compiler error just to find another single compile error. Stopping at one static assert is undesired behavior in a production environment. If this behavior is by design, it's terrible design.
Jul 28 2019
On Sunday, 28 July 2019 at 11:41:20 UTC, John Colvin wrote:In D it's very easy for one little typo to invalidate vast amounts of code, which leads to massive cascading errors.I mean, that's true of C++ as well.How would you propose changing the compiler such that you got the "right" amount of errors, without any spurious ones? IIRC the current design "poisons" anything derived from an error to minimise error spam.I've long held the view that DMD's error reporting is not that great. And after my recent poke at the C++ mangler code and seeing the state of things... The move to DDMD means it's time to revist the reasons for why error reporting was done like that in the first place. First and foremost, my constant battle for *any* error generated while processing code must show the file and line it was processing at the time. I know Walter's view is "you know what code you were just writing." But the reality of software development in D (templates and mixins and metaprogramming, oh my!) and software development in general (pull a source code database from the internet and compile it with a newer version of a compiler than it was generated on) means that the point becomes increasingly irrelevant as time and complexity increases from when a piece of code was originally written. My other battle is error codes. Microsoft's documentation is spot on there. Your compiler generates an error code. Copy that code and stick it in to Google. Microsoft results up top, StackOverflow/etc right beneath it. Now you can go directly to relevant articles instead of trying to strip all context out of the message like type names and Google things that way, which is really inconsistent in the results you can get. The old argument that error codes increase the execution time of a compile, or the compilation time of DMD, surely must be irrelevant now. All this stuff can be handled with D's metaprogramming capabilities for no runtime cost. Don't make a table that needs static initialisation, make a table and assign it to an enum. The error function already works as a printf, so that's not a problem. You can even reduce the number of error calls you need to make, since the error code can contain information on whether it's a fatal error that stops the compiler or not. Currently that's two calls - one to error() and one to fatal(). And with all those error codes centralised, you can also generate documentation and upload it to dlang.org. Imagine the luxury of searching documentation instead of disparate forum posts for information on your error. So with all this in place. static_assert is currently treated as a fatal(), right? But I don't want it to. But some people desire that behavior. So surely we can parameterise static_assert in some manner to allow this?
Jul 29 2019
On Monday, 29 July 2019 at 15:28:02 UTC, Ethan wrote:On Sunday, 28 July 2019 at 11:41:20 UTC, John Colvin wrote:From C++20 overview https://hackaday.com/2019/07/30/c20-is-feature-complete-heres-what changes-are-coming/ :In D it's very easy for one little typo to invalidate vast amounts of code, which leads to massive cascading errors.I mean, that's true of C++ as well.As a result, the compiler can provide a short and meaningful error message if the defined requirement of a concept isn’t met, instead of dumping walls of errors and warnings from somewhere deep within the template code itself that won’t make much sense without digging further into that code.Looks like C++ compilers are supposed to print less errors too.
Jul 31 2019
On Wednesday, 31 July 2019 at 13:21:01 UTC, Kagamin wrote:Let's take a closer look, shall we....As a result, the compiler can provide a short and meaningful error message if the defined requirement of a concept isn’t met, instead of dumping walls of errors and warnings from somewhere deep within the template code itself that won’t make much sense without digging further into that code.Looks like C++ compilers are supposed to print less errors too.As a result, the compiler can provide a short and meaningful error message if the defined requirement of a concept isn’t metthe compiler can provide a short and meaningful error messageshort and meaningful error messagemeaningful error messagePerhaps you missed the point where I'm complaining that the static assert behavior *HIDES* short meaningful error messages. Come back to reality. We miss you.
Jul 31 2019