January 15
On 15/01/2024 3:03 AM, Nickolay Bukreyev wrote:
>     This makes it so things like |opApply|, only need one overload, not
>     say 24 of them to handle all the different combinations of attributes.
> 
> Just curious, why 24? +/- nothrow, +/- pure, +/- @nogc, @safe/@system—that’s /only/ 16. You can cut it down to 8 if you always require @safe (callers will have to provide a @trusted callback).

I ran a permutation on it a couple of days ago. Might not be too accurate.

But it is still a significantly larger number than 1 ;)
January 14
On 1/14/24 13:47, Richard (Rikki) Andrew Cattermole wrote:
> 
> I want this to be the default, although Timon wants it to be much more configurable so you can pick and choose per parameter (again not mutually exclusive things!).

Having this be the default is mutually exclusive with me considering the mechanism at all sane.
January 15
On 15/01/2024 2:55 AM, Alexandru Ermicioi wrote:
> On Sunday, 14 January 2024 at 13:40:11 UTC, Richard (Rikki) Andrew Cattermole wrote:
>> Earlier on I considered ``@assumenogc`` instead.
>>
>> It could work, but is much more explicit in code, that probably doesn't care. Which is why this should be the default, not opt-in.
> 
> I'd prefer it to be used explicitly as with `@trusted` since you should think twice before using gc, where people intend nogc. It may work as you've stated only when lib dev allows it to, i.e. only when callback parameter was declared with `@assumegc`.
> 
> That would allow it to be spotted easier, and allow reviewers to fuss over if they prefer to.
> 
> Besides now you need to put `@nogc` on callback anyways, so changing it to `@assumegc`, would be same level of pain.

I think that you might have this slightly backwards, but please do clarify.

The GC is excellent for application logic where performance does not matter. This makes a great default. It is how D exists, and I do not believe we will be changing this ever.

Disabling GC calls has a very strong compiler backed transitive guarantee with ``@nogc``, there are people that rely on this guarantee for their code and for that reason I do not believe we will ever weaken the transitory nature of that beyond what is provided in the arguments list. Especially since some people have businesses built upon it.

It is worth noting that closures when declared, will have their attributes inferred. You do not need to annotate ``@nogc`` on them. Such a guarantee when passed into a function/delegate pointer that does not have it, will be stripped automatically. Therefore there should not be any pain in such a case.

However I think the basic premise of what you are suggesting is a kind of informed consent towards the GC. You annotate if you use GC or not, and you may be callable.

During my mental experiments for such a design, I did not find any guarantees that would be provided by it. As such it would be a highly fragmentary approach to library development and would not achieve the desired goals but would cause unreset.

I did briefly consider a way of annotating of code that it is has been checked against a user identified thing manually. However I have not pursued it beyond that. This with ``@localnogc`` could function as you described in your previous post.

The only thing left to consider from your post I suppose is what would somebody want to review when you are calling a non-GC function from a GC function with a GC callback? This I cannot answer. I have not been able to come up with anything that would meet such a description. But I would welcome such a discussion!
January 15
On 15/01/2024 4:36 AM, Timon Gehr wrote:
> On 1/14/24 13:47, Richard (Rikki) Andrew Cattermole wrote:
>>
>> I want this to be the default, although Timon wants it to be much more configurable so you can pick and choose per parameter (again not mutually exclusive things!).
> 
> Having this be the default is mutually exclusive with me considering the mechanism at all sane.

I would be open to discussing presets for such a design, the reason I want it to be the default is it would be quite common to want this and it could be a bit of a pain to write it out often.
January 14

On Sunday, 14 January 2024 at 15:40:22 UTC, Richard (Rikki) Andrew Cattermole wrote:

>

I think that you might have this slightly backwards, but please do clarify.

Sorry, I've reread entire thread, and it seems my suggestion is not related to what you've proposed with @localnogc, it is related to another problem with delegate callbacks, where you need to mark them @nogc to be called in @nogc function.

So to make things clear about what I suggested:

void perform() {
    acceptDelegateWithGc(() {
        Object obj = new Object();
        return obj;
    });

    acceptNoGcDelegatesOnly(() {
        Object obj = new Object();
        return obj;
    }); // This fails since only nogc delegates are allowed

    acceptNoGcDelegatesOnly(() @trustedgc {
        Object obj = new Object();
        return obj;
    }); // This will work since delegate is marked with trustedgc, and therefore user knows whats he's doing when a nogc function calls a method that uses gc.
}

void acceptDelegateWithGc(Object delegate() @trustedgc create) @nogc {
	create();
}

void acceptNoGcDelegatesOnly(Object delegate() @nogc create) @nogc {
    create();
}

In your hot path case, @trustedgc functionality might be used, if it was possible to put it on statement level like this:

void hot(float[] a, float b) @nogc {
	size_t last;
	float delegate() dg = () { // error: will allocate closure context with GC
		if (last > a.length)
			return float.init;
		return a[last++] + b;
	};

	@trustedgc accept(dg); // ok, accept uses GC, this call is not checked.
}

This example is similar to a topic that was ongoing about @trusted statement blocks, which I hope would be revisited in future and implemented.

Best regards,
Alexandru.

January 14
On 1/14/2024 1:44 AM, Daniel N wrote:
> On Sunday, 14 January 2024 at 09:25:18 UTC, Walter Bright wrote:
>> Instead of using @nogc, we could have a compiler switch "warn on use of GC" which you can turn on if you like, or not, or turn on the -w switch to treat the gc warnings as errors.
> 
> What if you use @nogc in the hot-path but want to use gc during initialization?


The choices are:

1. throw -wgc switch and get a warning for every use of the GC

2. -wgc -w and get errors for every use of the GC

