Jump to page: 1 24  
Page
Thread overview
Instantiation of nested structs should be allowed outside their parent scope
Nov 08, 2021
Stanislav Blinov
Nov 09, 2021
Stefan Koch
Nov 09, 2021
Stanislav Blinov
Nov 09, 2021
Alexandru Ermicioi
Nov 09, 2021
Stanislav Blinov
Nov 09, 2021
Alexandru Ermicioi
Nov 09, 2021
Stanislav Blinov
Nov 09, 2021
Alexandru Ermicioi
Nov 09, 2021
Alexandru Ermicioi
Nov 09, 2021
Stanislav Blinov
Nov 09, 2021
Stanislav Blinov
Nov 09, 2021
Timon Gehr
Nov 09, 2021
Stanislav Blinov
Nov 09, 2021
Timon Gehr
Nov 09, 2021
Timon Gehr
Nov 09, 2021
Stanislav Blinov
Nov 09, 2021
Timon Gehr
Nov 09, 2021
Timon Gehr
Nov 09, 2021
Stanislav Blinov
Nov 09, 2021
Timon Gehr
Nov 09, 2021
Stanislav Blinov
Nov 09, 2021
Timon Gehr
Nov 09, 2021
Stanislav Blinov
Nov 09, 2021
Timon Gehr
Nov 09, 2021
Stanislav Blinov
Nov 09, 2021
Stanislav Blinov
Nov 09, 2021
Timon Gehr
Nov 09, 2021
Stanislav Blinov
Nov 09, 2021
Timon Gehr
Nov 09, 2021
Stanislav Blinov
Nov 09, 2021
Timon Gehr
Nov 09, 2021
Stanislav Blinov
Nov 09, 2021
Timon Gehr
Nov 09, 2021
Stanislav Blinov
Nov 09, 2021
Timon Gehr
November 08, 2021

Just make it @system, and even then ONLY if something is actually getting instantiated and it's not just a CTFE test. Unless I'm missing something, that should be the behavior. The 'cannot access frame pointer' blah SO needs to go away...

Rationale: instantiating things is super useful for compile time tests and inference. Nested structs complicate that to wazoo with that failure.

If you're not convinced, I encourage you to try and define e.g.

enum bool isNothrowCopyable(To, From) = /* ??? */

without reimplementing copy initialization by hand. It should be a trivial test. Just test copy-initialization of a union field. But no. Not when nested structs are involved. And they can get involved indirectly.

November 09, 2021

On Monday, 8 November 2021 at 01:02:11 UTC, Stanislav Blinov wrote:

>

Just make it @system, and even then ONLY if something is actually getting instantiated and it's not just a CTFE test. Unless I'm missing something, that should be the behavior. The 'cannot access frame pointer' blah SO needs to go away...

Rationale: instantiating things is super useful for compile time tests and inference. Nested structs complicate that to wazoo with that failure.

If you're not convinced, I encourage you to try and define e.g.

enum bool isNothrowCopyable(To, From) = /* ??? */

without reimplementing copy initialization by hand. It should be a trivial test. Just test copy-initialization of a union field. But no. Not when nested structs are involved. And they can get involved indirectly.

How would you want a struct to behave when it is used outside of it's context?
Set the context pointer to null and throw upon access?

November 09, 2021

On Tuesday, 9 November 2021 at 01:06:16 UTC, Stefan Koch wrote:

>

How would you want a struct to behave when it is used outside of it's context?
Set the context pointer to null and throw upon access?

Throw? No, segfault like any other null dereference. Ain't no harm in that. As compared to absolutely ruining generic code for, frankly, no benefit, and numerous, NUMEROUS bugs and "workarounds" that simply don't need to exist.

November 09, 2021

On Monday, 8 November 2021 at 01:02:11 UTC, Stanislav Blinov wrote:

>

Just make it @system...

On second thought, doesn't even need to be @system. Just needs to be allowed.

November 09, 2021
On 08.11.21 02:02, Stanislav Blinov wrote:
> 
> If you're not convinced, I encourage you to try and define e.g.
> 
> ```d
> enum bool isNothrowCopyable(To, From) = /* ??? */
> ```


There is never really a need to instantiate a value of any type just to check what it supports. Just use parameters in your function literal. This has the side effect of supporting `inout` shenanigans as well.

enum bool isNothrowCopyable(To, From) = __traits(compiles, (To to, From from)nothrow{ to=from; });

(Untested. If I have misunderstood what it should check for, just change the function body.)
November 09, 2021

On Tuesday, 9 November 2021 at 01:54:44 UTC, Stanislav Blinov wrote:

>

Throw? No, segfault like any other null dereference. Ain't no harm in that. As compared to absolutely ruining generic code for, frankly, no benefit, and numerous, NUMEROUS bugs and "workarounds" that simply don't need to exist.

I'd rather have compiler throw errors rather than having yet another potential segfault in application which needs to be checked.

