June 17, 2021

On Thursday, 17 June 2021 at 21:16:02 UTC, ag0aep6g wrote:

>

On Thursday, 17 June 2021 at 21:00:13 UTC, Paul Backus wrote:

>

On Thursday, 17 June 2021 at 20:42:20 UTC, Ola Fosheim Grøstad wrote:

>

On Thursday, 17 June 2021 at 20:33:33 UTC, Paul Backus wrote:

>

Assuming [issue 20941][1] is fixed, yes.

[…]

>

Yes.
[...]
The interpretation that I and ag0aep6g have been describing is the correct one.

Yet I would answer "no" where you answered "yes" above.

The question was: "Yes, but if I make size() @trusted and fix the bug then interface is provably safe?".

The corresponding code:

[...]

>

In my opinion, that code is fundamentally equivalent to this (regarding the safety of get):

int get(int* ptr, int offset) @trusted { return ptr[offset]; }

That function does not have a safe interface, because it exhibits undefined behavior wenn called like get(new int, 1000), which @safe code can do.

In current D, yes, because issue 20941 means that private cannot be relied upon for encapsulation--thus the caveat.

However, if we assume for the sake for argument that @safe code can't bypass private, then it is possible to prove that the invariant offset < 2 is maintained by examining only code in the module where offset is defined. And once we've proven that invariant, we can prove that get is always memory safe when called from @safe code.

I will grant that, even in this hypothetical, get still would not satisfy the definition of "safe interface" currently given in the language spec--but at that point, who cares? The current definition is valid for the current language, but if the language changes, the definition ought to be updated too.

June 17, 2021

On Thursday, 17 June 2021 at 22:03:47 UTC, Paul Backus wrote:

>

However, if we assume for the sake for argument that @safe code can't bypass private, then it is possible to prove that the invariant offset < 2 is maintained by examining only code in the module where offset is defined. And once we've proven that invariant, we can prove that get is always memory safe when called from @safe code.

Not when new (@safe) code is added to the same module. E.g., the new guy adds an @safe method that has the bug from Ola's original code (offset = 2;).

>

I will grant that, even in this hypothetical, get still would not satisfy the definition of "safe interface" currently given in the language spec--but at that point, who cares? The current definition is valid for the current language, but if the language changes, the definition ought to be updated too.

If the spec is ever changed to say that an @trusted function taints the module it's in, then sure. But until that happens, I maintain that @trusted code is not allowed to rely on an external integer for safety, including private ones.

I'm not saying that that's the best way to define @trusted. But I believe that it's in our best interest to acknowledge the spec, and that no one really bothers following it. That way everyone is on the same page (we don't need any more confusion when it comes to @trusted), and it gives DIP 1035 and other proposals more oomph, because it's clear that the status quo isn't good enough.

If everyone pretends that the spec agrees with their personal take on @trusted, then there is no perceived need to fix anything. People with slightly different interpretations will keep talking past each other. Newbies will keep having a hard time.

