3 days ago
On Monday, 12 May 2025 at 21:38:28 UTC, Walter Bright wrote:
> It never made it into the C++ Standard, and its only use is CLI.

So what.

It is a commercial success in the Windows developer community, to the point Microsoft even diverted resources from C++23 development, to improve C++20 compliance on C++/CLI, as communicated by Microsoft employees, as some of the reasons regarding the C++23 support delays.

GCC and clang also have lots of compiler extensions that never made into the C or C++ standard, and only exist in one of them. To the point Google invested lots of money to make some projects, like the Linux kernel, be able to compile with both compilers.

Unreal C++ extensions are also not into the C++ standard, they are only available on the most used games engine in the industry.

Are they also a failure?

If anything, this is a good example of the market fit that has been discussed in these threads, C++/CLI does one thing, and it is great at it, being a productive way to do C++ interop in .NET.


3 days ago

On Monday, 12 May 2025 at 19:28:10 UTC, Walter Bright wrote:

>

This comes about because old, being declared after ctx, has a shorter lifetime than ctx. If old has a destructor, that destructor will run before ctxs destructor, and ctx will be referring to an invalid instance of old.

You can't free a pointer that has aliases in @safe code. Therefore you can't simply have a destructor that performs a free(), the struct that has it needs to prevent aliasing by disabling copies with @disable this(this), or by providing a copy constructor that duplicates the pointer. Otherwise you allow memory corruption:

import std.stdio;
@safe:

struct S
{
    int* x;
    ~this() scope @trusted { writefln("~this(): free(%s)", cast(void*) x); }
}

void f(ref scope S ctx)
{
    {
    	auto old = ctx;
    }
    writefln("use %s", cast(void*) ctx.x);
}

void main()
{
    scope S s = S(new int(38));
    f(s);
}

This prints:

~this(): free(7F8D32557000)
use 7F8D32557000
~this(): free(7F8D32557000)

Both a 'use after free' and a 'double free'! But if you add this(this) scope { x = new int(*x); } to S, it works out.

>

If S does not have a destructor, does that make the error a false positive or not? I decided that the existence of a destructor should not change the scoping rules.

I agree with that, but in light of the above, I don't think a copy of a scope pointer should have its lifetime shortened to the destination variable.

It may be by design, but it's a false positive in the sense that it leads to unnecessary refactoring (like https://github.com/dlang/phobos/pull/8125), and to unnecessary @trusted code. The ctx = old example I gave is reduced from my actual code:
https://github.com/dkorpel/ctod/blob/1651fb4e31095e0cf5e0c4524149bdc2bcc7539e/source/ctod/cdeclaration.d#L231

If you have an alternate way to write that in a @safe way, I'd love to hear it.

>

BTW, thank you for your post. It's informative and excellent.

:)

14 hours ago
On Tue, 13 May 2025 at 04:42, Walter Bright via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> On 5/12/2025 3:55 AM, Manu wrote:
> > So, if it only works with @safe, I repeat again; WHY?
>
> So you can break the rules in @system code.
>

Don't write `scope` if you don't want it? What are the cases where this is a struggle?

We are trying to move towards @safe by default, but the new editions
> feature is
> needed first.


Again though, this really doesn't have anything much to do with @safe; the `scope` attribute is perfectly self-contained.


14 hours ago
On Tue, 13 May 2025 at 04:51, Walter Bright via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> On 5/12/2025 4:16 AM, Manu wrote:
> > `scope` has nothing to do with @safe, and it MUST work in its own right, otherwise the code is lying to the author, and it's an effective
> liability.
>
> An escape hatch is always needed.


Well the primary escape hatch is, obviously, just don't write `scope` if
it's not scope!
But I think you could divine an alternative escape hatch if required; like
`cast(ref T)myScopeT` or something. Or alternatively just `cast(T)myScopeT`
which might normally imply that a copy is made, but the language could
detect the identity cast and elide the copy...


> For example, you might want to interface with a 3rd party library that is scope-correct, but is not annotated with `scope`.
>

Okay sure; find another solution. This one is insane. I suggest some form
of cast().


4 hours ago

On Friday, 16 May 2025 at 01:27:18 UTC, Manu wrote:

>

Don't write scope if you don't want it? What are the cases where this is a struggle?

Lets say you have a function int* fun(return scope int* arg, uint flags).

You're calling it like

enum enumVal1 = /*...*/, enumVal2 = /*...*/, /*...*/, enumVal42 = /*...*/;

@system callingFunction()
{   int[16] localInts;
    // initialise localInts...
    static int* cache;
    if (cache == null)
    {   cache = fun(&localInts[enumVal1], enumVal12 | enumVal36);
    }
}

Under the current scope checking rules, result is going to be inferred as scope, because a scope argument (&localInts[enumVal1]) is assigned to a return scope parameter. Therefore, assigning it to a static variable wouldn't compile with scope checking on.

However, it might be the case that result is not actually pointing to the stack. Let's say fun will return arg only if a certain bit in flags is set, and the call in callingFunction is leaving that bit unset. In that case, the scope check would be returning a false error that you might want to override.

4 hours ago

On Friday, 16 May 2025 at 11:20:40 UTC, Dukc wrote:

>

Under the current scope checking rules, result is going to be inferred as scope, because a scope argument (&localInts[enumVal1]) is assigned to a return scope parameter. Therefore, assigning it to a static variable wouldn't compile with scope checking on.

I wrote this wrong due to editing the code example after writing this paragraph. Should be:

Under the current scope checking rules, the return value of fun is going to be inferred as scope, because a limited lifetime value (&localInts[enumVal1]) is assigned to it's return scope parameter. Therefore, assigning it to a static variable wouldn't compile with scope checking on.

3 hours ago
On Friday, 16 May 2025 at 01:27:18 UTC, Manu wrote:
> On Tue, 13 May 2025 at 04:42, Walter Bright via Digitalmars-d < digitalmars-d@puremagic.com> wrote:
>
>> On 5/12/2025 3:55 AM, Manu wrote:
>> > So, if it only works with @safe, I repeat again; WHY?
>>
>> So you can break the rules in @system code.
>>
>
> Don't write `scope` if you don't want it? What are the cases where this is a struggle?

https://forum.dlang.org/post/ixwrioxceojzwaoqaeom@forum.dlang.org
5 6 7 8 9 10 11 12 13 14 15
Next ›   Last »