Thread overview
Is there a way to disable copying of an alias this'd member? - trying to make a NotNull type
May 24, 2019
aliak
May 24, 2019
Simen Kjærås
May 24, 2019
Simen Kjærås
May 24, 2019
aliak
May 24, 2019
Simen Kjærås
May 24, 2019
aliak
May 24, 2019
Basically, I want this to fail:

auto notNull(T, Args...)(Args args) {
    return NotNull!T(new T(args));
}

struct NotNull(T) {
  private T _value;
  @property ref inout(T) value() inout { return this._value; }
  alias value this;
  //disable opAssign to null as well
}

class C {}
void func(ref C t) {
  t = null;
}

auto a = notNull!C;
func(a); // i want a compile error here

Any ideas that don't involve disabling copying or making the property non-ref?

Full example here: https://run.dlang.io/is/ubOwkd

Thanks!

May 24, 2019
On Friday, 24 May 2019 at 10:16:50 UTC, aliak wrote:
> Basically, I want this to fail:
>
> auto notNull(T, Args...)(Args args) {
>     return NotNull!T(new T(args));
> }
>
> struct NotNull(T) {
>   private T _value;
>   @property ref inout(T) value() inout { return this._value; }
>   alias value this;
>   //disable opAssign to null as well
> }
>
> class C {}
> void func(ref C t) {
>   t = null;
> }
>
> auto a = notNull!C;
> func(a); // i want a compile error here
>
> Any ideas that don't involve disabling copying or making the property non-ref?

Pretty sure that can't be done. On the other hand, why is the property ref if you're explicitly not going to use its ref-ness? Alternatively, can you show me how you use its ref-ness?

And just for completeness, you are aware that alias this takes an overload set, so that this works?

   struct NotNull(T) {
       private T _value;
       @property inout(T) value() inout { return _value; }
       @property void value(T val) { _value = val; } // new
       alias value this;
       // disable opAssign to null as well
   }

   class C {}
   void func(ref C t) { t = null; }

   unittest {
       NotNull n;
       n = new C(); // Look ma, I'm assigning without ref!
       func(n); // Does not compile - value() doesn't return by ref
   }

--
  Simen
May 24, 2019
On Friday, 24 May 2019 at 10:40:01 UTC, Simen Kjærås wrote:
>        NotNull n;

Typo. Should be NotNull!C n;

--
  Simen
May 24, 2019
On Friday, 24 May 2019 at 10:40:01 UTC, Simen Kjærås wrote:
> On Friday, 24 May 2019 at 10:16:50 UTC, aliak wrote:
>> Basically, I want this to fail:
>>
>> auto notNull(T, Args...)(Args args) {
>>     return NotNull!T(new T(args));
>> }
>>
>> struct NotNull(T) {
>>   private T _value;
>>   @property ref inout(T) value() inout { return this._value; }
>>   alias value this;
>>   //disable opAssign to null as well
>> }
>>
>> class C {}
>> void func(ref C t) {
>>   t = null;
>> }
>>
>> auto a = notNull!C;
>> func(a); // i want a compile error here
>>
>> Any ideas that don't involve disabling copying or making the property non-ref?
>
> Pretty sure that can't be done. On the other hand, why is the property ref if you're explicitly not going to use its ref-ness? Alternatively, can you show me how you use its ref-ness?

It's ref so that you can do this for e.g.

class C { int i; }
auto a = notNull!C;
a.i = 3;

I guess maybe there's a way to go about supporting that kinda thing with opDispatch. But I've tried doing that in the optional type [0] and it's rather painful to get right, and trickier to make @safe as well.

>
> And just for completeness, you are aware that alias this takes an overload set, so that this works?
>
>    struct NotNull(T) {
>        private T _value;
>        @property inout(T) value() inout { return _value; }
>        @property void value(T val) { _value = val; } // new
>        alias value this;
>        // disable opAssign to null as well
>    }
>
>    class C {}
>    void func(ref C t) { t = null; }
>
>    unittest {
>        NotNull n;
>        n = new C(); // Look ma, I'm assigning without ref!
>        func(n); // Does not compile - value() doesn't return by ref
>    }
>
> --
>   Simen

Si si. I is aware. I've disabled opAssign to T actually (i think i have at least). And I only allow assigning to another NotNull else there's no way to guarantee that the NotNull stays non null.

It looks like I'm going to have to sacrifice being able to manipulate member variables of the type the NotNull is wrapping, or give up on the guarantee of the inner value not being null.

[0] https://code.dlang.org/packages/optional

May 24, 2019
On Friday, 24 May 2019 at 11:40:20 UTC, aliak wrote:
> It's ref so that you can do this for e.g.
>
> class C { int i; }
> auto a = notNull!C;
> a.i = 3;

That's a valid concern for a struct, but classes are already reference types, so you're only adding a new layer of ref-ness. The above will work great with a non-ref alias this.


--
  Simen
May 24, 2019
On Friday, 24 May 2019 at 12:03:08 UTC, Simen Kjærås wrote:
> On Friday, 24 May 2019 at 11:40:20 UTC, aliak wrote:
>> It's ref so that you can do this for e.g.
>>
>> class C { int i; }
>> auto a = notNull!C;
>> a.i = 3;
>
> That's a valid concern for a struct, but classes are already reference types, so you're only adding a new layer of ref-ness. The above will work great with a non-ref alias this.
>
>
> --
>   Simen

Ah true. Yes I guess I can do this for ref types indeed. And maybe I can just constrain it to classes, interfaces and pointers 🤔

Cheers,
- Ali