digitalmars.D.learn - How to workaround on this (bug?)
- frame (14/14) Sep 16 2022 ```d
- H. S. Teoh (12/31) Sep 16 2022 I was doing to suggest using `const ref`, but if the signature must
- frame (5/10) Sep 16 2022 I understand why this happens but not why the compiler does not
- H. S. Teoh (12/22) Sep 16 2022 [...]
- Quirin Schroll (30/45) Sep 23 2022 A reference effectively is a never-`null` pointer. A slice is a
- Kagamin (10/10) Sep 23 2022 Provide two functions and let the caller choose
```d import std.variant; // error: destructor `std.variant.VariantN!32LU.VariantN.~this` is not `nothrow` void fun(Variant v) nothrow { } void main() { fun(Variant()); } ``` A reference, pointer or slice works. I could do something on the caller site but the signature of `fun()` should remain like above.
Sep 16 2022
On Fri, Sep 16, 2022 at 10:43:43PM +0000, frame via Digitalmars-d-learn wrote:```d import std.variant; // error: destructor `std.variant.VariantN!32LU.VariantN.~this` is not `nothrow` void fun(Variant v) nothrow { } void main() { fun(Variant()); } ``` A reference, pointer or slice works.Yes, because in that case the dtor would not need to be invoked in .fun.I could do something on the caller site but the signature of `fun()` should remain like above.I was doing to suggest using `const ref`, but if the signature must remain the same, then I'm out of ideas. Basically, if you pass something to .fun by value, then that value must be destroyed by .fun once it's ready to return. So if the value has a dtor, the dtor must be called upon exiting from .fun. Since Variant has a throwing dtor, this means .fun may throw when it's about to return, which violates `nothrow`. T -- If creativity is stifled by rigid discipline, then it is not true creativity.
Sep 16 2022
On Friday, 16 September 2022 at 23:06:35 UTC, H. S. Teoh wrote:Basically, if you pass something to .fun by value, then that value must be destroyed by .fun once it's ready to return. So if the value has a dtor, the dtor must be called upon exiting from .fun. Since Variant has a throwing dtor, this means .fun may throw when it's about to return, which violates `nothrow`.I understand why this happens but not why the compiler does not check if the value is actually destroyed in user code by `.destroy()`. Thanks for your suggestion, I will consider this.
Sep 16 2022
On Sat, Sep 17, 2022 at 12:19:16AM +0000, frame via Digitalmars-d-learn wrote:On Friday, 16 September 2022 at 23:06:35 UTC, H. S. Teoh wrote:[...] I don't know for sure, but my guess is that .destroy is seen by the compiler just like any other D function; i.e., it's not treated specially. So it would not factor into the compiler's lifetime considerations. Or are you talking about the case where the Variant may not actually contain values that have dtors? That information is not available until runtime; the compiler can't make decisions based on that. T -- Political correctness: socially-sanctioned hypocrisy.Basically, if you pass something to .fun by value, then that value must be destroyed by .fun once it's ready to return. So if the value has a dtor, the dtor must be called upon exiting from .fun. Since Variant has a throwing dtor, this means .fun may throw when it's about to return, which violates `nothrow`.I understand why this happens but not why the compiler does not check if the value is actually destroyed in user code by `.destroy()`.
Sep 16 2022
On Friday, 16 September 2022 at 22:43:43 UTC, frame wrote:```d import std.variant; // error: destructor `std.variant.VariantN!32LU.VariantN.~this` is not `nothrow` void fun(Variant v) nothrow { } void main() { fun(Variant()); } ``` A reference, pointer or slice works. I could do something on the caller site but the signature of `fun()` should remain like above.A reference effectively is a never-`null` pointer. A slice is a pointer to the first of many objects plus the number of those objects (or empty, or `null`). It boils down to pointers, and the pointed-to `Variant` object is not the responsibility of `fun`. When you have a parameter that binds by copy, you cannot escape from calling its destructor, and if one happens not to be `nothrow`, your function cannot be `nothrow`. The new semantics for `in` (compile with `-preview=in`) might work for you. The `in` storage class binds by copy if the copy is cheap – which I suspect is never the case for a `Variant` – or else by reference; and it can bind temporaries by reference (unlike `ref`). However, `in` also incurs `const` and `scope`. It is unlikely that `scope` will be your problem, but `const` very well might be an issue when the contained value has indirections to mutable values, e.g. an `int[]` will be read as a `const(int)[]`. Calling the destructor is then the responsibility of the caller. ```d // Compile with -preview=in import std.variant; void fun(in Variant v) nothrow { } void main() { fun(Variant()); // okay: `in` binds rvalues Variant v; fun(v); // okay: `in` binds lvalues } ```
Sep 23 2022
Provide two functions and let the caller choose ``` void fun(ref Variant v) nothrow { } void fun2(Variant v) { fun(v); } ```
Sep 23 2022