August 09, 2011
On 8/9/2011 2:08 PM, Jonathan M Davis wrote:
> From what I can see though, it sure looks like any C code which relies on the
> C behavior would be buggy.

I don't see any way to make that judgment. It's been Standard C behavior forever, including K+R prehistory. It's guaranteed that a lot of code will rely on it, whether or not anyone considers it good form.
August 09, 2011
> On Wed, 10 Aug 2011 00:08:02 +0300, Jonathan M Davis <jmdavisProg@gmx.com>
> 
> wrote:
> > There's no reason to have a separate version of the language which is
> > more
> > compatible with C than another version. It would just complicate things.
> > 
> > Not
> > only would it be a burden on the compiler maintainers, but then you
> > would have
> > to know whether code was intended to be compiled with the standard D
> > compiler
> > or with the one which is more compatible with C. It would be a mess for
> > very
> > little benefit.
> 
> I see having a compiler flag is a bad idea, it would be entirely in the
> source code.
> It is not about having more/less compatible compilers. There is only one
> compiler to be maintained and it is D.
> Getting rid of such a restriction (C compatibility) would be priceless i
> can't express, and i don't understand why it is not obvious.
> Our problem is this very restriction. D should be called "C like (easy to
> learn if you know C/C++) and supports C natively", not "C compatible".
> Because if being out of date was the only thing wrong about C then someone
> would just add some modern features and call it maybe... C++-+%?

In general, it's not a problem at all. It's only relevant when the C/C++ code is valid D code. It often isn't. For the most part, the code which is both valid C/C++ code and valid D code is valid Java code and valid C# code as well (the primary exception that I can think of being pointers). It's stuff which is common across C-based languages and would screw over programmers pretty thoroughly if it changed. There are a few exceptions (such as this issue with the shift operator) which are a problem, but for the most part, it's really not an issue. It's trying to maintain C++'s level of compatibility with C where you really get into trouble. D does _not_ maintain anything even close to that level of compatability. It just chooses to be compatible when the syntax is identical so that code which is ported from C or C++ doesn't silently break.

So, while from what I can see, I think that in this particular case, it would be a good idea to fix C's behavior rather than follow it, I think that you're blowing the issue of general C compatibility out of proportion. D breaks compatibility all over the place. It just doesn't do it when C code would be valid D code.

- Jonathan M Davis
August 09, 2011
> On 8/9/2011 2:08 PM, Jonathan M Davis wrote:
> > From what I can see though, it sure looks like any C code which relies on the C behavior would be buggy.
> 
> I don't see any way to make that judgment. It's been Standard C behavior forever, including K+R prehistory. It's guaranteed that a lot of code will rely on it, whether or not anyone considers it good form.

Hmmm. It seems to me that the question is whether anyone would ever _intentially_ use this behavior. Is there any benefit to it whatsoever? If not, I'd argue that the risk of breakage to C code being ported over is minimal and that the behavior should be fixed in D. Now, if there _is_ a benefit to it such that someone would use it intentionally, then that's another story, but it sure likes like the only reason that it would occur in C code would be because the programmer who wrote it screwed up.

Now, that's still going to change the behavior of any code which used this behavior - even if it was by accident - which risks making code fail to work even if it only worked through a miracle before (i.e. in spite of the bug). So, maybe that's enough that we can't fix it. But it sure seems like the risk of new breakage is very low, since code whose behavior would change was broken in the first place, and I'd hate to see D's behavior stay like this if we can fix it.

- Jonathan M Davis
August 09, 2011
On Wed, 10 Aug 2011 00:57:17 +0300, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

