Thread overview
[dmd-internals] Questions: how consttructors and postblits work with qualifiers
May 09, 2012
kenji hara
May 09, 2012
Jonathan M Davis
May 09, 2012
I have some questions for the spec of struct object construction and copying. I hope that Walter and Andrei gives the answers.

Question 1:
    This is about syntax question.

    If struct S has no constructor, struct literal syntax fills the
fields with arguments.
    -> S(a0, a1, ...) is similar to:
       { S s; s.field0=a0, s.field1=a1, ..., return s; }()
    -> S() is valid and it is same as S.init.

    If struct S has some constructors, it is always used for struct
literal syntax.
    -> S(...) always calls one of constructors. It there is no match,
raises compile error.
    -> S() is always invalid, because constructor should have one or
more parameters.

    This is my understanding, is it right?

Question 2:
    If S has a constructor which it gets one argument and its type is
not a kind of S:

        struct S {
            this(int n) { ... }
        }
        S s1 = 1;    // runs this(int n) implicitly.
        S s2 = S(1); // same as above

    This is filed as issue 7019 and 4875 in bugzilla.
    Is this a bug or feature? I think it is useful feature for such
types like BigInt.
    And should it work in module scope?

Question 3:
    If S has a constructor which it gets one argument and its type is
a kind of S:

        struct S {
            this(S src) { ... }
            this(const S src) { ... }
            this(immutable S src) { ... }
        }

    It works as *copy constructor* and called on initialization with copying.

        S sm;
        immutable S si = immutable(S)(sm); // calls this(immutable S
src) explicitly
        immutable S si = sm; // calls this(immutable S src) instead of
blit copying

    This is a feature explained in TDPL, but I think it is not good.
    a. If S has a postblit, it seems to me that they conflicts each other.
    b. If S has no mutable indirection and no postblit, we can switch
object qualifier
       with blit copying, like built-types. (e.g. int n; immutable int m = n;)
       In the case, I think copy constructors won't work. Is it right?

    It seems to me that copy constructor concept conflicts with postblit one.

Question 4:
    Qualified postblits should work?

        struct S {
            this(this) {}
            this(this) immutable {}
        }
        S sm;
        const S sc = sm;     // runs this(this)? or runs only blit copy? [X]
        immutable S si = sm; // runs this(this)immutable?

    But, with current dmd, multiple postblits conflicts each other.
    Even if should do, I can't imagine how they works in some cases, like [X].

Regards.

Kenji Hara
_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals

May 09, 2012
On Wednesday, May 09, 2012 18:10:29 kenji hara wrote:
> Question 4:
>     Qualified postblits should work?
> 
>         struct S {
>             this(this) {}
>             this(this) immutable {}
>         }
>         S sm;
>         const S sc = sm;     // runs this(this)? or runs only blit copy? [X]
> immutable S si = sm; // runs this(this)immutable?
> 
>     But, with current dmd, multiple postblits conflicts each other.
>     Even if should do, I can't imagine how they works in some cases, like

Qualified postblits make no sense, given that if the object is const or immutable, you _can't_ alter it without violating the type system. But without them, you can't copy const or immutable objects which require a postblit. Walter and Andrei have stated in the past that they had a plan for solving this, but AFAIK, they've never actually revealed what it is. My best guess would be to introduce copy constructors for const and immutable objects, but I don't know. Regardless, this is a situation that definitely needs to be clarified and properly sorted out.

- Jonathan M Davis
_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals

May 10, 2012
On 5/9/12 4:10 AM, kenji hara wrote:
> I have some questions for the spec of struct object construction and copying.
> I hope that Walter and Andrei gives the answers.

Kenji, I'm very busy right now so for now let me just say this.

Construction of qualified objects is doable with some control flow but not completely implemented at the moment.

Copying of qualified objects, particularly copies that change the qualifier, has major issues regarding typechecking of this(this). At this moment Walter and I agree that this is the single largest design problem with the language.

I started a DIP on it but didn't get too far. I foresee we'll need to do some serious language change there.

Will get back to this soon. Please stay tuned.


Thanks,

Andrei
_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals

October 22, 2012
This is a reply to an older email by Kenji (I keep all of its text, in which I insert my replies).

