January 16, 2020
On 16.01.20 02:43, Joseph Rushton Wakeling wrote:
> 
> Do you seriously not see any difference between an annotation that tells you: "this function should be memory-safe, and the compiler will attempt to validate this to the best of its ability" versus, "this function should be memory-safe, but the compiler will not make any attempt to validate that"?  And do you seriously not see any value in having that distinction clear?

It's an implementation detail. If you care about the distinction, you should check out the function's implementation, not its signature.
January 16, 2020
On Thursday, 16 January 2020 at 01:53:18 UTC, Timon Gehr wrote:
> It's an implementation detail. If you care about the distinction, you should check out the function's implementation, not its signature.

Sure. But on a practical day-to-day basis, @safe vs @trusted signatures help to prioritize one's allocation of care somewhat.

I'm coming to the conclusion that much of the differences of opinion in this thread are between folks who want to see things as absolutes, and folks who recognize that these features are tools for mitigating risk, not eliminating it.

January 16, 2020
On 16.01.20 03:06, Joseph Rushton Wakeling wrote:
> On Thursday, 16 January 2020 at 01:53:18 UTC, Timon Gehr wrote:
>> It's an implementation detail. If you care about the distinction, you should check out the function's implementation, not its signature.
> 
> Sure. But on a practical day-to-day basis, @safe vs @trusted signatures help to prioritize one's allocation of care somewhat.
> ...

You have to be careful when writing a @trusted function, not when calling it. If you do not trust a given library, there is no reason to be more careful around a @trusted API than around a @safe API, as they do not mean different things.

@safe does not fully eliminate risk of memory corruption in practice, but that does not mean there is anything non-absolute about the specifications of the attributes. As I am sure you understand, if you see a @safe function signature, you don't know that its implementation is not a single @trusted function call, so the difference in signature is meaningless unless you adhere to specific conventions (which the library you will be considering to use as a dependency most likely will not do).


> I'm coming to the conclusion that much of the differences of opinion in this thread are between folks who want to see things as absolutes, and folks who recognize that these features are tools for mitigating risk, not eliminating it.
> 

I was not able to figure out a response to this sentence that is both polite and honest.
January 16, 2020
On Thursday, 16 January 2020 at 01:32:23 UTC, H. S. Teoh wrote:
> Hogwash. Did you even test this before making statements like that?
>
> 	void fun(void function() @safe dg) { }
>
> 	void trustme() @trusted { }
>
> 	void main() {
> 		fun(&trustme);
> 	}
>
> Compiles fine.

You’re right. I feel like a moron now.

If I am not mistaken, this is the only example of covariant function attributes.
January 16, 2020
On Wednesday, 15 January 2020 at 23:24:38 UTC, IGotD- wrote:
> On Wednesday, 15 January 2020 at 23:01:57 UTC, Joseph Rushton Wakeling wrote:
>>
>> Presumably your programs are therefore self-crafted binary, since you couldn't possibly trust the humans who wrote the standard library to write valid code, or the compiler writers to translate it correctly into machine instructions? :-)
>>
>
> @safe is a subset of D that guarantees no memory corruption. The only way to ensure this is if the compiler have all the source code (will object code also work?) and can check that all the calls are also @safe. If this condition is not met, it is not safe by definition. @trusted code has reduced memory guarantees and can also call unsafe code further along the line and therefore unsafe.

