Thread overview
with and shadowing variables
Jul 22, 2018
Anonymouse
Jul 22, 2018
Jonathan M Davis
Jul 23, 2018
Jim Balter
Jul 23, 2018
Jim Balter
Jul 23, 2018
Anonymouse
Jul 23, 2018
baz
Jul 24, 2018
Anonymouse
July 22, 2018
Can this be made a compiler warning?

struct Foo
{
    int i;
}

void main()
{
    Foo foo;

    with (foo)
    {
        i = 42;
        int i;
        i = 24;
    }
}

I'm hesitant to file a bug because it'll just be immediately closed with a link to https://dlang.org/spec/statement.html#WithStatement. I understand that's how it works, but it's weird and weak to human mistakes.
July 22, 2018
On Sunday, July 22, 2018 12:13:43 Anonymouse via Digitalmars-d wrote:
> Can this be made a compiler warning?
>
> struct Foo
> {
>      int i;
> }
>
> void main()
> {
>      Foo foo;
>
>      with (foo)
>      {
>          i = 42;
>          int i;
>          i = 24;
>      }
> }
>
> I'm hesitant to file a bug because it'll just be immediately closed with a link to https://dlang.org/spec/statement.html#WithStatement. I understand that's how it works, but it's weird and weak to human mistakes.

Given the shadowing protections listed in #5, it could certainly be argued that it would be in the spirit of the restrictions that with already has, and I think that there's a pretty clear argument to be made that allowing it is too error-prone, but maybe someone will have a reason why it doesn't make sense to disallow it. I don't know. Regardless, I would suggest that you open an enhancement request. I would guess that it's straightforward enough that a DIP isn't reauired so long as Walter approves of it, but I don't know. Either way, if it's in bugzilla, then it stands a much better chance of happening than if the only record of it is here.

- Jonathan M Davis

July 23, 2018
On Sunday, 22 July 2018 at 12:13:43 UTC, Anonymouse wrote:
> Can this be made a compiler warning?
>
> struct Foo
> {
>     int i;
> }
>
> void main()
> {
>     Foo foo;
>
>     with (foo)
>     {
>         i = 42;
>         int i;
>         i = 24;
>     }
> }
>
> I'm hesitant to file a bug because it'll just be immediately closed with a link to https://dlang.org/spec/statement.html#WithStatement. I understand that's how it works, but it's weird and weak to human mistakes.

Do you have an actual case where it was a problem, as opposed to a contrived example with semantically empty identifiers? I recently saw another comment objecting to `with` altogether as being obfuscating because you can't tell which symbols are qualified by the symbol in the with clause, when the obfuscation was  clearly due to the meaningless names in the poster's example.
July 23, 2018
On Sunday, 22 July 2018 at 14:05:45 UTC, Jonathan M Davis wrote:
> On Sunday, July 22, 2018 12:13:43 Anonymouse via Digitalmars-d wrote:
>> Can this be made a compiler warning?
>>
>> struct Foo
>> {
>>      int i;
>> }
>>
>> void main()
>> {
>>      Foo foo;
>>
>>      with (foo)
>>      {
>>          i = 42;
>>          int i;
>>          i = 24;
>>      }
>> }
>>
>> I'm hesitant to file a bug because it'll just be immediately closed with a link to https://dlang.org/spec/statement.html#WithStatement. I understand that's how it works, but it's weird and weak to human mistakes.
>
> Given the shadowing protections listed in #5, it could certainly be argued that it would be in the spirit of the restrictions that with already has, and I think that there's a pretty clear argument to be made that allowing it is too error-prone, but maybe someone will have a reason why it doesn't make sense to disallow it. I don't know. Regardless, I would suggest that you open an enhancement request. I would guess that it's straightforward enough that a DIP isn't reauired so long as Walter approves of it, but I don't know. Either way, if it's in bugzilla, then it stands a much better chance of happening than if the only record of it is here.
>
> - Jonathan M Davis

