Re: How to workaround on this (bug?)
Provide two functions and let the caller choose ``` void fun(ref Variant v) nothrow { } void fun2(Variant v) { fun(v); } ```
Re: How to workaround on this (bug?)
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 } ```
Re: How to workaround on this (bug?)
On Sat, Sep 17, 2022 at 12:19:16AM +, frame via Digitalmars-d-learn wrote: > 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()`. [...] 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.
Re: How to workaround on this (bug?)
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.
Re: How to workaround on this (bug?)
On Fri, Sep 16, 2022 at 10:43:43PM +, 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.
How to workaround on this (bug?)
```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.