www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Numeric limits tracking

reply Manu <turkeyman gmail.com> writes:
--00151757720a102b3e04dc8e35e8
Content-Type: text/plain; charset=UTF-8

So, here's an issue that constantly drives me nuts, and an elegant solution
seems so do-able.

void func(int x)
{
  x &= 0xFFFF;
  short s = x; // Error! (but we know x is 0 .. 65535)

  if(x < 256)
  {
    byte b = x; // Error! (we also know x is 0 .. 255)
  }
}

It would be really nice if the compiler would carry around the known
possible range of values, and refer to that information when performing
down-casting assignments.
It would also be very useful information for the back end, it can choose
more efficient types if it knows the range, or produce jump tables rather
than branch sequences.

I think the compiler would need a min, max, and mask for any integers, and
update them as it works.

There are many sources of this information.
Comparisons effectively limit the range:
if(x > 0)
{
  // x = 0 .. int.max
}
else
{
  // x = int.min .. -1
}

Masks, obviously:
x &= 15;

Also contracts are a really great source of seeding this information on
function entry.

Has this been discussed? It seems simple, and it's invisible to the
language. It would just reduce some boilerplate (tedious casts), and also
offer some great optimisation opportunities.

--00151757720a102b3e04dc8e35e8
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">So, here&#39;s an issue that constantly drives me nuts, an=
d an elegant solution seems so do-able.<div><br></div><div style>void func(=
int x)</div><div style>{</div><div style>=C2=A0 x &amp;=3D 0xFFFF;</div><di=
v style>
=C2=A0 short s =3D x; // Error! (but we know x is 0 .. 65535)</div><div sty=
le><br></div><div style>=C2=A0 if(x &lt; 256)</div><div style>=C2=A0 {</div=
<div style>=C2=A0 =C2=A0 byte b =3D x; // Error! (we also know x is 0 .. 2=

<div style>}</div><div style><br></div><div style>It would be really nice i= f the compiler would carry around the known possible range of values, and r= efer to that information when performing down-casting assignments.<br></div=

n choose more efficient types if it knows the range, or produce jump tables= rather than branch sequences.</div><div style><br></div><div style>I think= the compiler would need a min, max, and mask for any integers, and update = them as it works.</div> <div style><br></div><div style>There are many sources of this information.= </div><div style>Comparisons effectively limit the range:<br></div><div sty= le>if(x &gt; 0)</div><div style>{</div><div style>=C2=A0 // x =3D 0 .. int.= max</div> <div style>}</div><div style>else</div><div style>{</div><div style>=C2=A0 = // x =3D int.min .. -1</div><div style>}</div><div style><br></div><div sty= le>Masks, obviously:</div><div style>x &amp;=3D 15;</div><div style><br></d= iv><div style> Also contracts are a really great source of seeding this information on fun= ction entry.</div><div style><br></div><div style>Has this been discussed? = It seems simple, and it&#39;s invisible to the language. It would just redu= ce some boilerplate (tedious casts), and also offer some great optimisation= opportunities.</div> </div> --00151757720a102b3e04dc8e35e8--
May 12 2013
next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 13 May 2013 at 00:00:54 UTC, Manu wrote:
 So, here's an issue that constantly drives me nuts, and an 
 elegant solution
 seems so do-able.

 void func(int x)
 {
   x &= 0xFFFF;
   short s = x; // Error! (but we know x is 0 .. 65535)

   if(x < 256)
   {
     byte b = x; // Error! (we also know x is 0 .. 255)
   }
 }

 It would be really nice if the compiler would carry around the 
 known
 possible range of values, and refer to that information when 
 performing
 down-casting assignments.
 It would also be very useful information for the back end, it 
 can choose
 more efficient types if it knows the range, or produce jump 
 tables rather
 than branch sequences.

 I think the compiler would need a min, max, and mask for any 
 integers, and
 update them as it works.

 There are many sources of this information.
 Comparisons effectively limit the range:
 if(x > 0)
 {
   // x = 0 .. int.max
 }
 else
 {
   // x = int.min .. -1
 }

 Masks, obviously:
 x &= 15;

 Also contracts are a really great source of seeding this 
 information on
 function entry.

 Has this been discussed? It seems simple, and it's invisible to 
 the
 language. It would just reduce some boilerplate (tedious 
 casts), and also
 offer some great optimisation opportunities.

I've been thinking about this for a while from an optimisation point of view. Is this not a common practice for an optimising compiler?
May 12 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--00151757710cc0129f04dc8e9fa1
Content-Type: text/plain; charset=UTF-8

It is, but there are limits to what it can do.
D's contracts potentially offer a lot of information that the optimiser
wouldn't naturally have (any function receiving blind arguments can't make
any assumptions without a contract present), but more from a
usability/safety point of view, I really hate casting when the compiler
should know the assignment is safe.

It's not only an inconvenience, it's also a safety thing.
Consider:
I have an int that I assign to a byte, I know the value fits in a byte, but
I'm forced to type the manual cast anyway.
Once that cast is written, if the valid range of my int happens to change
in outer code, I will not receive an error informing me that the new range
doesn't fit within a byte anymore, it'll just truncate it anyway, since a
blind cast is already there in the code.
It would be much better for the compiler to start complaining that it can
no longer assure that the int fits into the byte. With the cast present, my
bug has been hidden until I eventually crash.


On 13 May 2013 10:18, John Colvin <john.loughran.colvin gmail.com> wrote:

 On Monday, 13 May 2013 at 00:00:54 UTC, Manu wrote:

 So, here's an issue that constantly drives me nuts, and an elegant
 solution
 seems so do-able.

 void func(int x)
 {
   x &= 0xFFFF;
   short s = x; // Error! (but we know x is 0 .. 65535)

   if(x < 256)
   {
     byte b = x; // Error! (we also know x is 0 .. 255)
   }
 }

 It would be really nice if the compiler would carry around the known
 possible range of values, and refer to that information when performing
 down-casting assignments.
 It would also be very useful information for the back end, it can choose
 more efficient types if it knows the range, or produce jump tables rather
 than branch sequences.

 I think the compiler would need a min, max, and mask for any integers, and
 update them as it works.

 There are many sources of this information.
 Comparisons effectively limit the range:
 if(x > 0)
 {
   // x = 0 .. int.max
 }
 else
 {
   // x = int.min .. -1
 }

 Masks, obviously:
 x &= 15;

 Also contracts are a really great source of seeding this information on
 function entry.

 Has this been discussed? It seems simple, and it's invisible to the
 language. It would just reduce some boilerplate (tedious casts), and also
 offer some great optimisation opportunities.

I've been thinking about this for a while from an optimisation point of view. Is this not a common practice for an optimising compiler?

--00151757710cc0129f04dc8e9fa1 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">It is, but there are limits to what it can do.<div>D&#39;s= contracts potentially offer a lot of information that the optimiser wouldn= &#39;t naturally have (any function receiving blind arguments can&#39;t mak= e any assumptions without a contract present), but more from a usability/sa= fety point of view, I really hate casting when the compiler should know the= assignment is safe.</div> <div style><br></div><div style>It&#39;s not only an inconvenience, it&#39;= s also a safety thing.</div><div style>Consider:</div><div style>I have an = int that I assign to a byte, I know the value fits in a byte, but I&#39;m f= orced to type the manual cast anyway.</div> <div style>Once that cast is written, if the valid range of my int happens = to change in outer code, I will not receive an error informing me that the = new range doesn&#39;t fit within a byte anymore, it&#39;ll just truncate it= anyway, since a blind cast is already there in the code.</div> <div style>It would be much better for the compiler to start complaining th= at it can no longer assure that the int fits into the byte. With the cast p= resent, my bug has been hidden until I eventually crash.</div></div><div cl= ass=3D"gmail_extra"> <br><br><div class=3D"gmail_quote">On 13 May 2013 10:18, John Colvin <span = dir=3D"ltr">&lt;<a href=3D"mailto:john.loughran.colvin gmail.com" target=3D= "_blank">john.loughran.colvin gmail.com</a>&gt;</span> wrote:<br><blockquot= e class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc sol= id;padding-left:1ex"> <div class=3D"HOEnZb"><div class=3D"h5">On Monday, 13 May 2013 at 00:00:54 = UTC, Manu wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> So, here&#39;s an issue that constantly drives me nuts, and an elegant solu= tion<br> seems so do-able.<br> <br> void func(int x)<br> {<br> =C2=A0 x &amp;=3D 0xFFFF;<br> =C2=A0 short s =3D x; // Error! (but we know x is 0 .. 65535)<br> <br> =C2=A0 if(x &lt; 256)<br> =C2=A0 {<br> =C2=A0 =C2=A0 byte b =3D x; // Error! (we also know x is 0 .. 255)<br> =C2=A0 }<br> }<br> <br> It would be really nice if the compiler would carry around the known<br> possible range of values, and refer to that information when performing<br> down-casting assignments.<br> It would also be very useful information for the back end, it can choose<br=

r> than branch sequences.<br> <br> I think the compiler would need a min, max, and mask for any integers, and<= br> update them as it works.<br> <br> There are many sources of this information.<br> Comparisons effectively limit the range:<br> if(x &gt; 0)<br> {<br> =C2=A0 // x =3D 0 .. int.max<br> }<br> else<br> {<br> =C2=A0 // x =3D int.min .. -1<br> }<br> <br> Masks, obviously:<br> x &amp;=3D 15;<br> <br> Also contracts are a really great source of seeding this information on<br> function entry.<br> <br> Has this been discussed? It seems simple, and it&#39;s invisible to the<br> language. It would just reduce some boilerplate (tedious casts), and also<b= r> offer some great optimisation opportunities.<br> </blockquote> <br></div></div> I&#39;ve been thinking about this for a while from an optimisation point of= view. Is this not a common practice for an optimising compiler?<br> </blockquote></div><br></div> --00151757710cc0129f04dc8e9fa1--
May 12 2013
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 5/12/2013 5:00 PM, Manu wrote:
 So, here's an issue that constantly drives me nuts, and an elegant solution
 seems so do-able.

It's a form of "data flow analysis". This is done by the optimizer, although it doesn't track ranges. It isn't quite as simple as you suggest, there are issues like dealing with arbitrary control flow. x &= 0xFFFF; short s = x; // Error! (but we know x is 0 .. 65535) Ok, but what about: x &= 0xFFFF; while (expr) { short s = x; x += 1; } There's a forward reference going on. We cannot semantically evaluate s=x until we semantically evaluate the rest of the function in order to know that x is or is not reassigned.
May 12 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 5/12/2013 6:23 PM, Manu wrote:
 It is done by the optimiser, but I'm suggesting that it doesn't only have value
 in terms of optimisation. It could improve language usability if performed in
 the front end.

I understand.
 In that context, unless the analysis is very powerful(/mature) and can
 statically determine 'expr', then x would need to be relaxed to unlimited at
 that point, since it obviously can't know the limits within (or after) that
loop.
 In this case, the compiler would complain that it can't determine x and you
 would need an explicit cast as usual.

 I can see the effective forward reference issue here, which could be addressed
 in time, but even just reasonably simple limits tracking (ie, within sequential
 code) would make a massive difference. I think programmers would intuitively
 understand this situation and wouldn't expect magic from the compiler.
 The places where it matters the most are places where it's dead obvious what
the
 numeric limits are, and it should be equally obvious to the compiler.

 It's the sort of thing that could be improved with time, but even a very simple
 start would be a big help in many cases.

It's true you could do a sequential only, very conservative form of data flow analysis. But be aware there are other problems, such as: int *p = ...; ... x &= 0xFFFF; ++(*p); // hmm, is x affected? short s = x;
May 12 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 There's a forward reference going on. We cannot semantically 
 evaluate s=x until we semantically evaluate the rest of the 
 function in order to know that x is or is not reassigned.

A first step to improve the situation is to propagate the range of const/immutable values inside a function: void main() { uint x = 1000; immutable y = x % 256; ubyte z = y; // currently error. } Bye, bearophile
May 12 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--047d7bb04d409a351f04dc8f5b68
Content-Type: text/plain; charset=UTF-8

On 13 May 2013 11:03, Walter Bright <newshound2 digitalmars.com> wrote:

 On 5/12/2013 5:00 PM, Manu wrote:

 So, here's an issue that constantly drives me nuts, and an elegant
 solution
 seems so do-able.

It's a form of "data flow analysis". This is done by the optimizer, although it doesn't track ranges. It isn't quite as simple as you suggest, there are issues like dealing with arbitrary control flow. x &= 0xFFFF; short s = x; // Error! (but we know x is 0 .. 65535) Ok, but what about: x &= 0xFFFF; while (expr) { short s = x; x += 1; } There's a forward reference going on. We cannot semantically evaluate s=x until we semantically evaluate the rest of the function in order to know that x is or is not reassigned.

It is done by the optimiser, but I'm suggesting that it doesn't only have value in terms of optimisation. It could improve language usability if performed in the front end. In that context, unless the analysis is very powerful(/mature) and can statically determine 'expr', then x would need to be relaxed to unlimited at that point, since it obviously can't know the limits within (or after) that loop. In this case, the compiler would complain that it can't determine x and you would need an explicit cast as usual. I can see the effective forward reference issue here, which could be addressed in time, but even just reasonably simple limits tracking (ie, within sequential code) would make a massive difference. I think programmers would intuitively understand this situation and wouldn't expect magic from the compiler. The places where it matters the most are places where it's dead obvious what the numeric limits are, and it should be equally obvious to the compiler. It's the sort of thing that could be improved with time, but even a very simple start would be a big help in many cases. --047d7bb04d409a351f04dc8f5b68 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 13 May 2013 11:03, Walter Bright <span dir=3D"ltr">&lt;= <a href=3D"mailto:newshound2 digitalmars.com" target=3D"_blank">newshound2 = digitalmars.com</a>&gt;</span> wrote:<br><div class=3D"gmail_extra"><div cl= ass=3D"gmail_quote"> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"><div class=3D"im">On 5/12/2013 5:00 PM, Manu= wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> So, here&#39;s an issue that constantly drives me nuts, and an elegant solu= tion<br> seems so do-able.<br> </blockquote> <br></div> It&#39;s a form of &quot;data flow analysis&quot;. This is done by the opti= mizer, although it doesn&#39;t track ranges.<br> <br> It isn&#39;t quite as simple as you suggest, there are issues like dealing = with arbitrary control flow.<div class=3D"im"><br> <br> =C2=A0 x &amp;=3D 0xFFFF;<br> =C2=A0 short s =3D x; // Error! (but we know x is 0 .. 65535)<br> <br></div> Ok, but what about:<br> <br> =C2=A0 x &amp;=3D 0xFFFF;<br> =C2=A0 while (expr) {<br> =C2=A0 =C2=A0 =C2=A0 short s =3D x;<br> =C2=A0 =C2=A0 =C2=A0 x +=3D 1;<br> =C2=A0 }<br> <br> There&#39;s a forward reference going on. We cannot semantically evaluate s= =3Dx until we semantically evaluate the rest of the function in order to kn= ow that x is or is not reassigned.<br> </blockquote></div><br></div><div class=3D"gmail_extra" style>It is done by= the optimiser, but I&#39;m suggesting that it doesn&#39;t only have value = in terms of optimisation. It could improve language usability if performed = in the front end.</div> <div class=3D"gmail_extra" style><br></div><div class=3D"gmail_extra" style=
In that context, unless the analysis is very powerful(/mature) and can sta=

ted at that point, since it obviously can&#39;t know the limits within (or = after) that loop.</div> <div class=3D"gmail_extra" style>In this case, the compiler would complain = that it can&#39;t determine x and you would need an explicit cast as usual.= </div><div class=3D"gmail_extra" style><br></div><div class=3D"gmail_extra"= style> I can see the effective forward reference issue here, which could be addres= sed in time, but even just reasonably simple limits tracking (ie, within se= quential code) would make a massive difference. I think programmers would i= ntuitively understand this situation and wouldn&#39;t expect magic from the= compiler.</div> <div class=3D"gmail_extra" style>The places where it matters the most are p= laces where it&#39;s dead obvious what the numeric limits are, and it shoul= d be equally obvious to the compiler.</div><div class=3D"gmail_extra" style=

could be improved with time, but even a very simple start would be a big he= lp in many cases.</div></div> --047d7bb04d409a351f04dc8f5b68--
May 12 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--089e0118413e61502904dc91e899
Content-Type: text/plain; charset=UTF-8

On 13 May 2013 13:46, Walter Bright <newshound2 digitalmars.com> wrote:

 On 5/12/2013 6:23 PM, Manu wrote:

 It is done by the optimiser, but I'm suggesting that it doesn't only have
 value
 in terms of optimisation. It could improve language usability if
 performed in
 the front end.

I understand. In that context, unless the analysis is very powerful(/mature) and can
 statically determine 'expr', then x would need to be relaxed to unlimited
 at
 that point, since it obviously can't know the limits within (or after)
 that loop.
 In this case, the compiler would complain that it can't determine x and
 you
 would need an explicit cast as usual.

 I can see the effective forward reference issue here, which could be
 addressed
 in time, but even just reasonably simple limits tracking (ie, within
 sequential
 code) would make a massive difference. I think programmers would
 intuitively
 understand this situation and wouldn't expect magic from the compiler.
 The places where it matters the most are places where it's dead obvious
 what the
 numeric limits are, and it should be equally obvious to the compiler.

 It's the sort of thing that could be improved with time, but even a very
 simple
 start would be a big help in many cases.

It's true you could do a sequential only, very conservative form of data flow analysis. But be aware there are other problems, such as: int *p = ...; ... x &= 0xFFFF; ++(*p); // hmm, is x affected? short s = x;

Yes indeed, there are certainly many ways to interfere with it, but I certainly hope that most lines of code you deal with on a daily basis aren't like this ;) Obviously it would grow in maturity over time. In that example, just revert to unlimited assumptions when it encounters the pointer operation. Limits may then be refined again in following code. I can imagine things like proper escaping analysis as planned could eventually help in cases like this. Anyway, it's just something to think about. I think it would offer additional safety/correctness to the language; anywhere you type a blind cast, you are potentially hiding a future bug. I'd rather never cast when I don't absolutely need/intend to. --089e0118413e61502904dc91e899 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 13 May 2013 13:46, Walter Bright <span dir=3D"ltr">&lt;= <a href=3D"mailto:newshound2 digitalmars.com" target=3D"_blank">newshound2 = digitalmars.com</a>&gt;</span> wrote:<br><div class=3D"gmail_extra"><div cl= ass=3D"gmail_quote"> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"><div class=3D"im">On 5/12/2013 6:23 PM, Manu= wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> It is done by the optimiser, but I&#39;m suggesting that it doesn&#39;t onl= y have value<br> in terms of optimisation. It could improve language usability if performed = in<br> the front end.<br> </blockquote> <br></div> I understand.<div class=3D"im"><br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> In that context, unless the analysis is very powerful(/mature) and can<br> statically determine &#39;expr&#39;, then x would need to be relaxed to unl= imited at<br> that point, since it obviously can&#39;t know the limits within (or after) = that loop.<br> In this case, the compiler would complain that it can&#39;t determine x and= you<br> would need an explicit cast as usual.<br> <br> I can see the effective forward reference issue here, which could be addres= sed<br> in time, but even just reasonably simple limits tracking (ie, within sequen= tial<br> code) would make a massive difference. I think programmers would intuitivel= y<br> understand this situation and wouldn&#39;t expect magic from the compiler.<= br> The places where it matters the most are places where it&#39;s dead obvious= what the<br> numeric limits are, and it should be equally obvious to the compiler.<br> <br> It&#39;s the sort of thing that could be improved with time, but even a ver= y simple<br> start would be a big help in many cases.<br> </blockquote> <br></div> It&#39;s true you could do a sequential only, very conservative form of dat= a flow analysis.<br> <br> But be aware there are other problems, such as:<br> <br> =C2=A0 int *p =3D ...;<br> =C2=A0 ...<br> =C2=A0 x &amp;=3D 0xFFFF;<br> =C2=A0 ++(*p); =C2=A0 =C2=A0 =C2=A0// hmm, is x affected?<br> =C2=A0 short s =3D x;<br></blockquote><div><br></div><div style>Yes indeed,= there are certainly many ways to interfere with it, but I certainly hope t= hat most lines of code you deal with on a daily basis aren&#39;t like this = ;)</div> <div style>Obviously it would grow in maturity over time. In that example, = just revert to unlimited assumptions when it encounters the pointer operati= on. Limits may then be refined again in following code.</div><div style> I can imagine things like proper escaping analysis as planned could eventua= lly help in cases like this.</div><div style><br></div><div style>Anyway, i= t&#39;s just something to think about. I think it would offer additional sa= fety/correctness to the language; anywhere you type a blind cast, you are p= otentially hiding a future bug. I&#39;d rather never cast when I don&#39;t = absolutely need/intend to.</div> </div></div></div> --089e0118413e61502904dc91e899--
May 12 2013
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Monday, 13 May 2013 at 00:00:54 UTC, Manu wrote:
 Has this been discussed? It seems simple, and it's invisible to 
 the language.

There is no such thing as a language feature invisible to the language – or at least there should not be. Even a feature, such as this, which only makes the language more permissive needs exact specifications, for all D compilers have to implement it in the same way. David
May 13 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Monday, 13 May 2013 at 12:37:34 UTC, David Nadlinger wrote:
 On Monday, 13 May 2013 at 00:00:54 UTC, Manu wrote:
 Has this been discussed? It seems simple, and it's invisible 
 to the language.

There is no such thing as a language feature invisible to the language – or at least there should not be. Even a feature, such as this, which only makes the language more permissive needs exact specifications, for all D compilers have to implement it in the same way. David

is(typeof()) say that any permissive change can also break code in D. This is our little specificity ;)
May 13 2013
prev sibling next sibling parent Marco Leise <Marco.Leise gmx.de> writes:
Am Mon, 13 May 2013 10:00:40 +1000
schrieb Manu <turkeyman gmail.com>:

 So, here's an issue that constantly drives me nuts, and an elegant solution
 seems so do-able.
 
 void func(int x)
 {
   x &= 0xFFFF;
   short s = x; // Error! (but we know x is 0 .. 65535)
 
   if(x < 256)
   {
     byte b = x; // Error! (we also know x is 0 .. 255)
   }
 }

Yes, I came across that one every so often myself. But as David pointed out, such a feature would have to make it into the D specification and implemented in all D compilers. In any case I wouldn't call a half-baked "I will solve the halting problem" flow-analysis elegant. :p Let's think different. You could write short s = x & 0xFFFF; on your first line, as you may already know DMD does this bit of range analysis (same for modulo). Also what was your intention? func() practically takes a short parameter. Maybe it's signature should be void func(short x) {...} If that's a problem on the calling site, maybe that can be fixed? bearophile's suggestion sounds like something that's pretty solid and naturally extends the likes of "short s = x & 0xFFF;" So if your "int x" was immutable it would really be trivial to have your "if" change the range of immutable x during that scope and have the assignment only fail because x may be -1000. ;) -- Marco
May 15 2013
prev sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Thu, 16 May 2013 07:34:18 +0200, Marco Leise <Marco.Leise gmx.de> wrote:

 Am Mon, 13 May 2013 10:00:40 +1000
 schrieb Manu <turkeyman gmail.com>:

 void func(int x)
 {
   x &= 0xFFFF;
   short s = x; // Error! (but we know x is 0 .. 65535)

   if(x < 256)
   {
     byte b = x; // Error! (we also know x is 0 .. 255)
   }
 }


 Also what was your intention? func() practically takes a short
 parameter. Maybe it's signature should be
     void func(short x) {...}
 If that's a problem on the calling site, maybe that can be
 fixed?

I believe the intention was to show an issue with the language, not to make a function that assigns to a short and a byte only to throw them away. Perhaps he needed to do some intermediate calculations at higher precision, perhaps he needs it to be an int for interfacing with a C function, etc. -- Simen
May 16 2013