November 12, 2017
On Sunday, 12 November 2017 at 16:00:28 UTC, Ola Fosheim Grøstad wrote:
> On Sunday, 12 November 2017 at 13:34:50 UTC, Dmitry Olshansky wrote:
>> if (a & (flag1 | flag2))
>>
>> to
>>
>> if ((a & (flag1 | flag2)) != 0)
>>
>> When the first is quite obvious.
>
> Just change the typing of the if-conditional to:
>
> if (boolean|integral) {…}

Rather I recall that:
if(expr)
is considered to be
if(cast(bool)expr)

The latter to support user-defined types.
So we are good.
November 12, 2017
On Sunday, November 12, 2017 19:13:00 Dmitry Olshansky via Digitalmars-d wrote:
> On Sunday, 12 November 2017 at 16:00:28 UTC, Ola Fosheim Grøstad
>
> wrote:
> > On Sunday, 12 November 2017 at 13:34:50 UTC, Dmitry Olshansky
> >
> > wrote:
> >> if (a & (flag1 | flag2))
> >>
> >> to
> >>
> >> if ((a & (flag1 | flag2)) != 0)
> >>
> >> When the first is quite obvious.
> >
> > Just change the typing of the if-conditional to:
> >
> > if (boolean|integral) {…}
>
> Rather I recall that:
> if(expr)
> is considered to be
> if(cast(bool)expr)
>
> The latter to support user-defined types.
> So we are good.

Yes. In conditional expressions, you get an implicitly inserted cast to bool. So, you have an implicit, explicit cast to bool (weird as that sounds). If the implicit cast to integers to bool were removed (meaning neither integer literals nor VRP allowed the conversion), then it would have no effect on if statements or loops and whatnot. It would affect overloading and other expressions. So, something like

bool a = 2 - 1;

or

auto foo(bool) {...}
foo(1);

wouldn't compile anymore. But something like

if(1)

would compile just fine, just like

if("str")

compiles just fine, but

auto foo(bool) {...}
foo("str");

does not.

- Jonathan M Davis


November 12, 2017
On Sunday, 12 November 2017 at 16:57:05 UTC, Andrei Alexandrescu wrote:

> A DIP could be formulated to only address the problem at hand. BTW, here's a really fun example:
>
> void fun(long) { assert(0); }
> void fun(bool) {}
>
> enum int a = 2;
> enum int b = 1;
>
> void main()
> {
>     fun(a - b);
> }
>
> The overload being called depends on (a) whether a - b can be computed during compilation or not, and (b) the actual value of a - b. Clearly a big problem for modular code. This is the smoking gun motivating the DIP.

As I understand it, the case above can be solved by changing the overload resolution rules without deprecating the implicit conversion to bool.  A PR for such a fix was submitted here https://github.com/dlang/dmd/pull/1942.

I fear a proposal to deprecate the implicit conversion to bool based solely on the example above could be refused in favor of overload resolution changes.  IMO, the example above, while certainly a smoking gun, is actually just a symptom of the deeper problem, so I tried to make that case in the DIP.

The DIP has been submitted here https://github.com/dlang/DIPs/pull/99

Perhaps I'm not the right person to be formulating these arguments, but given that the issue has been in Bugzilla for 4 years, I'm probably all you've got.  Sorry.

Mike


November 14, 2017
On Saturday, 11 November 2017 at 23:30:18 UTC, Andrei Alexandrescu wrote:
> A DIP is necessary for all language changes. In this case a short and well-argued DIP seems to be the ticket. Walter and I spoke and such a proposal has a good chance to be successful.

Subject issues:
https://issues.dlang.org/show_bug.cgi?id=9999
https://issues.dlang.org/show_bug.cgi?id=10560

Spec in question:
https://dlang.org/spec/type.html#bool

DIP:
https://github.com/dlang/DIPs/pull/99

I need some feedback from the community before I move forward with the DIP.  I'm torn between a few ideas and not sure how to proceed.

1. Deprecate implicit conversion of integer literals to bool
2. Allow implicit conversion of integer literals to bool if a function is not overloaded, but disallow it if the function is overloaded.
3. Change the overload resolution rules as illustrated in https://github.com/dlang/dmd/pull/1942

If I had to choose one I would go with 1, simply because the implicit conversion is janky and circumvents the type system for a mild-at-best convenience.  But, it will cause breakage that needs to be managed.

2 would solve the issues in question, but keep breakage at a minimum, and would probably be preferred if users wish to maintain the status quo.  Disadvantage is it's a special case to document, consider, and explain.

3 is similar to 2, and like 2, is a special case.

I don't even really have a dog in this fight, but the demonstration of the problem in the bugzilla issues is simply embarrassing, and I'm tired of seeing issues languish for so long in bugzilla without any resolution.

Is there any general consensus in the community on this issue so I can be sure I'm fulfilling the community's preference?