>> I see having a compiler flag is a bad idea, it would be entirely in the
>> source code.
>> It is not about having more/less compatible compilers. There is only one
>> compiler to be maintained and it is D.
>> Getting rid of such a restriction (C compatibility) would be priceless i
>> can't express, and i don't understand why it is not obvious.
>> Our problem is this very restriction. D should be called "C like (easy to
>> learn if you know C/C++) and supports C natively", not "C compatible".
>> Because if being out of date was the only thing wrong about C then someone
>> would just add some modern features and call it maybe... C++-+%?
>
> In general, it's not a problem at all. It's only relevant when the C/C++ code
> is valid D code. It often isn't. For the most part, the code which is both
> valid C/C++ code and valid D code is valid Java code and valid C# code as well
> (the primary exception that I can think of being pointers). It's stuff which
> is common across C-based languages and would screw over programmers pretty
> thoroughly if it changed. There are a few exceptions (such as this issue with
> the shift operator) which are a problem, but for the most part, it's really
> not an issue. It's trying to maintain C++'s level of compatibility with C
> where you really get into trouble. D does _not_ maintain anything even close
> to that level of compatability. It just chooses to be compatible when the
> syntax is identical so that code which is ported from C or C++ doesn't
> silently break.

What you are saying just covers the language being a C like language, aren't we talking about the restriction and threat it pose to the language?

> D breaks compatibility all over the place. It just doesn't do it when C code would be valid D code.

I am afraid this is not quite right. Wouldn't it be oxymoron when you reject every solution/idea using this argument? It doesn't matter if the idea has no merit or it was the meaning of life.
August 09, 2011
On 8/9/2011 3:04 PM, Jonathan M Davis wrote:
> Hmmm. It seems to me that the question is whether anyone would ever
> _intentially_ use this behavior. Is there any benefit to it whatsoever? If
> not, I'd argue that the risk of breakage to C code being ported over is
> minimal and that the behavior should be fixed in D. Now, if there _is_ a
> benefit to it such that someone would use it intentionally, then that's
> another story, but it sure likes like the only reason that it would occur in C
> code would be because the programmer who wrote it screwed up.
>
> Now, that's still going to change the behavior of any code which used this
> behavior - even if it was by accident - which risks making code fail to work
> even if it only worked through a miracle before (i.e. in spite of the bug).
> So, maybe that's enough that we can't fix it. But it sure seems like the risk
> of new breakage is very low, since code whose behavior would change was broken
> in the first place, and I'd hate to see D's behavior stay like this if we can
> fix it.

I don't see why it's a miracle that s>>1 would yield an int result.

Do any of the C lints flag this as a bad practice?

August 09, 2011
> On Wed, 10 Aug 2011 00:57:17 +0300, Jonathan M Davis <jmdavisProg@gmx.com>
> 
> wrote:
> >> I see having a compiler flag is a bad idea, it would be entirely in the
> >> source code.
> >> It is not about having more/less compatible compilers. There is only one
> >> compiler to be maintained and it is D.
> >> Getting rid of such a restriction (C compatibility) would be priceless i
> >> can't express, and i don't understand why it is not obvious.
> >> Our problem is this very restriction. D should be called "C like (easy
> >> to
> >> learn if you know C/C++) and supports C natively", not "C compatible".
> >> Because if being out of date was the only thing wrong about C then
> >> someone
> >> would just add some modern features and call it maybe... C++-+%?
> > 
> > In general, it's not a problem at all. It's only relevant when the C/C++
> > code
> > is valid D code. It often isn't. For the most part, the code which is
> > both
> > valid C/C++ code and valid D code is valid Java code and valid C# code
> > as well
> > (the primary exception that I can think of being pointers). It's stuff
> > which
> > is common across C-based languages and would screw over programmers
> > pretty
> > thoroughly if it changed. There are a few exceptions (such as this issue
> > with
> > the shift operator) which are a problem, but for the most part, it's
> > really
> > not an issue. It's trying to maintain C++'s level of compatibility with C
> > where you really get into trouble. D does _not_ maintain anything even
> > close
> > to that level of compatability. It just chooses to be compatible when the
> > syntax is identical so that code which is ported from C or C++ doesn't
> > silently break.
> 
> What you are saying just covers the language being a C like language, aren't we talking about the restriction and threat it pose to the language?
> 
> > D breaks compatibility all over the place. It just doesn't do it when C code would be valid D code.
> 
> I am afraid this is not quite right. Wouldn't it be oxymoron when you reject every solution/idea using this argument? It doesn't matter if the idea has no merit or it was the meaning of life.

??? One of the rules of language design that Walter has stuck to throughout the development of D is that if you take any C or C++ code and try to compile it as D code, it will either fail to compile, or it will compile with the same behavior as the code would have had in C or C++. This is so that you don't silently introduce bugs when porting code from C or C++ to D.

There's _lots_ of stuff in D that isn't valid C code, and there's plenty of stuff in C which isn't valid D code. Saying that C/C++ code must either be valid D code with the same behavior or not compile is not particularly restrictive on the whole. It's really only an issue with some arithmetic stuff. D is free to add additional restrictions (such as requiring casts for narrowing conversions), and it can do whatever it wants which is different from C as long as it isn't valid C - and almost everything that D does is different enough that it's almost a non-issue.

You'd actually probably have a hard time trying to come up with a feature to introduce to the language which would be valid C but have different behavior in D than C. The common stuff is the really basic stuff like arithmetic and pointers, which isn't really where you're going to be adding features. The only issue with it really is that there are a few rough edges in C with regards to arithmetic. Anyone looking for a drastically different way of handling math between different integer types, for instance, is going to be out of luck. But there's not much beyond that which is strictly compatible with C. D is just too different from C for that small amount of compatibility to be much of an issue. It does crop up periodically but not often, and it's a whole world of difference from how C++ treats compatibility with C.

- Jonathan M Davis
August 09, 2011
> On 8/9/2011 3:04 PM, Jonathan M Davis wrote:
> > Hmmm. It seems to me that the question is whether anyone would ever _intentially_ use this behavior. Is there any benefit to it whatsoever? If not, I'd argue that the risk of breakage to C code being ported over is minimal and that the behavior should be fixed in D. Now, if there _is_ a benefit to it such that someone would use it intentionally, then that's another story, but it sure likes like the only reason that it would occur in C code would be because the programmer who wrote it screwed up.
> > 
> > Now, that's still going to change the behavior of any code which used this behavior - even if it was by accident - which risks making code fail to work even if it only worked through a miracle before (i.e. in spite of the bug). So, maybe that's enough that we can't fix it. But it sure seems like the risk of new breakage is very low, since code whose behavior would change was broken in the first place, and I'd hate to see D's behavior stay like this if we can fix it.
> 
> I don't see why it's a miracle that s>>1 would yield an int result.
> 
> Do any of the C lints flag this as a bad practice?

Then I'm misunderstanding something here. It was my understanding that this was yielding results which pretty much any programmer would consider incorrect or undesirable. As such, when this issue pops up, it yields an incorrect result, so the code is broken, and if it works, it's because something else gets around the issue (hence the miracle). If this isn't actually yielding effectively incorrect results, then it's a different issue entirely.

So, I'm obviously misunderstanding exactly what the issue is - probably at least in part because I rarely need to use bitshifts.

- Jonathan M Davis
August 09, 2011
Jonathan M Davis wrote:
> Walter Bright wrote:
>> On 8/9/2011 3:04 PM, Jonathan M Davis wrote:
>> > Hmmm. It seems to me that the question is whether anyone would ever _intentially_ use this behavior. Is there any benefit to it whatsoever? If not, I'd argue that the risk of breakage to C code being ported over is minimal and that the behavior should be fixed in D. Now, if there _is_ a benefit to it such that someone would use it intentionally, then that's another story, but it sure likes like the only reason that it would occur in C code would be because the programmer who wrote it screwed up.
>> >
>> > Now, that's still going to change the behavior of any code which used this behavior - even if it was by accident - which risks making code fail to work even if it only worked through a miracle before (i.e. in spite of the bug). So, maybe that's enough that we can't fix it. But it sure seems like the risk of new breakage is very low, since code whose behavior would change was broken in the first place, and I'd hate to see D's behavior stay like this if we can fix it.
>>
>> I don't see why it's a miracle that s>>1 would yield an int result.
>>
>> Do any of the C lints flag this as a bad practice?
>
> Then I'm misunderstanding something here. It was my understanding that this >
was yielding results which pretty much any programmer would consider
> incorrect or undesirable. As such, when this issue pops up, it yields an incorrect
> result, so the code is broken, and if it works, it's because something else
> gets around the issue (hence the miracle). If this isn't actually yielding
> effectively incorrect results, then it's a different issue entirely.
>
> So, I'm obviously misunderstanding exactly what the issue is - probably at least in part because I rarely need to use bitshifts.
>
> - Jonathan M Davis

