Thread overview
[Issue 23998] @mustuse should require opCast(T:bool) is checked
Jun 18, 2023
Dennis
Jun 18, 2023
Richard Cattermole
Jun 18, 2023
Dennis
Jun 18, 2023
Richard Cattermole
Jun 18, 2023
Paul Backus
June 18, 2023
https://issues.dlang.org/show_bug.cgi?id=23998

Dennis <dkorpel@live.nl> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |dkorpel@live.nl

--- Comment #1 from Dennis <dkorpel@live.nl> ---
I don't follow, can you give a code example?

--
June 18, 2023
https://issues.dlang.org/show_bug.cgi?id=23998

--- Comment #2 from Richard Cattermole <alphaglosined@gmail.com> ---
Okay lets say we have an error struct:

```d
@mustuse struct Result(T) {
   private T* value;

   bool isNull() {
       return value is null;
   }

   ref T get() {
       return *value;
   }

   alias get this;
}
```

We pass it into our function somehow (in this case I'll go with a parameter):

```d
void myFunction(Result!int arg) {
    writeln(arg.get);
}
```

Great, you use the variable! But the whole reason for @mustuse is so that we can guarantee that error checks have been handled in some way.

So we want some way for a function (like the isNull in the above example) to have to be checked, not just a method being called.

Without this, you will end up with runtime errors instead of compiler ones (like I have been experiencing).

--
June 18, 2023
https://issues.dlang.org/show_bug.cgi?id=23998

--- Comment #3 from Dennis <dkorpel@live.nl> ---
@mustuse is supposed to prevent discarding values of that type. I'm not a fan of tacking on additional rules about `opCast` to a feature that should be simple and orthogonal. It looks like what you really want is type state, which Timon Gehr has been advocating for, but that would require a DIP.

--
June 18, 2023
https://issues.dlang.org/show_bug.cgi?id=23998

--- Comment #4 from Richard Cattermole <alphaglosined@gmail.com> ---
I'm not saying it has to be opCast, that's just my use case as it works for me at runtime as-is.

Basically, I need a way to tell the compiler, if any of these specific methods are not called immediately, then this value has been discarded even if other methods have been called.

--
June 18, 2023
https://issues.dlang.org/show_bug.cgi?id=23998

Paul Backus <snarwin+bugzilla@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |snarwin+bugzilla@gmail.com

--- Comment #5 from Paul Backus <snarwin+bugzilla@gmail.com> ---
Dennis is correct. This is completely outside the purview of @mustuse. What you are asking for is a guarantee not just that the object has been used, but that it has been used *correctly* (according to some programmer-defined criteria).

For this specific example, I think the best solution is to redesign your Result type so that it is impossible to access the wrapped value without performing a null check. Here's one possible way to do so:

---
import core.attribute, std.stdio;

@mustuse struct Result {
    private int* value;
    bool isNull() => value is null;
    int opApply(scope int delegate(int) dg)
    {
        if (value is null) return 0;
        return dg(*value);
    }
}

Result getResult() => Result(new int(42));

void main()
{
    auto r = getResult();
    foreach (int n; r)
        writeln("got ", n);
}
---

--