September 21, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7021



--- Comment #10 from Jonathan M Davis <jmdavisProg@gmx.com> 2012-09-21 12:19:15 PDT ---
It was my understanding that

@disable this();

was specifically the syntax to disable the init property. Certainly, trying to disable init directly doesn't work as far as I can tell. And since structs don't _have_ default constructors, I don't know what else

@disable this();

would be disabling (other than perhaps S(), which uses the init property
anyway, since there's no default consturctor).

The whole point is to be able disable init so that you can _never_ use it for _anything_. You must _always_ directly initialize such a type (unless you directly initialize it with void).

Yes, normally, T.init is the value that the type has before any constructor is called, but if it's disabled, then it effectively does not exist, and it should be impossible to use T.init _anywhere_. Construction should work the same with any constructors that do exist (so the object state prior to construction is the same as what T.init would have been had it existed), but it should be impossible to default initialize such a type or to use it in any context which would require default initialization, and it should be impossible to reference that type's init in code anywhere. That's the whole point of disabling init, and

@disable this();

is specifically for disabling init. It doesn't affect declared constructors work, but it affects every other aspect of init.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 22, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7021



--- Comment #11 from Kenji Hara <k.hara.pg@gmail.com> 2012-09-21 19:40:51 PDT ---
(In reply to comment #10)
> It was my understanding that
> 
> @disable this();
> 
> was specifically the syntax to disable the init property. Certainly, trying to disable init directly doesn't work as far as I can tell. And since structs don't _have_ default constructors, I don't know what else
> 
> @disable this();
> 
> would be disabling (other than perhaps S(), which uses the init property
> anyway, since there's no default consturctor).

I think @disable this(); _does_ disables just a default constructor, and doesn't disable init property.

As long as I repeated, init property represents a initial state of the object.
(In the language reference, it is called 'default initializer';
http://dlang.org/property.html#init ).
My first point is: init property does not construct anything.

Next, if any constructor is declared in struct S, S(...) is always calls the
constructors, and _should not_ become struct literal expression.
This is my second point. S() would call this(), but it is disabled, then the
compiler show an error so @disable function is used.

The third point is: the first and second are orthogonal. So I can agree that
@disable this();  would forbid a usage of S(), but I don't think that S.init
would also be forbidden.

> The whole point is to be able disable init so that you can _never_ use it for _anything_. You must _always_ directly initialize such a type (unless you directly initialize it with void).
> 
> Yes, normally, T.init is the value that the type has before any constructor is called, but if it's disabled, then it effectively does not exist, and it should be impossible to use T.init _anywhere_. Construction should work the same with any constructors that do exist (so the object state prior to construction is the same as what T.init would have been had it existed), but it should be impossible to default initialize such a type or to use it in any context which would require default initialization, and it should be impossible to reference that type's init in code anywhere. That's the whole point of disabling init, and
> 
> @disable this();
> 
> is specifically for disabling init. It doesn't affect declared constructors work, but it affects every other aspect of init.

There is a way to disable explicit init property usage.

struct S {
  @disable this();         // disable default construction
  @disable enum int init;  // dummy disabled init property, this is allowed
  ...
}

I think that the usage of S.init is at your own risk. S.init may generate invalid object, but it is sometimes useful. I hesitate that stopping such usage by the compiler.

At least, S() would be disabled by @disable this(); declaration. It is the
point of this issue, and my pull request will fix it.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 22, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7021



--- Comment #12 from Jonathan M Davis <jmdavisProg@gmx.com> 2012-09-21 19:48:34 PDT ---
For structs, as long as there is no static opCall declared, S() and S.init should be identical, and I'd strongly argue that if one is disabled, the other should be disabled. They do exactly the same thing. It makes _no_ sense IMHO to allow S.init but allow S() or vice versa (as long as no static opCall is declared).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 22, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7021



--- Comment #13 from Kenji Hara <k.hara.pg@gmail.com> 2012-09-21 20:19:53 PDT ---
(In reply to comment #12)
> For structs, as long as there is no static opCall declared, S() and S.init
> should be identical,

This is not already true for nested structs.

void main() {
    int g = 10;
    struct S {
        int n;
        auto foo(){ return g; }
    }
    auto s1 = S();  // StructLiteralExp
    assert(s1.tupleof[$-1] !is null);  // hidden ptr is filled
    assert(s1.foo() == 10);            // OK
    auto s2 = S.init;
    assert(s2.tupleof[$-1]  is null);  // hidden ptr isn't filled
    assert(s2.foo() == 10);            // Access Violation!
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 22, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7021



--- Comment #14 from Jonathan M Davis <jmdavisProg@gmx.com> 2012-09-21 21:10:52 PDT ---
> This is not already true for nested structs.

Well, that's disgusting. There are way too many special cases here. I'd vote to just make S() identical to S.init even with nested structs. It's more consistent that way, especially since you can't have a default constructor making it so that S() can't possible refer to a default constructor.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 24, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7021


Don <clugdbug@yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |clugdbug@yahoo.com.au


--- Comment #15 from Don <clugdbug@yahoo.com.au> 2012-09-24 06:31:57 PDT ---
(In reply to comment #13)
> (In reply to comment #12)
> > For structs, as long as there is no static opCall declared, S() and S.init
> > should be identical,
> 
> This is not already true for nested structs.
> 
> void main() {
>     int g = 10;
>     struct S {
>         int n;
>         auto foo(){ return g; }
>     }
>     auto s1 = S();  // StructLiteralExp
>     assert(s1.tupleof[$-1] !is null);  // hidden ptr is filled
>     assert(s1.foo() == 10);            // OK
>     auto s2 = S.init;
>     assert(s2.tupleof[$-1]  is null);  // hidden ptr isn't filled
>     assert(s2.foo() == 10);            // Access Violation!
> }

That's a bug: .init for nested structs is garbage. It's the cause of bug 6419, for example. defaultInitLiteral() is wrong.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 24, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7021



--- Comment #16 from Jonathan M Davis <jmdavisProg@gmx.com> 2012-09-24 08:32:45 PDT ---
> That's a bug: .init for nested structs is garbage. It's the cause of bug 6419,
for example. defaultInitLiteral() is wrong.

Then I _definitely_ think that S() and S.init should always be the same for structs as long as static opCall has not been declared, and

@disable this();

should disable S.init such that it's impossible to ever default-initialize S or
to use S.init or to use S() (though S() should still work if static opCall is
declared).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 24, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7021



--- Comment #17 from Kenji Hara <k.hara.pg@gmail.com> 2012-09-24 08:47:32 PDT ---
(In reply to comment #15)
> That's a bug: .init for nested structs is garbage. It's the cause of bug 6419, for example. defaultInitLiteral() is wrong.

Hmmm? Now all cases in bug 6419 run correctly. In current, by fixing bug 7965, TypeStruct::defaultInitLiteral always returns StructLiteralExp.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 24, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7021



--- Comment #18 from Kenji Hara <k.hara.pg@gmail.com> 2012-09-24 09:10:23 PDT ---
(In reply to comment #16)
> Then I _definitely_ think that S() and S.init should always be the same for structs as long as static opCall has not been declared

I cannot agree with your this opinion.

If S() is identical with S.init, default construction of nested struct will cause Access Violation in anywhere. It means that s1 would be broken at the example in comment#13. It is terrible language semantics.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
September 25, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7021


monarchdodra@gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |monarchdodra@gmail.com


--- Comment #19 from monarchdodra@gmail.com 2012-09-24 23:36:12 PDT ---
Erm, it was my understanding that @disable this() meant that it becomes illegal to initialize a struct to *just* .init (or call the .init property directly), and that a constructor must be called. The .init property still exists though, because construction can't actually happen without .init anyways...

------
import std.stdio;
struct S
{
    int i;
    S(int v)
    {
        i+=v;
    }
}

void main()
{

    // S s1; //Error: variable main.main.s1 initializer required for type S
    S s3 = S(3);
    writeln(s3.i);
}
------
3
------
The fact that this program outputs three is proof that s3 is first .init initialized, before the constructor is called proper. That's the only logical behavior (IMO) when you think of how D's initialization scheme works. If .init was truly disabled, the ONLY legal initialization would become:
----
S s = void;
----


THIS works though :/ ???
--------
void main()
{
    S s2 = S(); //WHAT...?
    S s3 = S(3);
    writeln(s3.i);
}
--------
I side with Jonathan that S() and .init should be the same thing. There are no
"default constructors" (or "no-arg", to my great dismay), in D, so having "S s
= S();" do some things behind the scenes that "S s;" doesn't is just not
conceivable from a language standpoint.

The fact that the stack pointer is not known at compile time in .init (I think, anyways) should not prevent "S s;" from properly initialized, be it by a stwo-step scheme if needed. That is a compiler implementation details, and users should (NEED) to remain blissfully unaware of it.

Either that, or we allow a true constructor that takes no argument:
S s; // .init
S s = S(); // this(){...}

But as of right now, it would seem there is a bastard of an hybrid that is half of both.

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