Instantiation of nested structs should be allowed outside their parent scope

Stanislav Blinov stanislav.blinov at gmail.com
Tue Nov 9 21:45:17 UTC 2021


On Tuesday, 9 November 2021 at 21:08:08 UTC, Timon Gehr wrote:
> On 09.11.21 19:41, Stanislav Blinov wrote:
>> On Tuesday, 9 November 2021 at 17:18:31 UTC, Timon Gehr wrote:
>>> On 09.11.21 17:51, Stanislav Blinov wrote:
>>>> On Tuesday, 9 November 2021 at 16:34:26 UTC, Timon Gehr 
>>>> wrote:
>>>>
>>>>> Sure, which is what I said (do it = copy things). But why 
>>>>> would you want the check to behave differently from actual 
>>>>> code that copies things?
>>>>
>>>> ? Because the check only needs to tell me if copying throws 
>>>> or not.
>>>
>>> For the specific issue we have been discussing, it seems to 
>>> me that copying does not work at all, independent of whether 
>>> it's throwing or not. It should just work.
>> 
>> It does work just fine. Can copy NestedThatFails within its 
>> context. Can copy it to outside of its context too if need be, 
>> with copyEmplace. Before you ask "why not just use copyEmplace 
>> for the test then?" the answers are 2:
>> 
>> 1) it's '@system', so I won't be able to devise an isSafe... 
>> test out of it, and
>
> Also, you won't be able to use it in `@safe` code. That's not 
> the same as "just work". The compiler should just do this 
> correctly, just like copyEmplace.

You can use it in @safe code. If you can determine that the copy 
is actually safe, and you're not corrupting anyone's memory. Just 
like the ctor from my example in the previous post.

> You said: "should be _that same_ union test [...] it is not". 
> My question was what is not the same.

I meant that currently it can't be "that same union test only 
without the attributes" because it will also fail, i.e. it will 
evaluate to false for copyable structs, for the same reasons. So, 
alas, it has to be a workaround monstrosity.

>> You've seen the test. It's a lambda outside of unittest. How 
>> do you propose to write a trait that DOES have access to 
>> context? Same goes for std.range.isInputRange...
>> ...

> The constraint should have as much access to context as the 
> function itself does. E.g., templates are sometimes 
> instantiated locally in the caller's context.

That won't help. Look at the example from my previous post. 
Container is nowhere near that context, and can't be. But it 
needs to be able to get *useful* introspection out of T. It won't 
if the compiler bails artificially.

>> Just to reiterate - I *have* a working implementation of a 
>> test that works around this problem for testing copy 
>> initialization specifically.


For reference:

```d
enum bool isCopyable(T, From=T)     = 
is(typeof(inferCopyAttributesIfCopyable!(T,From)));
enum bool isSafeCopyable(T, From=T) = is(typeof(() @safe => 
inferCopyAttributesIfCopyable!(T,From)));
enum bool isNogcCopyable(T, From=T) = is(typeof(() @nogc => 
inferCopyAttributesIfCopyable!(T,From)));
version (D_BetterC) {
     enum bool isNothrowCopyable(T, From=T) = .isCopyable!(T, 
From);
} else {
     enum bool isNothrowCopyable(T, From=T) = is(typeof(() nothrow 
=> inferCopyAttributesIfCopyable!(T,From)));
}

void inferIfBlittable(To, From)(scope To* to = null, scope From* 
from = null)
if (is(immutable To == immutable From))
{
     static if (__traits(isStaticArray, To))
         inferIfBlittable(&(*to)[0], &(*from)[0]);
     else static if (is(To == struct)) {
         foreach (i, ref it; to.tupleof[0 .. $-__traits(isNested, 
To)]) {
             inferIfBlittable(&it, &from.tupleof[i]);
         }
     } else {
         To copied = *from;
     }
}

void inferCopyAttributesIfCopyable(To, From)(scope To* to = null, 
scope From* from = null)
if (is(immutable To == immutable From))
{
     static if (__traits(isStaticArray, To))
         inferCopyAttributesIfCopyable(&(*to)[0], &(*from)[0]);
     else static if (is(To == struct)) {
         // This all SOOOO does not need to exist...
         // Unfortunately, if the struct is nested, doing a simple 
test
         // would result in "cannot access frame pointer" blah 
blah,
         // and if a nested struct is a field in some other 
struct, well,
         // that's even more "pleasant"...
         static if (__traits(hasPostblit, To)) {
             inferIfBlittable(to, from);
             to.__xpostblit;
         } else static if (__traits(hasCopyConstructor, To)) {
             to.__ctor(*from);
         } else {
             inferIfBlittable(to, from);
         }
     } else {
         To copied = *from;
     }
}
```

I mean, seriously, what the what! :D


More information about the Digitalmars-d mailing list