Jump to page: 1 2
Thread overview
T.init and @disable this
Oct 04, 2012
monarch_dodra
Oct 04, 2012
Jonathan M Davis
Oct 04, 2012
monarch_dodra
Oct 04, 2012
Andrej Mitrovic
Oct 04, 2012
Maxim Fomin
Oct 04, 2012
kenji hara
Oct 06, 2012
Jonathan M Davis
Oct 06, 2012
kenji hara
Oct 11, 2012
deadalnix
Oct 05, 2012
deadalnix
Oct 06, 2012
Jonathan M Davis
Oct 06, 2012
kenji hara
Oct 11, 2012
deadalnix
Oct 06, 2012
Jonathan M Davis
Oct 06, 2012
monarch_dodra
Oct 06, 2012
monarch_dodra
October 04, 2012
I'm trying to find out the exact semantics of

@disable this();

It is not well documented, and the fact that it is (supposedly) buggy makes it really confusing.

My understanding is that it "merely" makes it illegal to default initialization your type: You, the developer, have to specify the initial value.

//----
T t; //initializer required for type
//----
Which means, you, the developper, must explicitly choose an initial value.

However, DOES or DOES NOT this remain legal?
//----
T t = T.init; //Fine: You chose the initializer T.init
//----

Keep in mind it is not possible to make "T.init" itself disappear, because nothing can be constructed if T.init is not first memcopied onto the object, before calling any constructor proper.

I think this should be legal, because you, the developer, is asking for it, just the same way one can write "T t = void".

Making it illegal would pretty much make T unmoveable, un-emplaceable, un-initializeable on un-initialized memmory, and would probably break more than one function/trait which uses "T.init"

Feedback?
October 04, 2012
On Thursday, October 04, 2012 10:18:14 monarch_dodra wrote:
> Making it illegal would pretty much make T unmoveable, un-emplaceable, un-initializeable on un-initialized memmory,

That's kind of the point. If that's not what you want, don't disable init.

> and
> would probably break more than one function/trait which uses
> "T.init"

Which is a definite downside to the whole disabling init idea.

As for T.init and constructors, it should be perfectly possible to initialize the object to what T.init would be prior to construction without making T.init available at all.

- Jonathan M Davis
October 04, 2012
On Thursday, 4 October 2012 at 09:25:01 UTC, Jonathan M Davis wrote:
> On Thursday, October 04, 2012 10:18:14 monarch_dodra wrote:
>> Making it illegal would pretty much make T unmoveable,
>> un-emplaceable, un-initializeable on un-initialized memmory,
>
> That's kind of the point. If that's not what you want, don't disable init.

Hum... I had never actually thought of it that way!

>> and
>> would probably break more than one function/trait which uses
>> "T.init"
>
> Which is a definite downside to the whole disabling init idea.
>
> As for T.init and constructors, it should be perfectly possible to initialize
> the object to what T.init would be prior to construction without making T.init
> available at all.
>
> - Jonathan M Davis

Good point too.
October 04, 2012
On 10/4/12, monarch_dodra <monarchdodra@gmail.com> wrote:
> I'm trying to find out the exact semantics of
>
> @disable this();

Also this still works:

struct Foo
{
    @disable this();
}

void main()
{
    Foo foo = Foo();
}

I really don't know why though.. Isn't this a bug? A workaround in user-code is defining a disabled static opCall:

struct Foo
{
    @disable this();
    @disable static void opCall();
}
October 04, 2012
On Thursday, 4 October 2012 at 17:37:58 UTC, Andrej Mitrovic wrote:
> On 10/4/12, monarch_dodra <monarchdodra@gmail.com> wrote:
>> I'm trying to find out the exact semantics of
>>
>> @disable this();
>
> Also this still works:
>
> struct Foo
> {
>     @disable this();
> }
>
> void main()
> {
>     Foo foo = Foo();
> }
>
> I really don't know why though.. Isn't this a bug? A workaround in
> user-code is defining a disabled static opCall:
>
> struct Foo
> {
>     @disable this();
>     @disable static void opCall();
> }

http://d.puremagic.com/issues/show_bug.cgi?id=8703

October 04, 2012
2012/10/4 monarch_dodra <monarchdodra@gmail.com>:
> I'm trying to find out the exact semantics of
>
> @disable this();
>
> It is not well documented, and the fact that it is (supposedly) buggy makes
> it really confusing.
>
> My understanding is that it "merely" makes it illegal to default initialization your type: You, the developer, have to specify the initial value.
>
> //----
> T t; //initializer required for type
> //----
> Which means, you, the developper, must explicitly choose an initial value.
>
> However, DOES or DOES NOT this remain legal?
> //----
> T t = T.init; //Fine: You chose the initializer T.init
> //----
>
> Keep in mind it is not possible to make "T.init" itself disappear, because nothing can be constructed if T.init is not first memcopied onto the object, before calling any constructor proper.
>
> I think this should be legal, because you, the developer, is asking for it, just the same way one can write "T t = void".

