www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to workaround on this (bug?)

reply frame <frame86 live.com> writes:
```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
next sibling parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
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
parent reply frame <frame86 live.com> writes:
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
parent "H. S. Teoh" <hsteoh qfbox.info> writes:
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:
 
 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.
Sep 16 2022
prev sibling next sibling parent Quirin Schroll <qs.il.paperinik gmail.com> writes:
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
prev sibling parent Kagamin <spam here.lot> writes:
Provide two functions and let the caller choose
```
void fun(ref Variant v) nothrow
{
}

void fun2(Variant v)
{
	fun(v);
}
```
Sep 23 2022