Thread overview
Shared with no type in Druntime.
Apr 29, 2012
Adam Wilson
Apr 29, 2012
Ali Çehreli
Apr 29, 2012
Adam Wilson
Apr 29, 2012
Jonathan M Davis
Apr 29, 2012
Adam Wilson
Apr 29, 2012
Paulo Pinto
Apr 29, 2012
Jacob Carlborg
Apr 30, 2012
Jakob Ovrum
Apr 30, 2012
Adam Wilson
May 01, 2012
Jacob Carlborg
April 29, 2012
Ok. So i've been trying to build Phobos with my new DI generation code (available here: https://github.com/LightBender/dmd.git) and i've run into an interesting usage of shared in the D Runtime. Namely, it has no type. I've been told that this is not correct and it should have a type. Is that correct?

Currently the source file (stdio.d in the DRT) has this in it and it compiles successfully:

    private extern shared FILE[_NFILE] _iob;

    shared stdin  = &_iob[0];
    shared stdout = &_iob[1];
    shared stderr = &_iob[2];
    shared stdaux = &_iob[3];
    shared stdprn = &_iob[4];

With the new DI generation code stdio.di contains this:

    private extern shared FILE[_NFILE] _iob;

    shared stdin; (Errors here and all subsequent lines in this snippet)
    shared stdout;
    shared stderr;
    shared stdaux;
    shared stdprn;

Is D doing some kind of type inference based on the type of the _iob variable in the first example that causes DMD to throw an error with the "= &_iob[0];" part removed?