I think that T.init is legal even if T has just only @disable this()
constructor. If not,
> Making it illegal would pretty much make T unmoveable, un-emplaceable, un-initializeable on un-initialized memmory, and would probably break more than one function/trait which uses "T.init"

But, I also agree that T.init _sometimes_ *unsafe*.
1) If T has @disable this(), T.init will returns an object which just
initialized (== the value itself is never undefined), but not
constructed (might be logically invalid object).
2) If T is nested struct, it's frame pointer is always null. It might
cause access violation by its member function call.

I came up with just now: The use of such unsafe T.init should be
allowed only inside @system/@trusted functions.
I think it is acceptable limitation.

Thoughts?

Kenji Hara
October 05, 2012
Le 04/10/2012 10:18, monarch_dodra a écrit :
> I'm trying to find out the exact semantics of
>
> @disable this();
>
> It is not well documented, and the fact that it is (supposedly) buggy
> makes it really confusing.
>
> My understanding is that it "merely" makes it illegal to default
> initialization your type: You, the developer, have to specify the
> initial value.
>
> //----
> T t; //initializer required for type
> //----
> Which means, you, the developper, must explicitly choose an initial value.
>
> However, DOES or DOES NOT this remain legal?
> //----
> T t = T.init; //Fine: You chose the initializer T.init
> //----
>
> Keep in mind it is not possible to make "T.init" itself disappear,
> because nothing can be constructed if T.init is not first memcopied onto
> the object, before calling any constructor proper.
>
> I think this should be legal, because you, the developer, is asking for
> it, just the same way one can write "T t = void".
>
> Making it illegal would pretty much make T unmoveable, un-emplaceable,
> un-initializeable on un-initialized memmory, and would probably break
> more than one function/trait which uses "T.init"
>
> Feedback?

Making T.init unsafe in this case should be enough.
October 06, 2012
On 10/4/12 7:33 AM, kenji hara wrote:
> But, I also agree that T.init _sometimes_ *unsafe*.
> 1) If T has @disable this(), T.init will returns an object which just
> initialized (== the value itself is never undefined), but not
> constructed (might be logically invalid object).
> 2) If T is nested struct, it's frame pointer is always null. It might
> cause access violation by its member function call.
>
> I came up with just now: The use of such unsafe T.init should be
> allowed only inside @system/@trusted functions.
> I think it is acceptable limitation.
>
> Thoughts?

I think we should go back to the rationale for introducing @disable. The most important motivating examples were:

1. Defining NonNull references

2. Defining objects that are movable but not copyable

For NonNull references, the existence of an usable T.init would be a definite problem because it would suddenly allow the existence of, well, a null reference.

For (2) there may also be breakage, although more subtle: uncopyable objects are often associated with carefully-guarded resources (e.g. mutex locks) and shouldn't exist without special creation.

However, T.init is good to have as an always available value inside static code that tests e.g. for capabilities.

(There's been a long-standing similar problem in C++ as well.)

A possible solution is to allow T.init for uncopyable types as an unresolved reference: code can use it symbolically, but if it tries to actually do things with it at runtime that would be a link-time error.

Another solution would be to define T.init for uncopyable types as function that just throws if ever called.

Thoughts?


Andrei
October 06, 2012
On Saturday, October 06, 2012 02:54:23 Andrei Alexandrescu wrote:
> A possible solution is to allow T.init for uncopyable types as an unresolved reference: code can use it symbolically, but if it tries to actually do things with it at runtime that would be a link-time error.

This sounds like a great solution. Being able to disallow the init property where appropriate but still be able to use it with compile-time reflection would be fantastic. The issues with compile-time checks are the biggest problem that I've had with the idea of disabling init.

> Another solution would be to define T.init for uncopyable types as function that just throws if ever called.

A linker problem would be better than throwing IMHO.

Regardless, we need to better sort out how disabling init works. It was my understanding that the correct way to do it was to do

@disable this();

but apparently that's in dispute (at least, Kenji doesn't seem to think that that's supposed to disable the init property), and it doesn't actually work.

- Jonathan M Davis
October 06, 2012
2012/10/6 Jonathan M Davis <jmdavisProg@gmx.com>:
> Regardless, we need to better sort out how disabling init works. It was my understanding that the correct way to do it was to do
>
> @disable this();
>
> but apparently that's in dispute (at least, Kenji doesn't seem to think that that's supposed to disable the init property), and it doesn't actually work.

My argue is simple: If your argument is proper behavior, you never move NonNull object.

Kenji Hara
« First   ‹ Prev
1 2