Thanks,
Mike
November 14, 2017
On 11/13/17 8:01 PM, Michael V. Franklin wrote:
> On Saturday, 11 November 2017 at 23:30:18 UTC, Andrei Alexandrescu wrote:
>> A DIP is necessary for all language changes. In this case a short and well-argued DIP seems to be the ticket. Walter and I spoke and such a proposal has a good chance to be successful.
> 
> Subject issues:
> https://issues.dlang.org/show_bug.cgi?id=9999
> https://issues.dlang.org/show_bug.cgi?id=10560
> 
> Spec in question:
> https://dlang.org/spec/type.html#bool
> 
> DIP:
> https://github.com/dlang/DIPs/pull/99
> 
> I need some feedback from the community before I move forward with the DIP.  I'm torn between a few ideas and not sure how to proceed.
> 
> 1. Deprecate implicit conversion of integer literals to bool
> 2. Allow implicit conversion of integer literals to bool if a function is not overloaded, but disallow it if the function is overloaded.
> 3. Change the overload resolution rules as illustrated in https://github.com/dlang/dmd/pull/1942
> 
> If I had to choose one I would go with 1, simply because the implicit conversion is janky and circumvents the type system for a mild-at-best convenience.  But, it will cause breakage that needs to be managed.
> 
> 2 would solve the issues in question, but keep breakage at a minimum, and would probably be preferred if users wish to maintain the status quo.  Disadvantage is it's a special case to document, consider, and explain.
> 
> 3 is similar to 2, and like 2, is a special case.
> 
> I don't even really have a dog in this fight, but the demonstration of the problem in the bugzilla issues is simply embarrassing, and I'm tired of seeing issues languish for so long in bugzilla without any resolution.
> 
> Is there any general consensus in the community on this issue so I can be sure I'm fulfilling the community's preference?

My vote would be for 1. It's disruptive, but not that disruptive.

I almost always initialize a bool with true or false, not with 1 or 0.

The array handling is probably the only part that would be painful. but we could handle that the same way we deprecated octal numbers:

bools!"01001101"; => [false, true, false, false, true, true, false, true];

-Steve
November 14, 2017
On Sunday, 12 November 2017 at 16:57:05 UTC, Andrei Alexandrescu wrote:
> The overload being called depends on (a) whether a - b can be computed during compilation or not, and (b) the actual value of a - b. Clearly a big problem for modular code. This is the smoking gun motivating the DIP.

An very similar problem exists for int and char overloads:

alias foo = (char c) => 1;
alias foo = (int i) => 4;

enum int e = 7;
static assert(foo(e) == 4); // fails

November 14, 2017
On 11/14/17 8:20 AM, Nick Treleaven wrote:
> On Sunday, 12 November 2017 at 16:57:05 UTC, Andrei Alexandrescu wrote:
>> The overload being called depends on (a) whether a - b can be computed during compilation or not, and (b) the actual value of a - b. Clearly a big problem for modular code. This is the smoking gun motivating the DIP.
> 
> An very similar problem exists for int and char overloads:
> 
> alias foo = (char c) => 1;
> alias foo = (int i) => 4;
> 
> enum int e = 7;
> static assert(foo(e) == 4); // fails

Thanks. Addressing this should be part of the DIP as well. -- Andrei
November 14, 2017
On Tuesday, 14 November 2017 at 13:32:52 UTC, Andrei Alexandrescu wrote:

>> An very similar problem exists for int and char overloads:
>> 
>> alias foo = (char c) => 1;
>> alias foo = (int i) => 4;
>> 
>> enum int e = 7;
>> static assert(foo(e) == 4); // fails
>
> Thanks. Addressing this should be part of the DIP as well. --

It doesn't appear to be related to the implicit conversion of integer literals to bool.  While Andrei's example is fixed by by deprecating implicit conversion of integral literals to bool (at least using this implementation: https://github.com/dlang/dmd/pull/7310), Nick's example isn't.

Nick, if it's not in bugzilla already, can you please add it?

Mike


November 14, 2017
On 11/14/17 8:32 AM, Andrei Alexandrescu wrote:
> On 11/14/17 8:20 AM, Nick Treleaven wrote:
>> On Sunday, 12 November 2017 at 16:57:05 UTC, Andrei Alexandrescu wrote:
>>> The overload being called depends on (a) whether a - b can be computed during compilation or not, and (b) the actual value of a - b. Clearly a big problem for modular code. This is the smoking gun motivating the DIP.
>>
>> An very similar problem exists for int and char overloads:
>>
>> alias foo = (char c) => 1;
>> alias foo = (int i) => 4;
>>
>> enum int e = 7;
>> static assert(foo(e) == 4); // fails
> 
> Thanks. Addressing this should be part of the DIP as well. -- Andrei

IMO, no character types should implicitly convert from integer types. In fact, character types shouldn't convert from ANYTHING (even other character types). We have so many problems with this.

-Steve
November 14, 2017
On Tuesday, 14 November 2017 at 13:43:32 UTC, Michael V. Franklin wrote:

>>> An very similar problem exists for int and char overloads:
>>> 
>>> alias foo = (char c) => 1;
>>> alias foo = (int i) => 4;
>>> 
>>> enum int e = 7;
>>> static assert(foo(e) == 4); // fails
>>
>> Thanks. Addressing this should be part of the DIP as well. --
>
> It doesn't appear to be related to the implicit conversion of integer literals to bool.  While Andrei's example is fixed by by deprecating implicit conversion of integral literals to bool (at least using this implementation: https://github.com/dlang/dmd/pull/7310), Nick's example isn't.

Well, of course it's not related; it's a char not a bool.  But there does seem to be some systematic problems in D's implicit conversion rules.  I'll have to investigate this and perhaps I can address them both in one DIP.

Mike