#5 says that a symbol defined in an outer scope and used within the with block must not also be a member of Foo, to prevent a silent change in the meaning of the code if that symbol gets added to Foo -- #5 will result in an error message if that happens. Nothing like that applies here ... clearly the two `i's are different, since you can't use a symbol before it's defined (except at top level). You might want to argue that it should be disallowed (I wouldn't), but I don't think you can use "the spirit of #5" to do so.
July 23, 2018
On Monday, 23 July 2018 at 12:01:19 UTC, Jim Balter wrote:
> Do you have an actual case where it was a problem, as opposed to a contrived example with semantically empty identifiers? I recently saw another comment objecting to `with` altogether as being obfuscating because you can't tell which symbols are qualified by the symbol in the with clause, when the obfuscation was  clearly due to the meaningless names in the poster's example.

Copy/pasted but changed some bits for clarity.

struct IRCServer
{
    // ...
    string prefixchars;
    string prefixes;  // <--
}

struct IRCBot
{
    // ...
    IRCServer server;
}

struct IRCParser
{
    // ...
    IRCBot bot;
}

IRCParser parser;

// string content == "EXCEPTS INVEX PREFIX=(Yqaohv)!~&@%+";

foreach (entry; content.splitter(" "))
{
    // Roughly rewritten splitting
    auto split = entry.findSplit("=");
    string key = split[0];
    string value = split[2];

    with (parser.bot.server)
    switch (key)
    {
    case "PREFIX":
        // PREFIX=(Yqaohv)!~&@%+
        import std.format : formattedRead;

        string modes;
        string prefixes;  // <--
        value.formattedRead("(%s)%s", modes, prefixes);

        foreach (immutable i; 0..modes.length)
        {
            prefixchars[prefixes[i]] = modes[i];  // parser.bot.server.prefixchars
            prefixes ~= modes[i];  // <-- accidental local prefixes instead of parser.bot.server.prefixes
        }
        break;

    // ...

    default:
        break;
}

https://github.com/zorael/kameloso/blob/93002da193eac2dfbfeb6c8756feb2d74a345530/source/kameloso/irc.d#L1887
July 23, 2018
On Sunday, 22 July 2018 at 12:13:43 UTC, Anonymouse wrote:
> I'm hesitant to file a bug because it'll just be immediately closed with a link to https://dlang.org/spec/statement.html#WithStatement. I understand that's how it works, but it's weird and weak to human mistakes.

IMO the only reasonable thing to do with `with` is not to use it, generally speaking.
Maybe in D the only exception would be with an named enum ( the final switch pattern). But otherwise the WithStatement, D or not, is known for being a big nono.
July 23, 2018
On 7/22/18 8:13 AM, Anonymouse wrote:
> Can this be made a compiler warning?
> 
> struct Foo
> {
>      int i;
> }
> 
> void main()
> {
>      Foo foo;
> 
>      with (foo)
>      {
>          i = 42;
>          int i;
>          i = 24;
>      }
> }
> 
> I'm hesitant to file a bug because it'll just be immediately closed with a link to https://dlang.org/spec/statement.html#WithStatement. I understand that's how it works, but it's weird and weak to human mistakes.

I'm with Jonathan, it should be an error. It shouldn't matter what scope you declared `i` in, just when you use it, the ambiguity should trigger. The fix is super-simple, name it something else!

Note that this won't fix other ambiguities. For example, if Foo has an opDispatch that matches "i", or `i` is a UFCS function (actually, I don't know if UFCS works using `with`).

-Steve
July 24, 2018
On Monday, 23 July 2018 at 17:26:16 UTC, Steven Schveighoffer wrote:
> On 7/22/18 8:13 AM, Anonymouse wrote:
>> Can this be made a compiler warning?
>> 
>> struct Foo
>> {
>>      int i;
>> }
>> 
>> void main()
>> {
>>      Foo foo;
>> 
>>      with (foo)
>>      {
>>          i = 42;
>>          int i;
>>          i = 24;
>>      }
>> }
>> 
>> I'm hesitant to file a bug because it'll just be immediately closed with a link to https://dlang.org/spec/statement.html#WithStatement. I understand that's how it works, but it's weird and weak to human mistakes.
>
> I'm with Jonathan, it should be an error. It shouldn't matter what scope you declared `i` in, just when you use it, the ambiguity should trigger. The fix is super-simple, name it something else!

Filed as https://issues.dlang.org/show_bug.cgi?id=19113.