3. compile the gc and non-gc modules separately, using the warning switches for the latter

4. disable GC collections on the hot path with GC.disable()/GC.enable()

5. use @nogc and transitively prevent any GC use at all on such functions

6. forcibly cast away @nogc and use the GC anyway

Surely one of those will work for you!

January 14
On 1/14/2024 4:47 AM, Richard (Rikki) Andrew Cattermole wrote:
> ```d
> void func(void delegate() @nogc del) @nogc;
> ```
> 
> Basically if you pass in a delegate that does not have ``@nogc``, the ``@nogc`` on the function gets removed.
> 
> The function body will of course be typed checked as if it did have ``@nogc``.
> 
> I want this to be the default, although Timon wants it to be much more configurable so you can pick and choose per parameter (again not mutually exclusive things!).

The trouble with having a nogc function calling a gc delegate is it makes the nogc function a gc function. (If the nogc function does not actually call the gc delegate, but just stores it somewhere, that works fine.) If the nogc was silently removed, wouldn't that be very surprising behavior?

There is another way, though. In @system code, the gc delegate can be forcibly cast to be @nogc (as far as the type system is concerned - it doesn't change the behavior of the delegate).

Such forcible casting can be done with any of the attributes. However, as this subverts the type system, the correctness of it would be entirely up to the user.

D has overrides like this because it's a systems programming language.

January 14
On Sunday, 14 January 2024 at 13:48:14 UTC, Guillaume Piolat wrote:
> On Sunday, 14 January 2024 at 13:32:14 UTC, Alexandru Ermicioi wrote:
>>
>> Perhaps there should be a `@trustedgc`, similar to what`@trusted` is in safe system?
>> That would fix callback issue.
>>
>> Best regards,
>> Alexandru.
>
> In favor of this.
>
> In the other thread Walter's solution is to write a delegate that uses no GC but isn't marked @nogc. This is were such a attribute could intervene.
>
> It would be a nice symmetry with @safe/@trusted/@system if we had @nogc/@trustedgc/@gc but then perhaps not the mental load most people want ouf ot stuff they don't care about. But if I don't care about @safe, @trusted helps me a lot more.

+1, explicit is better then implicit
January 14
On Sunday, 14 January 2024 at 18:58:11 UTC, Walter Bright wrote:
> On 1/14/2024 1:44 AM, Daniel N wrote:
>> On Sunday, 14 January 2024 at 09:25:18 UTC, Walter Bright wrote:
>>> Instead of using @nogc, we could have a compiler switch "warn on use of GC" which you can turn on if you like, or not, or turn on the -w switch to treat the gc warnings as errors.
>> 
>> What if you use @nogc in the hot-path but want to use gc during initialization?
>
>
> The choices are:
>
> 1. throw -wgc switch and get a warning for every use of the GC
>
> 2. -wgc -w and get errors for every use of the GC
>
> 3. compile the gc and non-gc modules separately, using the warning switches for the latter
>
> 4. disable GC collections on the hot path with GC.disable()/GC.enable()
>
> 5. use @nogc and transitively prevent any GC use at all on such functions
>
> 6. forcibly cast away @nogc and use the GC anyway
>
> Surely one of those will work for you!

Yes, I use 5 and it works great thanks! I was under the impression that you considered removing @nogc, glad that wasn't the case.

January 15
On 15/01/2024 8:23 AM, Walter Bright wrote:
> On 1/14/2024 4:47 AM, Richard (Rikki) Andrew Cattermole wrote:
>> ```d
>> void func(void delegate() @nogc del) @nogc;
>> ```
>>
>> Basically if you pass in a delegate that does not have ``@nogc``, the ``@nogc`` on the function gets removed.
>>
>> The function body will of course be typed checked as if it did have ``@nogc``.
>>
>> I want this to be the default, although Timon wants it to be much more configurable so you can pick and choose per parameter (again not mutually exclusive things!).
> 
> The trouble with having a nogc function calling a gc delegate is it makes the nogc function a gc function. (If the nogc function does not actually call the gc delegate, but just stores it somewhere, that works fine.) If the nogc was silently removed, wouldn't that be very surprising behavior?

I think that we are looking at this inversely to each other.

Storing such a function pointer is itself a big problem, for instance it could create a time bomb that you cannot predict. But calling it has no direct program security issues (actual term in type theory!).

``@nogc`` doesn't affect codegen. But when it gets called on say a non-registered thread, could crash the program.

So as long as the caller is still in the call stack while the ``@nogc`` code has access to it, is perfectly fine from a code security standpoint.

Whilst code security isn't a concern, performance could be. It is up to the caller to ensure GC is disabled if it needs to be. This may be the primary side effect that could be surprising. Which of course could be determined by using a profiler.

So in other words, the worst case scenario for calling it means you need to use a profiler if you care about it being slow. Which is already the recommended course of action.

On the other hand, storing it has as its worse case scenario program termination and data corruption.

As for is this surprising? Think of it this way. The caller doesn't have a guarantee. It does not care if what it calls has it. So why should the compiler create an error for something the caller never cared about in the first place when it could be removed?

> There is another way, though. In @system code, the gc delegate can be forcibly cast to be @nogc (as far as the type system is concerned - it doesn't change the behavior of the delegate).
> 
> Such forcible casting can be done with any of the attributes. However, as this subverts the type system, the correctness of it would be entirely up to the user.
> 
> D has overrides like this because it's a systems programming language.

Correctness is built upon the ability to reason the logic about something.

Casting removes the ability to reason, therefore correctness goes away too.

However, if we instead make the compiler smarter and give it the ability to reason the removal of guarantees, now we get to keep correctness whilst making the code much easier to work with.

Guarantees can be removed, they cannot be added without a proof.