November 09, 2021
On Tuesday, 9 November 2021 at 09:24:29 UTC, Timon Gehr wrote:
> On 08.11.21 02:02, Stanislav Blinov wrote:
>> 
>> If you're not convinced, I encourage you to try and define e.g.
>> 
>> ```d
>> enum bool isNothrowCopyable(To, From) = /* ??? */
>> ```

...WITHOUT REIMPLEMENTING COPY INITIALIZATION BY HAND.

>
>
> There is never really a need to instantiate a value of any type just to check what it supports.

Yes, there is. isInputRange tries, and fails for some nested structs (keyword - some). This copy attributes check needs an instance too.

> enum bool isNothrowCopyable(To, From) = __traits(compiles, (To to, From from)nothrow{ to=from; });

Nope. That tests assignment. Which may, or may not, also test destructor, depending on whether opAssign is defined. The check must needs to test ONLY copy-initialization (blit, copy ctor, and/or postblit).

> (Untested. If I have misunderstood what it should check for, just change the function body.)

Yes. "Just". For that specific check - by recreating the copy semantics. I can show you the code I came up with, but like I said, I really do encourage you to try. Just to experience, in full, how ridiculous it gets.
November 09, 2021
On 09.11.21 15:11, Stanislav Blinov wrote:
> On Tuesday, 9 November 2021 at 09:24:29 UTC, Timon Gehr wrote:
>> ...
>>
>> There is never really a need to instantiate a value of any type just to check what it supports.
> 
> Yes, there is. isInputRange tries, and fails for some nested structs (keyword - some).

Fair, sometimes you want to check whether you can declare a value of the given type, though that _should_ fail in case it's not actually possible for the algorithm to do that and get an actually working instance. It's plausible that that check does not actually work correctly for some Phobos functions though, as local instantiation of templates is a bit messy.

> This copy attributes check needs an instance too.
>  >> enum bool isNothrowCopyable(To, From) = __traits(compiles, (To to,
>> From from)nothrow{ to=from; });
> 
> Nope. That tests assignment. Which may, or may not, also test destructor, depending on whether opAssign is defined. The check must needs to test ONLY copy-initialization (blit, copy ctor, and/or postblit).
> ...

I see, I guess you actually want this, but it does not work:

enum bool isNothrowCopyable(To, From) = __traits(compiles, (From from)nothrow{ To to=from; });

What's the use case for checking only this kind of initialization, if you don't need to create new instances of `to`?
November 09, 2021
On 09.11.21 16:07, Timon Gehr wrote:
> 
> I see, I guess you actually want this, but it does not work:
> 
> enum bool isNothrowCopyable(To, From) = __traits(compiles, (From from)nothrow{ To to=from; });

Well, that checks the destructor too of course. x)
But now I understand why you want to instantiate To.
November 09, 2021
On Tuesday, 9 November 2021 at 15:07:58 UTC, Timon Gehr wrote:
> On 09.11.21 15:11, Stanislav Blinov wrote:
>> On Tuesday, 9 November 2021 at 09:24:29 UTC, Timon Gehr wrote:
>>> ...
>>>
>>> There is never really a need to instantiate a value of any type just to check what it supports.
>> 
>> Yes, there is. isInputRange tries, and fails for some nested structs (keyword - some).
>
> Fair, sometimes you want to check whether you can declare a value of the given type, though that _should_ fail in case it's not actually possible for the algorithm to do that and get an actually working instance. It's plausible that that check does not actually work correctly for some Phobos functions though, as local instantiation of templates is a bit messy.

The point is it must be possible to test that, and it's not, because of some arbitrary artificial limitation. I mean, we can freely instantiate null delegates, but we can't instantiate nested structs? There's, to me, zero logic in that.

> I see, I guess you actually want this, but it does not work:
>
> enum bool isNothrowCopyable(To, From) = __traits(compiles, (From from)nothrow{ To to=from; });

No, that also tests destruction, of both `from`, because it's D, where functions destruct their arguments, and `to`, because it's a local :) What I want is this:

```d
template isNothrowCopyable(To, From)
if (is(immutable To == immutable From))
{
    enum bool isNothrowCopyable = is(typeof((ref scope From from) nothrow { union U { To to; } U u = U(from); }));
}
```

...but it indeed doesn't work for nested structs. And a thing that does "work" has to reimplement compiler's copy semantics, including field-by-field blitting, calling constructors and postblits, etc.

> What's the use case for checking only this kind of initialization, if you don't need to create new instances of `to`?

? You *do* need to create new instances of `to`. By copying existing instances. Any container that wants to support copying has to do that, and beyond. I want a test that would also tell me if my container needs special handling of exception guarantees, or if it can freely do an easy thing and not worry about it: can I just copy existing things on element insertion one element over, or do I have to do a three step algorithm because copying might throw?..
I also want other tests, that would tell me if copying is safe to do, if it needs GC, if it's pure... (I *do* have them already, but like I said, they're ludicrous, for no other reason than this handwaving error message). And as for isInputRange - I haven't got a clue if it's even possible to make it work for all nested structs unless the compiler stops issuing this error message.
« First   ‹ Prev
1 2 3 4