View mode: basic / threaded / horizontal-split · Log in · Help
April 29, 2012
Shared with no type in Druntime.
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
Re: Shared with no type in Druntime.
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
Re: Shared with no type in Druntime.
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
Re: Shared with no type in Druntime.
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
Re: Shared with no type in Druntime.
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
Re: Shared with no type in Druntime.
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
Re: Shared with no type in Druntime.
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
Re: Shared with no type in Druntime.
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
Re: Shared with no type in Druntime.
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
Re: Shared with no type in Druntime.
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
Top | Discussion index | About this forum | D home