June 23, 2014
> I think that unfortunately this currently can't work, you can't tell the range of the input value like that. I have explained why in one of my posts in this thread. Please try to explain me why I'm wrong.

I'm currently merely talking about possibilities in this case, so I cannot currently prove you wronge ;) To me it seem like an unneccessary limitation that valueRanges aren't propagated to function call arguments provided that the function source is known at compile time. And it doesn't sound to me like enabling this in DMD would be such a great task either.
June 23, 2014
""Nordlöw""  wrote in message news:jctlkqtiztnbnctldtdg@forum.dlang.org...

> I'm currently merely talking about possibilities in this case, so I cannot currently prove you wronge ;) To me it seem like an unneccessary limitation that valueRanges aren't propagated to function call arguments provided that the function source is known at compile time. And it doesn't sound to me like enabling this in DMD would be such a great task either.

What happens when a function is called from different places with values with different ranges?  What about when it's called from another compilation unit?  Generally the argument ranges can only be known when the function is inlined, and by then it's much too late to expose them via __traits. 

June 23, 2014
Daniel Murphy:

> What happens when a function is called from different places with values with different ranges?  What about when it's called from another compilation unit?

One solution is to ignore such cases, so that feature gives useful results only when the source is compiled in the same compilation unit.

An alternative solution is to handle the functions that use those features like templates, and keep the source available across different compilation units. This is perhaps acceptable because I think that kind of features is going to be used mostly for library code and not for most user functions.

Bye,
bearophile
June 23, 2014
On Monday, 23 June 2014 at 12:51:58 UTC, Daniel Murphy wrote:
> What happens when a function is called from different places with values with different ranges?  What about when it's called from another compilation unit?  Generally the argument ranges can only be known when the function is inlined, and by then it's much too late to expose them via __traits.

Ok. That indeed makes things more complicated than I first thought :|
June 23, 2014
On Monday, 23 June 2014 at 13:13:38 UTC, bearophile wrote:
> One solution is to ignore such cases, so that feature gives useful results only when the source is compiled in the same compilation unit.
>
> An alternative solution is to handle the functions that use those features like templates, and keep the source available across different compilation units. This is perhaps acceptable because I think that kind of features is going to be used mostly for library code and not for most user functions.

That is certainly a good idea.
June 24, 2014
On 2014-06-23 13:13:37 +0000, bearophile said:

> Daniel Murphy:
> 
>> What happens when a function is called from different places with values with different ranges?  What about when it's called from another compilation unit?
> 
> One solution is to ignore such cases, so that feature gives useful results only when the source is compiled in the same compilation unit.
> 
> An alternative solution is to handle the functions that use those features like templates, and keep the source available across different compilation units. This is perhaps acceptable because I think that kind of features is going to be used mostly for library code and not for most user functions.
> 
> Bye,
> bearophile

Wouldn't that cause compiler errors that only happen depending on what order you compile things?

-Shammah

June 24, 2014
Shammah Chancellor:

> Wouldn't that cause compiler errors that only happen depending on what order you compile things?

If you refer to the first "solution", then the answer is yes. The ability to catch bugs at compile-time is not fully deterministic, it's a help for the programmer, but it's not always possible. This is why when you use a enum precondition you also have to add a regular pre-condition too.

If you refer to the second "solution" then I think the answer is no, because your problems doesn't currently happen with templates.

Bye,
bearophile
June 27, 2014
On 23/06/14 04:51, "Nordlöw" wrote:
>> That will only work now if you use an "else".
>
> So you mean something like
>
>       if(x<byte.min || x>byte.max)
>           throw new InvalidArgumentException("...
>       else {}
>
> ?
>
> That seems like a strange restriction. Why is that?

I meant, else return x;

Because it's easy to see what the value of x is within the if and else body. It's not trivial to find out that the if body never exits (because of the throw) and therefor the code after the if is in essence the else body.

L.
June 30, 2014
Latest [1] now also supports CTFE:

    const i = foo ? -1 : 33;

    if (i)
      static assert(__traits(intrange, i) == Tuple!(-1, 33));
    else
    {
      static assert(i == 0); // Works now!
      static assert(__traits(intrange, i) == Tuple!(0, 0));
    }

    if (i == 33)
    {
      static assert(i == 33); // Works now!
      static assert(__traits(intrange, i) == Tuple!(33, 33));
    }
    else
      static assert(__traits(intrange, i) == Tuple!(-1, 32));


Next up: support for immutable/const members and "if (i) static assert(i)"

L.

[1] https://github.com/lionello/dmd/tree/if-else-range
July 01, 2014
On 18 June 2014 16:40, Lionello Lunesu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> Hi,
>
> I got this thing working and I think it's about time I get some comments on it.
>
> I've been wanting to extend Value Rang Propagation (VRE) for some time now. Mostly because of the fix to the troublesome "signed-unsigned comparisons" issue. Enabling VRE for if-else and "&&" will fix many of the false-positive warnings given out by the fix to bug 259 by allowing code like this: if (signed > 0 && signed < unsigned) { .. }
>
> Have a look at the branch: https://github.com/lionello/dmd/compare/if-else-range
>
> There, I've also added a __traits(intrange, <expression>) which returns a tuple with the min and max for the given expression. It's used in the test case as follows:
>
>
>     const i = foo ? -1 : 33;
>
>     if (i)
>       static assert(__traits(intrange, i) == Tuple!(-1, 33));
>     else
>     {
>       //static assert(i == 0); TODO
>       static assert(__traits(intrange, i) == Tuple!(0, 0));
>     }
>
>     if (i == 33)
>     {
>       //static assert(i == 33); TODO
>       static assert(__traits(intrange, i) == Tuple!(33, 33));
>     }
>     else
>       static assert(__traits(intrange, i) == Tuple!(-1, 32));
>
>     if (10 <= i)
>       static assert(__traits(intrange, i) == Tuple!(10, 33));
>     else
>       static assert(__traits(intrange, i) == Tuple!(-1, 9));
>
>
> It would be nice if this can be used by CTFE as well.
>
> Destroy?

I'm looking forward to this so hard!
The one time I've attempted to hack on DMD, it was to investigate the
idea of doing this.

As others said, I think a key use case is for contracts/preconditions. Also eliminating annoying warnings when down-casting.

I suspect there are many great optimisation opportunities available too when this is pervasive. switch() may gain a lot of great information to work with! :)