May 20, 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 up

Well, 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:
>> 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
>
> Well, 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.

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); // w00t

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:
> > 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
>
> Well, 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.

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 Davis

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 Davis

I 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 21, 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:
>> 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
> 
> Well, 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.

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.

-Steve
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
> 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
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:
>> [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?

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.

>> 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.

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.

>>
>> 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.

Agreed, it is cool when your compiler tells you bugs like a variable is used before it's assigned, etc.

> 
>>
>> 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.

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.

-Steve
1 2
Next ›   Last »