July 26, 2021

On Monday, 26 July 2021 at 09:08:05 UTC, Dominikus Dittes Scherkl wrote:

>

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.

I agree that future versions of the code may not be memory-safe if favoriteNumber is changed, but that does not mean the current version is unsafe.

If you believe that the current version is unsafe, you should be able to demonstrate this unsafety by writing a @safe program that uses the current version to cause undefined behavior.

July 26, 2021

On Monday, 26 July 2021 at 11:02:48 UTC, Steven Schveighoffer wrote:

>

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;

...

If your theory of memory safety leads you to conclude that the presence or absence of a comment can make otherwise-unsafe code memory safe, you have taken a wrong turn somewhere in your reasoning.

I agree with you that the version with the comment is better, more maintainable code, and that we should hold our code to such standards in code review. But bad and hard-to-maintain code can still be memory safe (that is: free from possible UB).

July 26, 2021

On Monday, 26 July 2021 at 09:39:57 UTC, claptrap wrote:

>

On Monday, 26 July 2021 at 07:32:24 UTC, Paul Backus wrote:

>

@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.

Well, it is in a @trusted function, which is callable from @safe code, so any undefined behavior in the @system block is also possible undefined behavior in @safe code.

If you can write a call to favoriteElement from @safe code that causes UB, that would be sufficient to demonstrate that it is not memory safe. Of course, it only counts as a mistake in my example if you use the version I wrote, not your own modified version. :)

July 26, 2021

On Monday, 26 July 2021 at 13:26:56 UTC, Steven Schveighoffer wrote:

>

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.

Yes. You have argued, persuasively, that the language should infer these properties and others. IIUC, in a pervasive inference scenario, @safe/@trusted/@nogc/... annotations would function as programmer assertions: "if this property doesn't hold, error out". Couple this with Ali's @trusted-by-default proposal and you'd be living in a wonderful world (he says before walking off in to the unknown! :-) ).

>

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.

Definitely more to work out, but I now think that we have an opportunity to achieve a much bigger win than that implied by the initial proposal. It feels like there is a simple path forward patiently awaiting discovery.

July 26, 2021

On Monday, 26 July 2021 at 14:18:29 UTC, Bruce Carneal wrote:

>

On Monday, 26 July 2021 at 13:26:56 UTC, Steven Schveighoffer wrote:

>

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

Yes. You have argued, persuasively, that the language should infer these properties and others. IIUC, in a pervasive inference scenario, @safe/@trusted/@nogc/... annotations would function as programmer assertions: "if this property doesn't hold, error out". Couple this with Ali's @trusted-by-default proposal and you'd be living in a wonderful world (he says before walking off in to the unknown! :-) ).

Rather, "if this compiler can't prove that the property holds, error out".

July 26, 2021

On Monday, 26 July 2021 at 13:54:33 UTC, Paul Backus wrote:

>

On Monday, 26 July 2021 at 11:02:48 UTC, Steven Schveighoffer wrote:

>

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;

...

If your theory of memory safety leads you to conclude that the presence or absence of a comment can make otherwise-unsafe code memory safe, you have taken a wrong turn somewhere in your reasoning.

It's not a comment, it's a specification. Whereby I can conclude that if in review favoriteNumber returns something other than 0 to 49, it is in error. Without specifications, exactly zero trusted lines of code can be written.

>

I agree with you that the version with the comment is better, more maintainable code, and that we should hold our code to such standards in code review. But bad and hard-to-maintain code can still be memory safe (that is: free from possible UB).

Consider that the posix function read has the specification that it will read data from a file descriptor, put the data into a passed-in buffer, up to the amount of bytes indicated in the third parameter. Its prototype is:

@system extern(C) int read(int fd, void *ptr, size_t nBytes);

Without reading the code of read, you must conclude from the specification that it does what it says it should do, and not say, ignore nBytes and just use the pointed-at data for as many bytes as it wants. Without the specification, just relying on the types, you can conclude nothing, and can never use read from @trusted code, ever.

It's no different from favoriteNumber. In order to use it and make the assumption that it always will return 42, the author of that function must agree that that is what it's going to do. Otherwise (as you rightly say), anyone can change it to return something else legitimately and that might be beyond the bounds of the array you are using it for an index.

So without the specification for favoriteNumber, I must conclude that favoriteElement is invalid as written. With a specification I can reason about what does and does not constitute validity.

-Steve

July 26, 2021

On Monday, 26 July 2021 at 13:58:46 UTC, Paul Backus wrote:

>

On Monday, 26 July 2021 at 09:39:57 UTC, claptrap wrote:

>

On Monday, 26 July 2021 at 07:32:24 UTC, Paul Backus wrote:

>

@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.

Well, it is in a @trusted function, which is callable from @safe code, so any undefined behavior in the @system block is also possible undefined behavior in @safe code.

If you can write a call to favoriteElement from @safe code that causes UB, that would be sufficient to demonstrate that it is not memory safe. Of course, it only counts as a mistake in my example if you use the version I wrote, not your own modified version. :)

Its a pointless exercise because your example is a red herring, but this breaks it.

ref int[50] ohYeah() @trusted
{
    return *(cast(int[50]*) 123456);
}

int redHerring() @safe
{
    return favoriteElement(ohYeah());
}

See what we've learnt? That trusted / system etc can break safety. Top down, or bottom up. Its a house of cards, you cant escape that, unless you get rid of trusted and system completely.

Who knew? :)

Another way to think about it is that you are conflating "memory safe by convention" with "memory safe by compiler". Your example is memory safe by convention, IE, it is only so because the programmer has checked favouriteNumber doesnt break favouriteElement. So when you change favouriteNumber to 52 you are violating "safe by convention". You are not violating "safe by compiler". IE when you change favouriteNumber it doesnt change anything in terms of what is checked by the compiler. Or in terms of runtime checks. At least AFAIK.

I wonder what it is you expect the compiler to do.

And TBH I'm not even sure what your overall point is.

July 26, 2021

On Monday, 26 July 2021 at 16:26:53 UTC, claptrap wrote:

>

Its a pointless exercise because your example is a red herring, but this breaks it.
...
And TBH I'm not even sure what your overall point is.

It's a response to overly strong claims about what this DIP will achieve:

https://forum.dlang.org/post/fnhvydmbguyagcmaepih@forum.dlang.org

>

It is a response to the claim that "the compiler's assertions regarding your remaining @safe code might actually mean something." They mean exactly the same thing with your proposal as they do without it: that the @safe portion of the program does not violate the language's memory-safety invariants directly.

And it's again from the perspective of someone reviewing a patch rather than someone troubleshooting a bug. Once there is a memory error in your program, then @safe helps you by telling you to look elsewhere for the direct violation. If you are reviewing patches with an eye towards not including a memory error in your program, then @safe matters a lot less.

July 26, 2021
On 7/26/2021 1:21 AM, ShadoLight wrote:
> On Sunday, 25 July 2021 at 12:01:01 UTC, Walter Bright wrote:
>> The user could silence this error by adding an empty @system block:
>>
>>     @system { }
> 
> ...or rather simply marked as a @safe function then?


It's still possible that the programmer wants to keep it @trusted because it's doing things not catchable by the safety checks.
July 26, 2021
On 7/25/2021 8:46 PM, Timon Gehr wrote:
> The documentation no longer says much about that.
> https://github.com/dlang/dlang.org/pull/2453#commitcomment-53328593
> 
> Probably we should fix that soon.

https://github.com/dlang/dlang.org/pull/3076