June 18, 2021
On Thursday, 17 June 2021 at 10:26:07 UTC, Walter Bright wrote:
> For ImportC, it's going to be @system. But that may get relaxed in the future by having the compiler infer the safety by analyzing the function bodies, if they are provided.

Consider a convenient syntax for asserting the @trustedness of ImportC'd functions?
June 18, 2021
On Thursday, 17 June 2021 at 10:28:42 UTC, Ola Fosheim Grøstad wrote:
> it could be helpful to list the invariants unsafe code depends on, e.g.:
>
>
> ```
> @unsafe(assumes_singlethreaded){
>    …fast update of shared datastructure…
> }
>
> @unsafe(pointer_packing, pointer_arithmetics){

This also opens the door to more sophisticated compiler checking.  E.G. an @unsafe(pointer packing, pointer arithmetic) function can call an @unsafe(pointer arithmetic) function, but not an @unsafe(assumes singlethreaded) function.
June 18, 2021
On 6/18/2021 3:35 PM, Elronnd wrote:
> Consider a convenient syntax for asserting the @trustedness of ImportC'd functions?

We already have that. It's DasBetterC!
June 19, 2021

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

>

Indeed. But if you think about C functions that require arrays of zero terminated strings… Ok, you can create a simple @trusted wrapper, but then that wrapper has to check that all the strings are zero terminated, which adds unacceptable overhead. So even in this trivial example the @trusted code has to assume that the provided data structure is correct, and thus it enables @safe code to make correct @trusted code unsafe.

There are always trade offs. The best it is for trusted code to check the input arguments, and output too. We also have for this contract programming luckily. If you want performance, then it is really upon the owner of the project to decide. In worst case trusted at least marks pieces of code that need extra care during review and from testing point of view.

>

It gets even more complicated in real system level programming where you might make a function @trusted because you know that when this function is called no other threads are running. That is an assumption about an invariant bound to time.

Proving things about timelines and concurrency is difficult/impossible. So, in practice, the correctness of @trusted is ad hoc, cannot be assumed to be local and requires audits as the code base changes.
Correct me if I'm wrong but this is also true for @safe functions, since safe is about memory mainly, not concurrency.

But it could be helpful to list the invariants unsafe code depends on, e.g.:

@unsafe(assumes_singlethreaded){
   …fast update of shared datastructure…
}

@unsafe(pointer_packing, pointer_arithmetics){
 …
}

@unsafe(innocent_compiler_workaround){
 …
}

This may work if safety system offers safety not only for memory. I think you could rename unsafe to trusted, implying that underlying function is aware of the issue and resolves it at runtime somehow.

>

Now you have something to scan for. Like, in testing you could inject a check before the code that assumes no threads to be running. If you build with GC then you can scan all used libraries that does tricks with pointers and so on.
The thing about trusted per my understanding is that it talks about inner code of the function itself, not behavior of the calling function. If you want safety, for input arguments, than call it from within a safe function.

For true system level programming something like this (or more advanced) is needed for people to use it. Otherwise just slapping @system on all the code is the easier option. There has to be some significant benefits if you want programmers to add visual noise to their codebase.

Well, it might be for true systems programming, but let's not forget that we have other use cases for D, such as GUI apps, web apps, console apps, and a plethora of other uses which might not necessarily, require every inch of performance to be squeezed, and more focus on convenience and better safety for lower cost of developing the product.

In summary, we do need to improve the @trusted functionality, and best to account for all use cases of D or at least to have a consistent and easy to use (not misuse) feature.

P.S. I really try to avoid use of trusted lambdas as much as possible, but sometimes I can't, and then I have the choice, either to use lambda, or slap entire function as trusted which I hate. And no extracting a two words unsafe operation into separate method, from a four word method, is not an appealing solution for me.

June 19, 2021
Am 18.06.2021 um 04:07 schrieb Walter Bright:
> (...)
> 
> m_core.m_handles[h] looks like it needs encapsulation in a proper function that takes m_core and h as arguments.

Accessing `m_core.m_handles[h]` is `@safe`, just taking the address of the result is not. `scope slot = ...` might make it work in this particular case, but of course only with the appropriate compiler version and `-preview` switch.

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

The problem here is just escaping references to contained items. At some point in the future, with DIP25/DIP1000 enabled by default, this will hopefully become a non-issue.

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

The code that calls it *is* the `@safe` wrapper ;)  (more or less, it does a little bit more than that - but adding another wrapper in-between wouldn't really add anything apart from complexity, because the function is only used in a single place)
June 20, 2021
On Saturday, 19 June 2021 at 21:19:29 UTC, Sönke Ludwig wrote:

> The code that calls it *is* the `@safe` wrapper ;)  (more or less, it does a little bit more than that - but adding another wrapper in-between wouldn't really add anything apart from complexity, because the function is only used in a single place)

I agree. The whole point of having free variables is to avoid useless explicit interfaces for local blocks of code. If they ban trusted lambdas/blocks, the next logical step is to ban free variables overall.
June 20, 2021

Thanks for this solution!

June 20, 2021

On Wednesday, 16 June 2021 at 13:00:07 UTC, kinke wrote:

>

Absolutely love it, I've wanted this for ages, similar to C# unsafe {} blocks. I absolutely hate the trusted lambdas 'idiom'.

I completely agree.

June 23, 2021
On 6/17/21 2:18 PM, Walter Bright wrote:
> On 6/17/2021 8:49 AM, Andrei Alexandrescu wrote:
>> I think the whole discussion should be redirected toward simplifying `pure` instead.
>>
>> * There are many legitimate reasons to want impure code act as pure.
>> * There is no easy recourse as there is for @trusted. All approaches are crazily convoluted.
> 
> There are ways to do it that are in use in Phobos. It involves doing an unsafe cast.

Problem is there's a lot more work than trusted casts.

> Doing things like that is why D supports @system code.

Non-sequitur. The problem is there is no @system/@trusted/@safe troika for pure. It's either pure or not, no way to express (as is needed in key parts) "this function shall be trusted to be pure".

> I'm uncomfortable making it too easy to defeat the semantics of pure.

This is a misunderstanding. That wasn't asked for.

You transferred your answer to the @trusted blocks discussion to a different question.
June 23, 2021
On Wednesday, 23 June 2021 at 06:25:08 UTC, Andrei Alexandrescu wrote:
> [snip]
>> Doing things like that is why D supports @system code.
>
> Non-sequitur. The problem is there is no @system/@trusted/@safe troika for pure. It's either pure or not, no way to express (as is needed in key parts) "this function shall be trusted to be pure".
> [snip]

Reminds me of C's restrict. It's kind of like the equivalent of trusting that you are not overlapping data. I don't believe it provides a compile-time error if you do (just run-time undefined behavior).