Re: How to workaround on this (bug?)

2022-09-23 Thread Kagamin via Digitalmars-d-learn

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?)

2022-09-23 Thread Quirin Schroll via Digitalmars-d-learn

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?)

2022-09-16 Thread H. S. Teoh via Digitalmars-d-learn
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?)

2022-09-16 Thread frame via Digitalmars-d-learn

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?)

2022-09-16 Thread H. S. Teoh via Digitalmars-d-learn
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?)

2022-09-16 Thread frame via Digitalmars-d-learn

```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.