No, that's where you're wrong. @trusted gives the same guarantees than @safe. The only difference is that @safe can automatically be checked and @trusted cannot. ANY memory violation in a trusted code is a BUG and the responsibility of the programmer.
That's why @trusted is important and should be only applied to the parts that cannot be checked by the compiler.
Why limit then @trusted block to functions and not to scopes? Imo the call interface has a semantic that does not allow (or at least not encourage) to interact directly with data of the callers scope. All interactions have to be done via parameters which scopes and lifetimes are known. This is not the case with simple scopes. So the difference between the two is the ABI which adds some guarantees that a simple scope cannot (see Steven Schveighofer's example).




January 16, 2020
On Wednesday, 15 January 2020 at 16:54:58 UTC, Joseph Rushton Wakeling wrote:
> So here's the problem with this approach (which was mentioned by several people in the discussion): the actual safety of a function like this is usually down to the combination of the lines that (in your example) are both inside and outside the @trusted block.

The are two scenarios of memory corruption in a function with a @trusted block. Either @trusted section is incorrect, or the @trusted section is given incorrect input. Safe code that has no deal with @trusted code cannot compromise safety.

So while the culprit can be outside of @trusted block, it will lower the number of suspects. It will give you a good idea of the required safety checks.
January 16, 2020
On Thursday, 16 January 2020 at 10:44:56 UTC, Patrick Schluter wrote:
>
> No, that's where you're wrong. @trusted gives the same guarantees than @safe. The only difference is that @safe can automatically be checked and @trusted cannot. ANY memory violation in a trusted code is a BUG and the responsibility of the programmer.

Then we can remove @safe all together and trust the programmer to only use the safe subset of D.

> That's why @trusted is important and should be only applied to the parts that cannot be checked by the compiler.

Then trusted is as good as putting a comment in the code.

> All interactions have to be done via parameters which scopes and lifetimes are known. This is not the case with simple scopes. So the difference between the two is the ABI which adds some guarantees that a simple scope cannot (see Steven Schveighofer's example).

Yes, so if safe code can only call function with the safe attribute but can have @system blocks in it. This is the same thing as trusted. This is very similar to another language and I think it at least got that part right.



January 16, 2020
On Thursday, 16 January 2020 at 03:34:26 UTC, Timon Gehr wrote:
> You have to be careful when writing a @trusted function, not when calling it. If you do not trust a given library, there is no reason to be more careful around a @trusted API than around a @safe API, as they do not mean different things.

Thanks for being patient enough to clarify the issues here.  This helps to make much clearer the thinking behind the point of view that's been articulated elsewhere in this discussion, that the @trusted/@safe distinction is there for library maintainers rather than users.

I agree that it's _primarily_ there for maintainers, but I don't agree that it has _no_ value for users (more on that below).  But your observations do make clear how unreasonable my rather judgemental "I'm coming to the conclusion ..." remarks were, so apologies to everyone for that.

(It's no excuse, but I was quite tired when I wrote that, and so probably not exercising as much good judgement as I ought.)

> @safe does not fully eliminate risk of memory corruption in practice, but that does not mean there is anything non-absolute about the specifications of the attributes.

Would we be able to agree that the absolute part of the spec of both amounts to, "The emergence of a memory safety problem inside this function points to a bug either in the function itself or in the initialization of the data that is passed to it" ... ?

(In the latter case I'm thinking that e.g. one can have a perfectly, provably correct @safe function taking a slice as input, and its behaviour can still get messed up because the user initializes a slice in some crazy unsafe way and passes that in.)

> As I am sure you understand, if you see a @safe function signature, you don't know that its implementation is not a single @trusted function call

Yes, on this we agree.  (I even mentioned this case in one of my posts above.)

> so the difference in signature is meaningless unless you adhere to specific conventions

Here's where I think we start having a disagreement.  I think it is meaningful to be able to distinguish between "The compiler will attempt to validate the memory safety of this function to the extent possible given the @trusted assumptions injected by the developer" (which _might_ be the entirety of the function), versus "The safety of this function will definitely not be validated in any way by the compiler".

Obviously that's _more_ helpful to the library authors than users, but it's still informative to the user: it's saying that while the _worst case_ assumptions are the same (100% unvalidated), the best case are not.

> (which the library you will be considering to use as a dependency most likely will not do).

Obviously in general one should not assume virtue on the part of library developers.  But OTOH in a day-to-day practical working scenario, where one has to prioritize how often one wants to deep-dive into implementation details -- versus just taking a function's signature and docs at face value and only enquiring more deeply if something breaks -- it's always useful to have a small hint about the best vs. worst case scenarios.

It's not that @safe provides a stronger guarantee than @trusted, it's that @trusted makes clear that you are definitely in worst-case territory.  It's not a magic bullet, it's just another data point that helps inform the question of whether one might want to deep-dive up front or not (a decision which might be influenced by plenty of other factors besides memory safety concerns).

The distinction only becomes meaningless if one is unable to deep-dive and explore the library code.

>> I'm coming to the conclusion that much of the differences of opinion in this thread are between folks who want to see things as absolutes, and folks who recognize that these features are tools for mitigating risk, not eliminating it.
>> 
>
> I was not able to figure out a response to this sentence that is both polite and honest.

Well FWIW, don't feel the need to be polite to me if you don't think I deserve it :-)  But in any case, apologies again to everyone for those remarks.  They were unfair and based on a misinterpretation of the positions being articulated.
January 16, 2020
On Thursday, 16 January 2020 at 10:58:33 UTC, IGotD- wrote:
> On Thursday, 16 January 2020 at 10:44:56 UTC, Patrick Schluter wrote:
>>
>> No, that's where you're wrong. @trusted gives the same guarantees than @safe. The only difference is that @safe can automatically be checked and @trusted cannot. ANY memory violation in a trusted code is a BUG and the responsibility of the programmer.
>
> Then we can remove @safe all together and trust the programmer to only use the safe subset of D.

The difference between "a small subset of the program must be manually verified in order to guarantee memory safety" and "the entire program must be manually verified in order to guarantee memory safety" is not insignificant.
January 16, 2020
On Thursday, 16 January 2020 at 14:46:15 UTC, Paul Backus wrote:
> On Thursday, 16 January 2020 at 10:58:33 UTC, IGotD- wrote:
>> Then we can remove @safe all together and trust the programmer to only use the safe subset of D.
>
> The difference between "a small subset of the program must be manually verified in order to guarantee memory safety" and "the entire program must be manually verified in order to guarantee memory safety" is not insignificant.

If memory-safety is the default then you only need to mark functions and code blocks as unsafe. No need for @trusted or @safe.