digitalmars.D - Error about constructor calls in loops/labels, but there are no loops
- DarkHole (3/3) May 17 2018 This strange code - https://run.dlang.io/is/BKgv49 - fails with
- Steven Schveighoffer (3/6) May 17 2018 Switch cases are labels.
- Steven Schveighoffer (7/13) May 17 2018 That being said, I don't understand the point of this restriction in
- DarkHole (3/9) May 17 2018 But why?
- Steven Schveighoffer (6/15) May 17 2018 You mean why is it an error? Probably because the compiler needs to
- Yuxuan Shui (4/21) May 19 2018 Why isn't the compiler doing proper flow analysis? Is it that
- Jonathan M Davis (24/48) May 19 2018 As I understand it, in general, Walter is against doing much in the way ...
- KingJoffrey (4/5) May 19 2018 All I ever hear, is walter walter walter....
- Neia Neutuladh (17/21) May 19 2018 While it's mildly refreshing that you found something new to talk
- KingJoffrey (7/15) May 19 2018 Think of it this way.. that I'm injecting some quantum
- Yuxuan Shui (5/8) May 20 2018 Well, doesn't this post show exactly this problem, and that's
- Daniel N (7/15) May 20 2018 There is one construct which is guaranteed to run at the end...
- Jonathan M Davis (30/38) May 20 2018 Well, constructors are one of the few places that the compiler attempts ...
- Yuxuan Shui (4/39) May 20 2018 I would argue that the best approach is to design the language to
- Steven Schveighoffer (23/32) May 21 2018 There is something to be said for keeping the compiler dumb:
- Yuxuan Shui (17/43) May 21 2018 My response below might be a little off-topic.
- Steven Schveighoffer (31/76) May 21 2018 There are at least two other incomplete front ends. One by deadalnix
- Yuxuan Shui (5/13) May 21 2018 Clarification to my last point. I'm saying Swift's compiler is
This strange code - https://run.dlang.io/is/BKgv49 - fails with error "Error: constructor calls not allowed in loops or after labels", but there is no loops or labels.
May 17 2018
On 5/17/18 3:55 PM, DarkHole wrote:This strange code - https://run.dlang.io/is/BKgv49 - fails with error "Error: constructor calls not allowed in loops or after labels", but there is no loops or labels.Switch cases are labels. -Steve
May 17 2018
On 5/17/18 4:02 PM, Steven Schveighoffer wrote:On 5/17/18 3:55 PM, DarkHole wrote:That being said, I don't understand the point of this restriction in this case -- yes, it's after a label, but it's after the whole switch construct. It's probably a conservative application of a rule. You can fix by moving the final switch into a function: https://run.dlang.io/is/352nIC -SteveThis strange code - https://run.dlang.io/is/BKgv49 - fails with error "Error: constructor calls not allowed in loops or after labels", but there is no loops or labels.Switch cases are labels.
May 17 2018
On Thursday, 17 May 2018 at 20:02:19 UTC, Steven Schveighoffer wrote:On 5/17/18 3:55 PM, DarkHole wrote:But why?This strange code - https://run.dlang.io/is/BKgv49 - fails with error "Error: constructor calls not allowed in loops or after labels", but there is no loops or labels.Switch cases are labels. -Steve
May 17 2018
On 5/17/18 4:25 PM, DarkHole wrote:On Thursday, 17 May 2018 at 20:02:19 UTC, Steven Schveighoffer wrote:You mean why is it an error? Probably because the compiler needs to guarantee you are calling the super constructor, and it can't figure out the flow when it sees labels/loops. Not that it's always impossible, but it's likely a complication the compiler devs don't want to deal with. -SteveOn 5/17/18 3:55 PM, DarkHole wrote:But why?This strange code - https://run.dlang.io/is/BKgv49 - fails with error "Error: constructor calls not allowed in loops or after labels", but there is no loops or labels.Switch cases are labels.
May 17 2018
On Thursday, 17 May 2018 at 20:32:23 UTC, Steven Schveighoffer wrote:On 5/17/18 4:25 PM, DarkHole wrote:Why isn't the compiler doing proper flow analysis? Is it that just no one bothered to implement it?On Thursday, 17 May 2018 at 20:02:19 UTC, Steven Schveighoffer wrote:You mean why is it an error? Probably because the compiler needs to guarantee you are calling the super constructor, and it can't figure out the flow when it sees labels/loops. Not that it's always impossible, but it's likely a complication the compiler devs don't want to deal with. -SteveOn 5/17/18 3:55 PM, DarkHole wrote:But why?This strange code - https://run.dlang.io/is/BKgv49 - fails with error "Error: constructor calls not allowed in loops or after labels", but there is no loops or labels.Switch cases are labels.
May 19 2018
On Saturday, May 19, 2018 22:54:16 Yuxuan Shui via Digitalmars-d wrote:On Thursday, 17 May 2018 at 20:32:23 UTC, Steven Schveighoffer wrote:As I understand it, in general, Walter is against doing much in the way of flow analysis, because it tends to become very difficult to get right in all cases and results in situations where the programmer is forced to do something in order to make the compiler shut up - e.g. in Java, you're forced to initialize all variables, and it's not uncommon that you have to initialize variables when you can clearly see that it shouldn't be necessary, but the compiler isn't smart enough to see that. Also, if D started use more flow analysis, then the exact rules of the flow analysis would have to be in the spec and set in stone, or you end up with code compiling on one compiler but not another. So, given issues like these Walter has taken the approach of trying to avoid doing much where flow analysis would be required by the spec. In the case of initialization, D's approach is to default-initialize evertything and then let the optimizer optimize out unnessary initializations where it can, which avoids the problem that Java has and eliminated the need to embed the flow analysis rules in the spec. And in general, the places that D does much in the way of flow analysis is in the optimization step where the compiler is free to change an improve how it does flow analysis. There are a few places wheree it's forced to do basic flow analysis (e.g. in constructors in cases like you ran into here), but in such cases, it pretty much always sticks to simple rules so that the flow analysis does not have to be complicated. - Jonathan M DavisOn 5/17/18 4:25 PM, DarkHole wrote:Why isn't the compiler doing proper flow analysis? Is it that just no one bothered to implement it?On Thursday, 17 May 2018 at 20:02:19 UTC, Steven Schveighoffer wrote:You mean why is it an error? Probably because the compiler needs to guarantee you are calling the super constructor, and it can't figure out the flow when it sees labels/loops. Not that it's always impossible, but it's likely a complication the compiler devs don't want to deal with. -SteveOn 5/17/18 3:55 PM, DarkHole wrote:But why?This strange code - https://run.dlang.io/is/BKgv49 - fails with error "Error: constructor calls not allowed in loops or after labels", but there is no loops or labels.Switch cases are labels.
May 19 2018
On Sunday, 20 May 2018 at 00:05:39 UTC, Jonathan M Davis wrote:As I understand it, in general, Walter is against doing ...All I ever hear, is walter walter walter.... mmm..takes me back to my childhood.. https://www.youtube.com/watch?v=-yZHveWFvqM
May 19 2018
On Sunday, 20 May 2018 at 02:53:10 UTC, KingJoffrey wrote:On Sunday, 20 May 2018 at 00:05:39 UTC, Jonathan M Davis wrote:While it's mildly refreshing that you found something new to talk about, it would be nice if you found something productive to say. You're merely complaining that a person who has spent about two decades on D (for free), who has decades more experience with compilers, who is the main contributor to the D compiler, and who has a track record of being right a lot, is influential when it comes to changes to the language. This is social influence. Jonathan M Davis cited Walter's previous complaint because we generally care what Walter thinks, because we respect him. We won't always agree, but he usually has a decent reason for holding a position regarding compilers and programming languages. If this bothers you, make your own language. You might not want to design it yourself, lest you fall into the same trap. Maybe you can find a committee? Or use a random number generator to design it?As I understand it, in general, Walter is against doing ...All I ever hear, is walter walter walter....
May 19 2018
On Sunday, 20 May 2018 at 03:13:12 UTC, Neia Neutuladh wrote:While it's mildly refreshing that you found something new to talk about, it would be nice if you found something productive to say. You're merely complaining that a person who has spent about two decades on D (for free), who has decades more experience with compilers, who is the main contributor to the D compiler, and who has a track record of being right a lot, is influential when it comes to changes to the language. da da dah da dah dah dah dahhhhhhhhThink of it this way.. that I'm injecting some quantum fluctuations into the D universe, in the hope that it triggers an inflationary period - otherwise the D universe will fizzle and die... Creating another universe from scratch, is a long drawn out process..who want's to sit around for that to happen?
May 19 2018
On Sunday, 20 May 2018 at 00:05:39 UTC, Jonathan M Davis wrote:because it tends to become very difficult to get right in all cases and results in situations where the programmer is forced to do something in order to make the compiler shut upWell, doesn't this post show exactly this problem, and that's because the compiler is too dumb? Making the compiler smarter will only decrease the number of these cases.
May 20 2018
On Sunday, 20 May 2018 at 10:56:27 UTC, Yuxuan Shui wrote:On Sunday, 20 May 2018 at 00:05:39 UTC, Jonathan M Davis wrote:There is one construct which is guaranteed to run at the end... this(ExceptionType t, long rowsNum, string file = __FILE__, size_t line = __LINE__) pure safe { type = t; string msg; scope(exit) super(msg, file, line); // w00tbecause it tends to become very difficult to get right in all cases and results in situations where the programmer is forced to do something in order to make the compiler shut upWell, doesn't this post show exactly this problem, and that's because the compiler is too dumb? Making the compiler smarter will only decrease the number of these cases.
May 20 2018
On Sunday, May 20, 2018 10:56:27 Yuxuan Shui via Digitalmars-d wrote:On Sunday, 20 May 2018 at 00:05:39 UTC, Jonathan M Davis wrote:Well, constructors are one of the few places that the compiler attempts flow analysis for stuff other than optimization, because it pretty much has to in order to do what the language needs. And no, it's not very sophisticated about it, because it's simpler to guarantee correctness that way. It also highlights why Walter is usually against doing much in the way of flow analysis. By designing the language such that it doesn't need much flow analysis, you mostly avoid problems like this. Unfortunately, it becomes more or less impossible to completely avoid it in constructors when you have const or immutable members, so the compiler does have to do some flow analysis in constructors. And it seems that Walter's solution in this sort of situation is to err on the side of having the compiler be stupid in order to avoid better guarantee correctness. Not being a compiler expert, I can't really comment on what the best approach would be here, but I know that Walter is typically against flow analysis at the semantic pass level precisely because it's very hard to get right, and it's always a battle between having it be sophisticated enough to not get in the programmers way and having it actually be guaranteed to be correct. As I understand it, flow analysis in stuff like the optimizer is _much_ easier, because the constructs you're dealing with are much easier. That's also why Walter and Andrei really like to design advanced language features in terms of lowering into simpler features (e.g. the use of destructors and scope statments all get lowered to try-catch-finally blocks). It's much easier to guarantee correctness with simpler features. As for this particular case, I expect that the best course of action is to report it in bugzilla and see what Walter thinks is the best approach. I can comment on Walter's basic approach and reasoning based on what he's said about these issues in the past, but I can't way what his response would be to this particular example. - Jonathan M Davisbecause it tends to become very difficult to get right in all cases and results in situations where the programmer is forced to do something in order to make the compiler shut upWell, doesn't this post show exactly this problem, and that's because the compiler is too dumb? Making the compiler smarter will only decrease the number of these cases.
May 20 2018
On Sunday, 20 May 2018 at 14:39:28 UTC, Jonathan M Davis wrote:Well, constructors are one of the few places that the compiler attempts flow analysis for stuff other than optimization, because it pretty much has to in order to do what the language needs. And no, it's not very sophisticated about it, because it's simpler to guarantee correctness that way. It also highlights why Walter is usually against doing much in the way of flow analysis. By designing the language such that it doesn't need much flow analysis, you mostly avoid problems like this. Unfortunately, it becomes more or less impossible to completely avoid it in constructors when you have const or immutable members, so the compiler does have to do some flow analysis in constructors. And it seems that Walter's solution in this sort of situation is to err on the side of having the compiler be stupid in order to avoid better guarantee correctness. Not being a compiler expert, I can't really comment on what the best approach would be here, but I know that Walter is typically against flow analysis at the semantic pass level precisely because it's very hard to get right, and it's always a battle between having it be sophisticated enough to not get in the programmers way and having it actually be guaranteed to be correct. As I understand it, flow analysis in stuff like the optimizer is _much_ easier, because the constructs you're dealing with are much easier. That's also why Walter and Andrei really like to design advanced language features in terms of lowering into simpler features (e.g. the use of destructors and scope statments all get lowered to try-catch-finally blocks). It's much easier to guarantee correctness with simpler features. As for this particular case, I expect that the best course of action is to report it in bugzilla and see what Walter thinks is the best approach. I can comment on Walter's basic approach and reasoning based on what he's said about these issues in the past, but I can't way what his response would be to this particular example. - Jonathan M DavisI would argue that the best approach is to design the language to avoid flow analysis as much as possible. But for places that need it, the compiler should do as best as it can.
May 20 2018
On 5/20/18 6:56 AM, Yuxuan Shui wrote:On Sunday, 20 May 2018 at 00:05:39 UTC, Jonathan M Davis wrote:There is something to be said for keeping the compiler dumb: 1. Dumb is easy to implement, explain, and understand -- if you set the bar low then more compilers will be able to handle the use cases. Having code that compiles with all available compilers is better than something that you need a specific "really smart" compiler to work. 2. No matter how smart you make the compiler, you will get into situations that it can't figure out (halting problem). If you are going to have some situations that it doesn't handle, then it's really just a matter of where to draw the line. D has this problem with forward references -- it's a never ending battle of shuffling things around sometimes. The smarter you get, the more odd and difficult to deal with the cases that won't work become. With inner functions, it's really easy to satisfy the compiler here. You just have to make a few changes in your code, I don't see it being a huge problem. I've been using Swift in the past few years quite a bit, and it always amuses me when it can't figure out some kind of inference that seems trivial, but it just gives up because the compiler takes too long to determine: "This [one line] statement is too difficult, please split into multiple statements." This is the kind of stuff you would be encountering. -Stevebecause it tends to become very difficult to get right in all cases and results in situations where the programmer is forced to do something in order to make the compiler shut upWell, doesn't this post show exactly this problem, and that's because the compiler is too dumb? Making the compiler smarter will only decrease the number of these cases.
May 21 2018
My response below might be a little off-topic. On Monday, 21 May 2018 at 13:06:14 UTC, Steven Schveighoffer wrote:[snip] There is something to be said for keeping the compiler dumb: 1. Dumb is easy to implement, explain, and understand -- if you set the bar low then more compilers will be able to handle the use cases. Having code that compiles with all available compilers is better than something that you need a specific "really smart" compiler to work.This would have been a fair point if there is more than one working D frontend right now. Maybe you are arguing the bar of D could be lower? Then the problem of where to draw the line pops up again. "Being dumb" couldn't be a goal of the language, right?2. No matter how smart you make the compiler, you will get into situations that it can't figure out (halting problem).True.If you are going to have some situations that it doesn't handle, then it's really just a matter of where to draw the line. D has this problem with forward references -- it's a never ending battle of shuffling things around sometimes. The smarter you get, the more odd and difficult to deal with the cases that won't work become.I would argue this is not because the compiler is too smart. This is because the behavior of the compiler is not pinned down. How D resolve forward references is not well documented, so when problem occurs you have to guess (or read the compiler source code, like a real man) to figure out how to solve it.With inner functions, it's really easy to satisfy the compiler here. You just have to make a few changes in your code, I don't see it being a huge problem.Not a huge problem, but certainly a rough edge that might make someone think D is an unrefined language.I've been using Swift in the past few years quite a bit, and it always amuses me when it can't figure out some kind of inference that seems trivial, but it just gives up because the compiler takes too long to determine: "This [one line] statement is too difficult, please split into multiple statements." This is the kind of stuff you would be encountering.Not sure if this is another case of compiler being not smart enough? And the solution seems to be pretty simple here.-Steve
May 21 2018
On 5/21/18 4:29 PM, Yuxuan Shui wrote:My response below might be a little off-topic. On Monday, 21 May 2018 at 13:06:14 UTC, Steven Schveighoffer wrote:There are at least two other incomplete front ends. One by deadalnix (sdc) and one by Timon Gehr. But surely, if we got it right in the main front end, such techniques could be done in others right? Well, the problem simply is that I don't think there is a magic bullet here. We will have situations that are clear to a human that all paths call the super ctor, but aren't clear to some compilers. In that case, the language is different based on which compiler you might use. Rather than it be dependent on approximating a solution to an insolvable problem, we can simply say the *minimum* is this, and we KNOW that can be implemented. In turn, we also know that D gives you the tools to make it easy to conform to these requirements.[snip] There is something to be said for keeping the compiler dumb: 1. Dumb is easy to implement, explain, and understand -- if you set the bar low then more compilers will be able to handle the use cases. Having code that compiles with all available compilers is better than something that you need a specific "really smart" compiler to work.This would have been a fair point if there is more than one working D frontend right now. Maybe you are arguing the bar of D could be lower? Then the problem of where to draw the line pops up again. "Being dumb" couldn't be a goal of the language, right?I know Timon's front end handles a crazy amount of forward references. I've sat next to him at previous dconfs and he periodically shows me stuff his front end can handle, and it's insane. But in the meantime, the situation is not straightforward with forward references, and I'd fear that opening the gates to more flow analysis allowances would continue with those games.If you are going to have some situations that it doesn't handle, then it's really just a matter of where to draw the line. D has this problem with forward references -- it's a never ending battle of shuffling things around sometimes. The smarter you get, the more odd and difficult to deal with the cases that won't work become.I would argue this is not because the compiler is too smart. This is because the behavior of the compiler is not pinned down. How D resolve forward references is not well documented, so when problem occurs you have to guess (or read the compiler source code, like a real man) to figure out how to solve it.Agreed, it is cool when your compiler tells you bugs like a variable is used before it's assigned, etc.With inner functions, it's really easy to satisfy the compiler here. You just have to make a few changes in your code, I don't see it being a huge problem.Not a huge problem, but certainly a rough edge that might make someone think D is an unrefined language.I believe it's due to the goal of "we're going to infer ALL THE TYPES!" hitting the reality of actual code that makes it not that simple, or exponential performance to really get the answer. Stuff that's painfully obvious to you or me is not so obvious to the compiler that has to actually prove it. That being said, I haven't used swift much lately, but I don't remember this happening much to me in the recent past. So maybe they have gotten better at it or solved it. -SteveI've been using Swift in the past few years quite a bit, and it always amuses me when it can't figure out some kind of inference that seems trivial, but it just gives up because the compiler takes too long to determine: "This [one line] statement is too difficult, please split into multiple statements." This is the kind of stuff you would be encountering.Not sure if this is another case of compiler being not smart enough? And the solution seems to be pretty simple here.
May 21 2018
I've been using Swift in the past few years quite a bit, and it always amuses me when it can't figure out some kind of inference that seems trivial, but it just gives up because the compiler takes too long to determine: "This [one line] statement is too difficult, please split into multiple statements." This is the kind of stuff you would be encountering.Clarification to my last point. I'm saying Swift's compiler is not smart enough, because other type inference languages doesn't seem to have this weird limitation. Worst case is they can't infer the type, then they fail back to not inferring, which is not worse than not having type inference.-Steve
May 21 2018