-- 
Adam Wilson
IRC: LightBender
Project Coordinator
The Horizon Project
http://www.thehorizonproject.org/
April 29, 2012
On 04/28/2012 06:08 PM, Adam Wilson wrote:
> Ok. So i've been trying to build Phobos with my new DI generation code
> (available here: https://github.com/LightBender/dmd.git) and i've run
> into an interesting usage of shared in the D Runtime. Namely, it has no
> type. I've been told that this is not correct and it should have a type.
> Is that correct?
>
> Currently the source file (stdio.d in the DRT) has this in it and it
> compiles successfully:
>
> private extern shared FILE[_NFILE] _iob;
>
> shared stdin = &_iob[0];
> shared stdout = &_iob[1];
> shared stderr = &_iob[2];
> shared stdaux = &_iob[3];
> shared stdprn = &_iob[4];
>
> With the new DI generation code stdio.di contains this:
>
> private extern shared FILE[_NFILE] _iob;
>
> shared stdin; (Errors here and all subsequent lines in this snippet)
> shared stdout;
> shared stderr;
> shared stdaux;
> shared stdprn;
>
> Is D doing some kind of type inference based on the type of the _iob
> variable in the first example that causes DMD to throw an error with the
> "= &_iob[0];" part removed?
>

Yes. D does type inference all the time. Most of the time 'auto' is used because most variables have automatic storage class. The following are all legal:

void main()
{
    auto a = 42;               // int
    const c = "hello";         // string
    immutable i = 1.5;         // double

    struct S
    {}

    shared s = new shared(S);  // S*
    enum e = [ 0, 1 ];         // int[]
}

All of the standard streams are of type File:

    assert(typeid(stdin) == typeid(std.stdio.File));

Ali

April 29, 2012
On Sat, 28 Apr 2012 18:23:30 -0700, Ali Çehreli <acehreli@yahoo.com> wrote:

> On 04/28/2012 06:08 PM, Adam Wilson wrote:
>> Ok. So i've been trying to build Phobos with my new DI generation code
>> (available here: https://github.com/LightBender/dmd.git) and i've run
>> into an interesting usage of shared in the D Runtime. Namely, it has no
>> type. I've been told that this is not correct and it should have a type.
>> Is that correct?
>>
>> Currently the source file (stdio.d in the DRT) has this in it and it
>> compiles successfully:
>>
>> private extern shared FILE[_NFILE] _iob;
>>
>> shared stdin = &_iob[0];
>> shared stdout = &_iob[1];
>> shared stderr = &_iob[2];
>> shared stdaux = &_iob[3];
>> shared stdprn = &_iob[4];
>>
>> With the new DI generation code stdio.di contains this:
>>
>> private extern shared FILE[_NFILE] _iob;
>>
>> shared stdin; (Errors here and all subsequent lines in this snippet)
>> shared stdout;
>> shared stderr;
>> shared stdaux;
>> shared stdprn;
>>
>> Is D doing some kind of type inference based on the type of the _iob
>> variable in the first example that causes DMD to throw an error with the
>> "= &_iob[0];" part removed?
>>
>
> Yes. D does type inference all the time. Most of the time 'auto' is used because most variables have automatic storage class. The following are all legal:
>
> void main()
> {
>      auto a = 42;               // int
>      const c = "hello";         // string
>      immutable i = 1.5;         // double
>
>      struct S
>      {}
>
>      shared s = new shared(S);  // S*
>      enum e = [ 0, 1 ];         // int[]
> }
>
> All of the standard streams are of type File:
>
>      assert(typeid(stdin) == typeid(std.stdio.File));
>
> Ali

Ok, so that answers the legality of the issue, but it smacks of sloppy coding. We cannot ship the DRT as a dynamic library, as has been discussed and agreed to as a good idea, if their are variable declarations that rely on type inference from an assignment operation because those assignments will get stripped out of the DI. So what should I do then? Because shared stdin; by itself with no assignment to infer from IS illegal and there is not (that I can see) a way to separate an instantiation from an implementation and the whole point of DI files is too remove implementations.

-- 
Adam Wilson
IRC: LightBender
Project Coordinator
The Horizon Project
http://www.thehorizonproject.org/
April 29, 2012
On Saturday, April 28, 2012 18:32:00 Adam Wilson wrote:
> Ok, so that answers the legality of the issue, but it smacks of sloppy coding. We cannot ship the DRT as a dynamic library, as has been discussed and agreed to as a good idea, if their are variable declarations that rely on type inference from an assignment operation because those assignments will get stripped out of the DI. So what should I do then? Because shared stdin; by itself with no assignment to infer from IS illegal and there is not (that I can see) a way to separate an instantiation from an implementation and the whole point of DI files is too remove implementations.

There's nothing sloppy about it whatsoever. If you think that that's sloppy coding, then you're going to think that auto is sloppy coding, and you're going to be very unhappy with a lot of D code. Taking advantage of such type inference is considered _good_ style in D.  For the most part, you shouldn't use the type explicitly unless you actually need to.

If you need to put a variable in a .di file without its initializer, then that's a case where you're going to need to use the type explicitly. That means that either the .di generator is going to leave the initializer in (which I expect is what it currently does) - in which case you'd need to change it by hand - or it's going to need to take the type of the initializer and use that in the variable's declaration in the .di file rather than using shared by itself or auto or whatever it was using that involved type inference.

- Jonathan M Davis
April 29, 2012
On Sat, 28 Apr 2012 19:23:28 -0700, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> On Saturday, April 28, 2012 18:32:00 Adam Wilson wrote:
>> Ok, so that answers the legality of the issue, but it smacks of sloppy
>> coding. We cannot ship the DRT as a dynamic library, as has been discussed
>> and agreed to as a good idea, if their are variable declarations that rely
>> on type inference from an assignment operation because those assignments
>> will get stripped out of the DI. So what should I do then? Because shared
>> stdin; by itself with no assignment to infer from IS illegal and there is
>> not (that I can see) a way to separate an instantiation from an
>> implementation and the whole point of DI files is too remove
>> implementations.
>
> There's nothing sloppy about it whatsoever. If you think that that's sloppy
> coding, then you're going to think that auto is sloppy coding, and you're
> going to be very unhappy with a lot of D code. Taking advantage of such type
> inference is considered _good_ style in D.  For the most part, you shouldn't
> use the type explicitly unless you actually need to.
>
> If you need to put a variable in a .di file without its initializer, then
> that's a case where you're going to need to use the type explicitly. That
> means that either the .di generator is going to leave the initializer in
> (which I expect is what it currently does) - in which case you'd need to
> change it by hand - or it's going to need to take the type of the initializer
> and use that in the variable's declaration in the .di file rather than using
> shared by itself or auto or whatever it was using that involved type
> inference.
>
> - Jonathan M Davis

Ok, I can accept that. Explicit typing is lots of extra pointless typing when the compiler can just figure it out for me. But that leaves us with an interesting design question. Right now, DI gen is destructive, which means any changes I make to the DI file will get destroyed on the next build if I forget to remove the -H flags. Unfortunately that means that the DI generator is going to have to somewhat dictate coding style and we need to make sure that DI gen covers the broadest possible range of potential uses.

Personally, I have no problem leaving in initializers for module level variables. Is that an acceptable solution to the community?

-- 
Adam Wilson
IRC: LightBender
Project Coordinator
The Horizon Project
http://www.thehorizonproject.org/
April 29, 2012
Am 29.04.2012 05:03, schrieb Adam Wilson:
> On Sat, 28 Apr 2012 19:23:28 -0700, Jonathan M Davis
> <jmdavisProg@gmx.com> wrote:
>
>> On Saturday, April 28, 2012 18:32:00 Adam Wilson wrote:
>>> Ok, so that answers the legality of the issue, but it smacks of sloppy
>>> coding. We cannot ship the DRT as a dynamic library, as has been
>>> discussed
>>> and agreed to as a good idea, if their are variable declarations that
>>> rely
>>> on type inference from an assignment operation because those assignments
>>> will get stripped out of the DI. So what should I do then? Because
>>> shared
>>> stdin; by itself with no assignment to infer from IS illegal and
>>> there is
>>> not (that I can see) a way to separate an instantiation from an
>>> implementation and the whole point of DI files is too remove
>>> implementations.
>>
>> There's nothing sloppy about it whatsoever. If you think that that's
>> sloppy
>> coding, then you're going to think that auto is sloppy coding, and you're
>> going to be very unhappy with a lot of D code. Taking advantage of
>> such type
>> inference is considered _good_ style in D. For the most part, you
>> shouldn't
>> use the type explicitly unless you actually need to.
>>
>> If you need to put a variable in a .di file without its initializer, then
>> that's a case where you're going to need to use the type explicitly. That
>> means that either the .di generator is going to leave the initializer in
>> (which I expect is what it currently does) - in which case you'd need to
>> change it by hand - or it's going to need to take the type of the
>> initializer
>> and use that in the variable's declaration in the .di file rather than
>> using
>> shared by itself or auto or whatever it was using that involved type
>> inference.
>>
>> - Jonathan M Davis
>
> Ok, I can accept that. Explicit typing is lots of extra pointless typing
> when the compiler can just figure it out for me. But that leaves us with
> an interesting design question. Right now, DI gen is destructive, which
> means any changes I make to the DI file will get destroyed on the next
> build if I forget to remove the -H flags. Unfortunately that means that
> the DI generator is going to have to somewhat dictate coding style and
> we need to make sure that DI gen covers the broadest possible range of
> potential uses.
>
> Personally, I have no problem leaving in initializers for module level
> variables. Is that an acceptable solution to the community?
>

Maybe I have been spoiled by doing too much programming in languages that have module systems, but why is the initialization shown in the .di file?

This is an implementation issue on the module.

--
Paulo
April 29, 2012
On 2012-04-29 05:03, Adam Wilson wrote:

> Ok, I can accept that. Explicit typing is lots of extra pointless typing
> when the compiler can just figure it out for me. But that leaves us with
> an interesting design question. Right now, DI gen is destructive, which
> means any changes I make to the DI file will get destroyed on the next
> build if I forget to remove the -H flags. Unfortunately that means that
> the DI generator is going to have to somewhat dictate coding style and
> we need to make sure that DI gen covers the broadest possible range of
> potential uses.
>
> Personally, I have no problem leaving in initializers for module level
> variables. Is that an acceptable solution to the community?

No, I think it's way better that the DI generator outputs the actually type instead of just "shared/auto" and the assignment.

In this case:

shared stdin = &_iob[0];

Should be generated as:

shared File stdin;

Anything to the right of the assignment operator is just an implementation detail.

-- 
/Jacob Carlborg
April 30, 2012
On Sunday, 29 April 2012 at 15:21:10 UTC, Jacob Carlborg wrote:
> No, I think it's way better that the DI generator outputs the actually type instead of just "shared/auto" and the assignment.
>
> In this case:
>
> shared stdin = &_iob[0];
>
> Should be generated as:
>
> shared File stdin;
>
> Anything to the right of the assignment operator is just an implementation detail.

I agree, except to get the right behaviour, I think that must be:

    extern shared File stdin;


April 30, 2012
On Sun, 29 Apr 2012 08:21:10 -0700, Jacob Carlborg <doob@me.com> wrote:

> On 2012-04-29 05:03, Adam Wilson wrote:
>
>> Ok, I can accept that. Explicit typing is lots of extra pointless typing
>> when the compiler can just figure it out for me. But that leaves us with
>> an interesting design question. Right now, DI gen is destructive, which
>> means any changes I make to the DI file will get destroyed on the next
>> build if I forget to remove the -H flags. Unfortunately that means that
>> the DI generator is going to have to somewhat dictate coding style and
>> we need to make sure that DI gen covers the broadest possible range of
>> potential uses.
>>
>> Personally, I have no problem leaving in initializers for module level
>> variables. Is that an acceptable solution to the community?
>
> No, I think it's way better that the DI generator outputs the actually type instead of just "shared/auto" and the assignment.
>
> In this case:
>
> shared stdin = &_iob[0];
>
> Should be generated as:
>
> shared File stdin;
>
> Anything to the right of the assignment operator is just an implementation detail.

I agree, however, DMD has not yet performed it's semantic analysis at the time of DI generation so I have no clue what the type is when the files are generated. Theoretically that could be changed but such a decision is WAY above my paygrade and would probably require significant rewrites of the DI generation code, as in tearing it down and starting over. My understanding is that the reason for this is that the semantic analysis does significant rewriting of the AST and would probably drastically alter the look and even function of the output code...

Also, there is this comment in the code to start the DI generation:
        /* Generate 'header' import files.
         * Since 'header' import files must be independent of command
         * line switches and what else is imported, they are generated
         * before any semantic analysis.
         */
My guess is that that has to do with the way the command-line switches impact the semantic analysis.

-- 
Adam Wilson
IRC: LightBender
Project Coordinator
The Horizon Project
http://www.thehorizonproject.org/
May 01, 2012
On 2012-04-30 20:21, Adam Wilson wrote:

> I agree, however, DMD has not yet performed it's semantic analysis at
> the time of DI generation so I have no clue what the type is when the
> files are generated. Theoretically that could be changed but such a
> decision is WAY above my paygrade and would probably require significant
> rewrites of the DI generation code, as in tearing it down and starting
> over. My understanding is that the reason for this is that the semantic
> analysis does significant rewriting of the AST and would probably
> drastically alter the look and even function of the output code...
>
> Also, there is this comment in the code to start the DI generation:
> /* Generate 'header' import files.
> * Since 'header' import files must be independent of command
> * line switches and what else is imported, they are generated
> * before any semantic analysis.
> */
> My guess is that that has to do with the way the command-line switches
> impact the semantic analysis.
>

Ok, I didn't know about this. Regardless I think this needs to be solved in the end. Perhaps a new semantic analysis phase that is only run when generating DI files. But that would probably be quite hard.

-- 
/Jacob Carlborg