On 5/9/12 12:10 PM, kenji hara wrote:
> I have some questions for the spec of struct object construction and copying.
> I hope that Walter and Andrei gives the answers.
>
> Question 1:
>      This is about syntax question.
>
>      If struct S has no constructor, struct literal syntax fills the
> fields with arguments.
>      ->  S(a0, a1, ...) is similar to:
>         { S s; s.field0=a0, s.field1=a1, ..., return s; }()
>      ->  S() is valid and it is same as S.init.

That is correct.

>      If struct S has some constructors, it is always used for struct
> literal syntax.
>      ->  S(...) always calls one of constructors. It there is no match,
> raises compile error.
>      ->  S() is always invalid, because constructor should have one or
> more parameters.
>
>      This is my understanding, is it right?

That would be closer to the C++ rule. Right now (2.061) "auto s = S();" or "S s;" for a struct S with some constructors defined works and initializes the struct with S.init. Only if S.init is @disable the story is different.

I think that's a fine rule. It's important to be able to avail ourselves of a default constructor as often as possible.

> Question 2:
>      If S has a constructor which it gets one argument and its type is
> not a kind of S:
>
>          struct S {
>              this(int n) { ... }
>          }
>          S s1 = 1;    // runs this(int n) implicitly.
>          S s2 = S(1); // same as above
>
>      This is filed as issue 7019 and 4875 in bugzilla.
>      Is this a bug or feature? I think it is useful feature for such
> types like BigInt.
>      And should it work in module scope?

I sent a detailed reply to http://d.puremagic.com/issues/show_bug.cgi?id=7019 - in brief we should fix construction at module scope, and change nothing else.

> Question 3:
>      If S has a constructor which it gets one argument and its type is
> a kind of S:
>
>          struct S {
>              this(S src) { ... }
>              this(const S src) { ... }
>              this(immutable S src) { ... }
>          }
>
>      It works as *copy constructor* and called on initialization with copying.
>
>          S sm;
>          immutable S si = immutable(S)(sm); // calls this(immutable S
> src) explicitly
>          immutable S si = sm; // calls this(immutable S src) instead of
> blit copying
>
>      This is a feature explained in TDPL, but I think it is not good.
>      a. If S has a postblit, it seems to me that they conflicts each other.
>      b. If S has no mutable indirection and no postblit, we can switch
> object qualifier
>         with blit copying, like built-types. (e.g. int n; immutable int m = n;)
>         In the case, I think copy constructors won't work. Is it right?
>
>      It seems to me that copy constructor concept conflicts with postblit one.

I agree there's a big problem here. The worst of it is that postblit ctors make it VERY difficult to typecheck copy construction of qualified objects (const and immutable). It's much easier to check that some fields get initialized properly one by one, than to make sure the postblit "adjustments" leave the object in the correct state.

We didn't predict this when we designed postblit. It's probably D's largest design mistake.

Going forward I think we should design good copy constructors and migrate away from postblits, while still allowing them (they're very good when they're good - simple adjustments for non-qualified structs).

> Question 4:
>      Qualified postblits should work?
>
>          struct S {
>              this(this) {}
>              this(this) immutable {}
>          }
>          S sm;
>          const S sc = sm;     // runs this(this)? or runs only blit copy? [X]
>          immutable S si = sm; // runs this(this)immutable?
>
>      But, with current dmd, multiple postblits conflicts each other.
>      Even if should do, I can't imagine how they works in some cases, like [X].

There are two qualifiers involved in a postblit: the source and the target. We could allow such by using e.g.

this(const this) immutable {}

which would be called when constructing an immutable object from a const one.

But as I mentioned above semantically checking postblits is likely to be a nightmare. So I think we should go with exploring C++-style copy constructors that accept qualified arguments. In theory there are nine, excluding "shared":

this(S src) { ... }
this(const S src) { ... }
this(immutable S src) { ... }
this(S src) const { ... }
this(const S src) const { ... }
this(immutable S src) const { ... }
this(S src) immutable { ... }
this(const S src) immutable { ... }
this(immutable S src) immutable { ... }

In practice, of course, many would not need an implementation and rely on the default one (memcpy).

The right next step here is to start a DIP with a detailed explanation of how these constructors will be defined and typechecked - the whole raw to cooked business etc. Kenji, would you like to start that?


Thanks,

Andrei
_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals