July 26, 2021
On Monday, 26 July 2021 at 03:40:55 UTC, Timon Gehr wrote:
>
> The original claim was that the new feature is a tool that allows the code base to be properly segregated more easily, not that you can't still write incorrect @trusted code. If you have to review @safe code to ensure memory safety of your @trusted code, your @trusted code is incorrect.

@trusted code is correct if and only if it cannot possibly allow undefined behavior to be invoked in @safe code.

If my example is incorrect as-written, then you should be able to write a program that uses it, without modification, to cause undefined behavior in @safe code. Same for any given @trusted lambda.
July 26, 2021

On Sunday, 25 July 2021 at 12:05:10 UTC, Steven Schveighoffer wrote:

>

The name is the important change. A @safe function shouldn't require manual verification. A @trusted function does. The @safe function with @trusted escape gives the impression that the @safe parts don't need checking, but they do. It's also difficult to use tools to check which parts need review when focusing on memory safety.

Yes, I agree.
First I was skeptical about this DIP, but that I think is the important advantage above @trusted blocks. So I would support this DIP.

July 26, 2021
On Sunday, 25 July 2021 at 12:01:01 UTC, Walter Bright wrote:
>
> One solution would be for the compiler to check such @trusted functions for @safe-ty anyway, and issue an error for @trusted functions with no @system{} blocks and no @safe errors.
>
> The user could silence this error by adding an empty @system block:
>
>     @system { }

...or rather simply marked as a @safe function then?

July 26, 2021

On Sunday, 25 July 2021 at 23:50:12 UTC, Paul Backus wrote:

>

On Sunday, 25 July 2021 at 23:34:35 UTC, claptrap wrote:

>

Your argument the same as saying that bar() is memory safe as written. True, but it's not bug free. The bug is just waiting for the right set of circumstances to come to life and eat your face :)

IE. Memory safe as written != bug free

Yes; I agree completely. :)

The point of the example is to show that the proposal advanced in this thread does not prevent this type of bug from occurring.

You could probably come up with an example bug that wouldn't be caught by any system you can think of as long as you have an @system escape hatch. It doesnt really prove anything imo.

July 26, 2021

On Sunday, 25 July 2021 at 17:47:40 UTC, Paul Backus wrote:

>
@system {
   return array.ptr[favoriteNumber()];
}

I make the following claims:

  1. This code is memory-safe.

No, it's not. You use something that is not a literal, so it may change.
Even for a constant this should be checked for each new compile.
I would do that even if it actually were a literal, but here we have a function call!
The definition of the called function may be far away. How would this ever pass a review?
The only way to make this memory safe, is to actually test it:

@system {
   assert(array.length > favoriteNumber());
   return array.ptr[favoriteNumber()];
}
July 26, 2021
On 26.07.21 05:46, Timon Gehr wrote:
> On 26.07.21 02:21, ag0aep6g wrote:
[...]
>> The language doesn't have @trusted blocks. @trusted function literals (lambdas) are still functions. Everything the documentation says about @trusted functions applies to function literals.
> 
> The documentation no longer says much about that.
> https://github.com/dlang/dlang.org/pull/2453#commitcomment-53328593
> 
> Probably we should fix that soon.

That's just memory-safe-d.dd, which is an odd page that should be merged with function.dd. function.dd still says that @trusted functions must have safe interfaces.

https://dlang.org/spec/function.html#trusted-functions
July 26, 2021
On Monday, 26 July 2021 at 07:32:24 UTC, Paul Backus wrote:
> On Monday, 26 July 2021 at 03:40:55 UTC, Timon Gehr wrote:
>>
>> The original claim was that the new feature is a tool that allows the code base to be properly segregated more easily, not that you can't still write incorrect @trusted code. If you have to review @safe code to ensure memory safety of your @trusted code, your @trusted code is incorrect.
>
> @trusted code is correct if and only if it cannot possibly allow undefined behavior to be invoked in @safe code.

Your example doesn't invoke undefined behaviour in safe code, it invokes undefined behaviour in system code. The UB is in the system block. The memory corruption happens in the system block. After that all bets are off.

There's no way around that, which makes your example moot.


> If my example is incorrect as-written, then you should be able to write a program that uses it, without modification, to cause undefined behavior in @safe code. Same for any given @trusted lambda.

And that proves what? That you can write buggy system code that doesn't cause memory errors in some circumstances?


July 26, 2021

On Sunday, 25 July 2021 at 17:47:40 UTC, Paul Backus wrote:

>

On Sunday, 25 July 2021 at 16:29:38 UTC, Bruce Carneal wrote:

>

Machine advantage comes in other forms. Firstly, we now have a properly segregated code base. @safe always means 'machine checkable'. Zero procedural @trusted code review errors in that now easily identified class.

I have already demonstrated that this is false. Here's my example from the previous thread on this topic, rewritten slightly to use the new-style @trusted/@system syntax from your proposal:

module example;

size_t favoriteNumber() @safe { return 42; }

int favoriteElement(ref int[50] array) @trusted
{
    // This is memory safe because we know favoriteNumber returns 42
    @system {
        return array.ptr[favoriteNumber()];
    }
}

And I have already demonstrated, favoriteElement is invalid. You need to have a definition of what favoriteNumber does, and this needs to be reconciled with the definition of favoriteElement.

In this case, favoriteElement is invalid, because favoriteNumber has no formal specification. When reviewing favoriteElement, one must look at it like a black box:

/// Returns: a valid size_t
size_t favoriteNumber() @safe;

int favoriteElement(ref int[50] array) @trusted
{ /* code to review */ }

However, with a specification of favoriteNumber, favoriteElement can be reviewed as correct:

/// Returns: a size_t between 0 and 49, inclusive
size_t favoriteNumber() @safe;

...

Now, when reviewing favoriteElement, I can prove that it's a valid @trusted function given the formal definition of favoriteNumber. If reviewing favoriteNumber, I can reconcile the implementation changes against the spec for it, and know that as long as I follow the spec, I will not mess up any other code. If the spec changes, now you have to re-review anything that uses it (including other @safe code) for correctness.

As I said before, code reviews of @safe functions are still required for correctness, just not for memory safety.

-Steve

July 26, 2021

On Sunday, 25 July 2021 at 13:14:20 UTC, jfondren wrote:

>

OK. I'll argue the opposite position for a bit, then.

Here's a @trusted function with a non-@safe component:

ulong getAvailableDiskSpace(scope const(char)[] path) @trusted
{
    ULARGE_INTEGER freeBytesAvailable;
    auto err = GetDiskFreeSpaceExW(path.tempCStringW(), &freeBytesAvailable, null, null);
    cenforce(err != 0, "Cannot get available disk space");
    return freeBytesAvailable.QuadPart;
}

Yep. This function today is overly trusted (meaning that parts that can be at least partly mechanically checked are allowed to be checked.

>

With this proposal, I imagine:

ulong getAvailableDiskSpace(scope const(char)[] path) @trusted
{
    ULARGE_INTEGER freeBytesAvailable;
    auto err = @system GetDiskFreeSpaceExW(path.tempCStringW(), &freeBytesAvailable, null, null);  // expression usage?
    @system{ auto err = GetDiskFreeSpaceExW(path.tempCStringW(), &freeBytesAvailable, null, null); }  // scopeless block?
    cenforce(err != 0, "Cannot get available disk space");
    return freeBytesAvailable.QuadPart;
}

Yes, that's about right. The exact semantics are TBD (scope or no scope, expressions or statements, etc.).

[snip]

>

Does that sound about right?

I think all of what you are saying is along the same lines as what I'm thinking (though I look at it more as pragmatic reasoning for how to write such functions rather than some "blessed" way to do things).

-Steve

July 26, 2021

On Sunday, 25 July 2021 at 12:05:10 UTC, Steven Schveighoffer wrote:

>

On Sunday, 25 July 2021 at 06:13:41 UTC, jfondren wrote:

>

I appreciate that there's a vision also to @safe/@trusted/@system, but it doesn't seem to have stuck, with Phobos having more than twice as many @trusted lambdas than @trusted functions:

phobos$ grep -rP '\W\(\) @trusted' --include '*.d'|wc -l
238
phobos$ grep -rP '\w\(\) @trusted' --include '*.d'|wc -l
111

@trusted lambdas are required inside templates where you want code to be @safe when the type parameters allow it. The resulting function itself needs to be marked @trusted with the lambdas replaced with @system blocks to achieve the same effect, as memory safety review is still needed.

One thing that is incredibly important to get right here is the way to specify what to do with templates. I've been thinking about this a bit, and even this isn't the right way to do things (specify the function as @trusted and mark the actual trusted part as @system), because you want the compiler to infer @system for certain instantiations, and @trusted for others.

What we need is a way to say "this function should be @trusted iff certain sections of code are inferred @safe".

Perhaps the correct mechanism here is to encapsulate the @trusted parts into separate functions, and make sure the API is @safe (e.g. static inner functions).

I think it would be too confusing to allow @system blocks inside inferred templates.

-Steve