I think what can be surprising is that s >>> 1 sign-extends s prior to the unsigned right shift.

void main() {
    short s=-1;
    assert(s>>>1 == 2147483647);
    s=-1;
    s>>>=1;
    writeln(s == 32767);
}


August 09, 2011
On Wed, 10 Aug 2011 01:36:58 +0300, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> ??? One of the rules of language design that Walter has stuck to throughout
> the development of D is that if you take any C or C++ code and try to compile
> it as D code, it will either fail to compile, or it will compile with the same
> behavior as the code would have had in C or C++. This is so that you don't
> silently introduce bugs when porting code from C or C++ to D.

I like Walter's ideas on language design and his analysis on other languages, this is not one of them. I don't understand what purpose it does serve.

> There's _lots_ of stuff in D that isn't valid C code, and there's plenty of
> stuff in C which isn't valid D code. Saying that C/C++ code must either be
> valid D code with the same behavior or not compile is not particularly
> restrictive on the whole.

You are missing the point. You'd be right if D being C like was a strange consequence (we did everything as it should be done, did not repeat other languages mistakes, funny enough a C code compiles like it is a D code) rather than the result of some restriction (which would have only one outcome) in design.

> It's really only an issue with some arithmetic
> stuff. D is free to add additional restrictions (such as requiring casts for
> narrowing conversions), and it can do whatever it wants which is different
> from C as long as it isn't valid C - and almost everything that D does is
> different enough that it's almost a non-issue.

Free to add but on what criteria?

> You'd actually probably have a hard time trying to come up with a feature to
> introduce to the language which would be valid C but have different behavior
> in D than C. The common stuff is the really basic stuff like arithmetic and
> pointers, which isn't really where you're going to be adding features.

Funny enough it wouldn't be that hard find, my first appearance in this list was exactly on this issue.
Remember there was no templates in C, and C numerics was designed for that environment which is far from D.

Separation would be great help but i am afraid it is getting late for D. We know the consensus for major changes, especially at this stage.
August 10, 2011
On Aug 10, 11 01:06, Walter Bright wrote:
> On 8/9/2011 2:46 AM, Don wrote:
>> From a discussion on D.learn.
>>
>> If x and y are different integral types, then in an expression like
>> x >> y
>> the integral promotion rules are applied to x and y.
>> This behaviour is obviously inherited from C, but why did C use such a
>> counter-intuitive and bug-prone rule?
>> Why isn't typeof(x >> y) simply typeof(x) ?
>> What would break if it did?
>>
>> You might think the the rule is that typeof( x >> y) is typeof( x + y),
>> but it isn't: the arithmetic conversions are NOT applied:
>> typeof(int >> long) is int, not long, BUT
>> typeof(short >> int) is int.
>> And we have this death trap (bug 2809):
>>
>> void main()
>> {
>> short s = -1;
>> ushort u = s;
>> assert( u == s );
>> assert ( (s >>> 1) == (u >>> 1) ); // FAILS
>> }
>
>
> That last is why we can't just change the behavior from C.

Does C or C++ even have a '>>>' operator? If we need to have a type-promotion rule like C, it could be made as

    x >>> y   ==  cast(promoted type) cast(typeof(x)) (unsigned(x) >> y)

e.g.

    cast(short)(-1) >>> 1  == 0x7f.