www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 4733] New: Possible bugs caused by dynamic arrays in boolean evaluation context

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4733

           Summary: Possible bugs caused by dynamic arrays in boolean
                    evaluation context
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: bearophile_hugs eml.cc


--- Comment #0 from bearophile_hugs eml.cc 2010-08-26 14:12:04 PDT ---
In Python it is a normal idiom to test for collection emptiness just putting
their name in a boolean evaluation context (this is an idom valid for all
Python collections):

arr = [1]
assert arr


But in D similar code causes troubles, this differt code shows an example:


void main() {
    int[] arr = [1];
    int* orig_ptr = arr.ptr;
    arr.length = 0;
    assert(!!arr); // this doesn't assert
    assert(arr.ptr == orig_ptr); // this doesn't assert
}


!!arr is true because while arr.length is zero, arr.ptr is not null.

To avoid possible bugs (for example for programmers coming from Python
language) I suggest to turn "if(arr)" into a syntax error, forcing to use
"if(arr.length)" or "if(arr.ptr)" or similar things, and you avoid possible
bugs. In the uncommon cases where you want to test both fields to be empty, you
may use "if(arr.length || arr.ptr)" or "if(arr.length != arr.init)" or similar
things.

The semantics of "if(aa)" and "if(static_arr)", the first tests if the
reference is null, the second if all items are empty.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Aug 26 2010
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4733



--- Comment #1 from bearophile_hugs eml.cc 2012-02-19 04:57:20 PST ---
See also issue 7539

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 19 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4733



--- Comment #2 from bearophile_hugs eml.cc 2013-03-25 15:59:36 PDT ---
I have created a thread about this issue in the main D newsgroup:

http://forum.dlang.org/thread/bwgnbflygowctlisistg forum.dlang.org

It was well received by almost every one. But people are split between just
forbidding "if(dyn_arr)" and turning it into an equivalent of
"if(dyn_arr.length)". Both proposals have advantages and disadvantages.

Both are a little breaking change, but turning something into an error allows
you to find it quickly in most cases inside D code. (But D also has the
compiles __trait, that does not give an error, it just silently returns false
instead of true).

On the other hand the behaviour change is not meant to happen all at once. It
has to be a warning, then deprecation and then a change, along months and three
DMD versions. So there is time to fix old D code. And even if the old D code
doesn't get changed, I think it's uncommon for code to rely on dynamic array to
be actually (null,null) instead of being of zero length. So the total amount of
breakage even for a semantic change is probably small. Considering the presence
of the compiles __trait, the idea of the small behaviour change is not so bad.

In both cases the change path will start at the same way: warning, deprecation,
and then an error or a behavour change). So for now I am asking for a warning
for code like "if(dyn_arr)".

Note that the syntax "if(dyn_arr !is null)" is still allowed.

--------------------

A related issue is what to do with associative arrays:


void main() {
    bool[int] aa;
    assert(!aa);
    aa = [1: true];
    assert(aa);
    aa.remove(1);
    assert(aa);
    assert(!aa.length);
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 25 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4733


Dmitry S <ds.dlang gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ds.dlang gmail.com


--- Comment #3 from Dmitry S <ds.dlang gmail.com> 2013-05-11 21:08:09 PDT ---
I feel that there is an additional bug: "if(slice)" evaluates an empty slice as
true (as does "!!slice"), but "cast(bool)slice" does not compile ("cannot cast
slice to integral type bool").

So somehow, converting arrays to booleans isn't consistently supported, and
when it compiles, the meaning is indeed unintuitive. I agree that if conversion
to booleans is to be supported, then "non-empty" is the best meaning to go for.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 11 2013
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4733



--- Comment #4 from bearophile_hugs eml.cc 2013-09-21 05:19:09 PDT ---
See also issue 11080, that asks to disallow this bug-prone construct:

assert("something going wrong");

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Sep 21 2013