June 18, 2021
On Thursday, 17 June 2021 at 17:14:12 UTC, Paul Backus wrote:
> On Thursday, 17 June 2021 at 16:50:28 UTC, Paolo Invernizzi wrote:
>> On Thursday, 17 June 2021 at 16:21:53 UTC, Paul Backus wrote:
...
>
> Yes, that's exactly my point. This can't be solved by changing the language, but it *can* be solved by a good code review process. So we should avoid wasting our time on language-based solutions (like Steven's proposal for `@system` blocks in `@trusted` functions), and instead focus on how to improve our code review process so that this kind of brittle `@trusted` code doesn't slip through.

I don't consider it a waste of time to search for language upgrades that would reduce the need for expert code review.  I trust experts significantly less than I trust automated checking (in this context I am one of those less trusted "expert"s).

I like where Steven's proposal was headed, if I understood it correctly, and have a variant to put forward that should be opt-in, with an uncluttered syntax and clear semantics for the long term, or so I believe.

I suggest that we discuss the topic at beerconf where, with any luck, we can converge quickly on understanding.

> ...



June 18, 2021

On Thursday, 17 June 2021 at 21:19:32 UTC, Ola Fosheim Grøstad wrote:

>

On Wednesday, 16 June 2021 at 23:52:02 UTC, Bruce Carneal wrote:

>

If I understand your meaning here, I disagree. I think @safe/@trusted is very useful, essential even, in code bases that are changing. It is a demarcation tool that lets us carve out ever larger safe areas.

Ok, I think I understand better what you meant now.

...

>

So basically one wants @trusted code to be checked by the compiler just like @safe, and then instead explicitly turn off the checking in a more narrow unsafe region within the @trusted method.

Yep. I think there's a clean opt-in way to do it that should wear well going forward. If you're at beerconf we can discuss it and your and other alternatives.

>

..

June 17, 2021
You're right that the way to unittest file I/O is to use mock files.
June 17, 2021
On 6/17/2021 12:15 PM, Sönke Ludwig wrote:
> Am 16.06.2021 um 23:22 schrieb Walter Bright:
>> On 6/16/2021 6:09 AM, Sönke Ludwig wrote:
>>> There are 800 of these in vibe.d alone.
>>
>> That is concerning. But it isn't necessarily cause for redesigning @trusted. For example, I removed (in aggregate) a great deal of unsafe allocation code from the backend simply by moving all that code into one resizable array abstraction.
>>
>> Piece by piece, I've been removing the unsafe code from the backend. There really should be very, very little of it.
> 
> Many of them are external functions that are `@system` when they shouldn't have to be:
>                                        - `() @trusted { return typeid(string).getHash(&ln); }()));`
> - `() @trusted { return allocatorObject(GCAllocator.instance); } ();`
> - `() @trusted { GC.addRange(mem.ptr, ElemSlotSize); } ()`
> - `() @trusted { return sanitize(ustr); } ()`
> - `() @trusted { return logicalProcessorCount(); } ()`
> - ...
> 
> It could be that nowadays a number of those has been made `@safe` already, I'd have to check one-by-one.
> 
> Then there are OS/runtime functions that are not `@safe`, but need to be called from a `@safe` context:
> 
> - `() @trusted { return mkstemps(templ.ptr, cast(int)suffix.length); } ();`
> - ```
>      @trusted {
>          scope (failure) assert(false);
>          return CreateFileW(...);
>      } ();
>      ```
> - ...
> 
> There is also quite some manual memory management that requires `@trusted`. Once we are there with ownership (and ten compiler versions ahead) those can be replaced by some kind custom reference type.
> 
> Then there are some shortcut references as pointers that are necessary because `ref` can't be used for local symbols (lifetime analysis could solve this, too):
> 
> - `auto slot = () @trusted { return &m_core.m_handles[h]; } ();`
> 
> There are surely some places that can be refactored to push `@trusted` further down, but right now most of them can't in a meaningful way.

Things like logicalProcessorCount() surely can be @safe.

m_core.m_handles[h] looks like it needs encapsulation in a proper function that takes m_core and h as arguments.

I got rid of a *lot* of memory management code in the back end by creating a container type to do it and prevent a safe interface.

Unsafe system calls like CreateFileW() can be encapsulated with a wrapper that presents a safe interface.

Yes, this is extra work. But it's good work. I bet you'll like the result! I sure have when I've done it.

June 18, 2021

On Friday, 18 June 2021 at 01:13:47 UTC, Bruce Carneal wrote:

>

Yep. I think there's a clean opt-in way to do it that should wear well going forward. If you're at beerconf we can discuss it and your and other alternatives.

Maybe it is better to mark the whole class as @trusted, have all methods checked and mark the unsafe regions with the invariants they rely on.

Maybe automated proofs of @safe methods would be possible if invariants for a class were made explicit.

(I will be on a weak mobile link in the summer, not suitable for video, but Beerconf sounds like a great idea!)

June 18, 2021
On 6/17/21 3:39 AM, Walter Bright wrote:
> On 6/16/2021 2:25 PM, Timon Gehr wrote:
>> Yes. This.
> 
> At last, Timon, we agree on something! You've made my day!

We agree on many things. Maybe I should point it out more often. :)
June 18, 2021
On Wednesday, 16 June 2021 at 13:17:41 UTC, Steven Schveighoffer wrote:
> I would support @trusted blocks, as long as we can have @system variables (DIP1035) and variables declared inside a @trusted block were implicitly @system.

That would be great if both reading and writing those local @system variables wouldn't compile in @safe only code. So it would require another @trusted block any time those variables were used. That could be the holy grail of supporting compiler checking of all @safe operations even in a function that does unsafe stuff.

June 18, 2021
On 6/18/2021 2:41 AM, Timon Gehr wrote:
> On 6/17/21 3:39 AM, Walter Bright wrote:
>> On 6/16/2021 2:25 PM, Timon Gehr wrote:
>>> Yes. This.
>>
>> At last, Timon, we agree on something! You've made my day!
> 
> We agree on many things. Maybe I should point it out more often. :)

<g>