June 16, 2021
On Wednesday, 16 June 2021 at 21:47:55 UTC, jmh530 wrote:
> On Wednesday, 16 June 2021 at 21:22:32 UTC, Walter Bright wrote:
>> [snip]
>>> `@trusted` *should* probably not even be available for functions (of course it is not a desirable breaking change to disallow that now, though).
>>
>> The idea is to encourage programmers to think about organizing code so that there are clear separations between safe and system code. Interleaving the two on a line-by-line basis defeats the purpose.
>
> This is a better argument against @trusted blocks within @safe blocks than it is against @system blocks within @trusted code.

I'd love to see those gone as well but it could be hard to get there from here.

It's easier to validate simply nested rather than finely interwoven dependencies.

I hope we can start reversing course rather than moving further down the "convenience over practical safety" path.

June 16, 2021
On Wednesday, 16 June 2021 at 22:02:18 UTC, Bruce Carneal wrote:
> On Wednesday, 16 June 2021 at 21:47:55 UTC, jmh530 wrote:
>> On Wednesday, 16 June 2021 at 21:22:32 UTC, Walter Bright wrote:
>>> [snip]
>>>> [...]
>>>
>>> The idea is to encourage programmers to think about organizing code so that there are clear separations between safe and system code. Interleaving the two on a line-by-line basis defeats the purpose.
>>
>> This is a better argument against @trusted blocks within @safe blocks than it is against @system blocks within @trusted code.
>
> I'd love to see those gone as well but it could be hard to get there from here.
>
> It's easier to validate simply nested rather than finely interwoven dependencies.
>
> I hope we can start reversing course rather than moving further down the "convenience over practical safety" path.

Where do you make the distinction between convenience and practicality in this context?
June 16, 2021
On Wednesday, 16 June 2021 at 21:55:20 UTC, Bruce Carneal wrote:
> In the "bikeshedding" proposal @safe code need not be checked manually while the @trusted code, which already needed to be checked manually, will now enjoy a narrowing of focus.
>
> Perhaps I'm missing something here.  If so, please enlighten me as to the advantages of the "non-bikeshedding" approach and/or the errors in my logic.

The whole concept is kinda broken. If you have an unsafe region in a method then that may effect not only that method, but the class and all other methods. So basically the whole class, or maybe even the whole module, should be flagged as "@trusted".

But there is no reason to, as that can be deduced. And the explicit tags do not imply when it was checked nor does it say anything about whether the code in the class has changed after it was checked.

So what is good for?

For it to work you only need @unsafe markers that are as tight as possible, but with more detail of the nature of unsafety. For instance, some unsafe operations such as SIMD/casting optimizations can be guranteed to have only local effect. If they hinder @safe then that is just a compiler weakness, so you have to disable it to get past it. On the other hand, more global hacks... are quite different in nature.

As there is no way to express the nature of "unsafety", or whether it has been checked and what the edit timeline is for the surrounding code, it is not much more useful than a comment. Which renders the feature more annoying than useful.

Tight @unsafe is no worse than the D regime. More detailed information about the reason for why the region is marked @unsafe and when it was checked would be infinitely more useful than what D is doing now.

June 16, 2021
On Wednesday, 16 June 2021 at 22:10:38 UTC, max haughton wrote:
> On Wednesday, 16 June 2021 at 22:02:18 UTC, Bruce Carneal wrote:
>> On Wednesday, 16 June 2021 at 21:47:55 UTC, jmh530 wrote:
>>> On Wednesday, 16 June 2021 at 21:22:32 UTC, Walter Bright wrote:
>>>> [snip]
>>>>> [...]
>>>>
>>>> The idea is to encourage programmers to think about organizing code so that there are clear separations between safe and system code. Interleaving the two on a line-by-line basis defeats the purpose.
>>>
>>> This is a better argument against @trusted blocks within @safe blocks than it is against @system blocks within @trusted code.
>>
>> I'd love to see those gone as well but it could be hard to get there from here.
>>
>> It's easier to validate simply nested rather than finely interwoven dependencies.
>>
>> I hope we can start reversing course rather than moving further down the "convenience over practical safety" path.
>
> Where do you make the distinction between convenience and practicality in this context?

"practical safety" was meant to signify "machine checked safety", as in "if humans are actively involved it is likely not safe".  Should have been more specific.

Addressing what I believe you're asking, around my confusing formulation, I dont think that we have to choose between ease of use and safety in this case.  If we move to @safe checking by default within @trusted code we get additional safety with more localized (easier) manual checking.

I think the opt-in scheme I proposed (@system blocks trigger @safe checking) would be backward compatible and also readable/maintainable going forward.

June 16, 2021
On Wednesday, 16 June 2021 at 22:21:22 UTC, Ola Fosheim Grøstad wrote:
> On Wednesday, 16 June 2021 at 21:55:20 UTC, Bruce Carneal wrote:
>> In the "bikeshedding" proposal @safe code need not be checked manually while the @trusted code, which already needed to be checked manually, will now enjoy a narrowing of focus.
>>
>> Perhaps I'm missing something here.  If so, please enlighten me as to the advantages of the "non-bikeshedding" approach and/or the errors in my logic.
>
> The whole concept is kinda broken. If you have an unsafe region in a method then that may effect not only that method, but the class and all other methods. So basically the whole class, or maybe even the whole module, should be flagged as "@trusted".

We all work to isolate dependencies, safety related and otherwise, so that we can reason about the whole with more confidence.  Whenever we introduce something that impedes our ability to "treeify" dependencies, something that makes analysis more of a graph analysis than a tree analysis, we've done something that has made maintenance and code-reuse more difficult.

At the language level we can't stop programmers from writing code with nasty dependencies but we can make it easier to write code with fewer entanglements.

>
> But there is no reason to, as that can be deduced. And the explicit tags do not imply when it was checked nor does it say anything about whether the code in the class has changed after it was checked.
>
> So what is good for?

Perhaps I misunderstand you but I'd say it's good for a lot. As a contrasting exercise one can think about what would happen if @safe/@trusted/@system became compiler noops starting tomorrow and forevermore.

Yes, I think things can be made better but there's already, to my way of thinking at least, a lot of value.

>
> For it to work you only need @unsafe markers that are as tight as possible, but with more detail of the nature of unsafety. ...

I think that finer granularity/specificity might be useful, particularly if can improve basic readability/nesting.

June 16, 2021

On Wednesday, 16 June 2021 at 11:38:54 UTC, RazvanN wrote:

>
void foo() @safe
{
    @trusted
    {
        int[100] a = void;
    }
    ...
}

What do you think?

It raises the question, that what is this going to do?

@trusted
{ // Is d @trusted?
  // Or is someDelegateProvider allowed to be @system?
  // Or both?
  void delegate(int) d = someDelegateProvider();
}
June 16, 2021
On Wednesday, 16 June 2021 at 22:54:51 UTC, Bruce Carneal wrote:
> We all work to isolate dependencies, safety related and otherwise, so that we can reason about the whole with more confidence.  Whenever we introduce something that impedes our ability to "treeify" dependencies, something that makes analysis more of a graph analysis than a tree analysis, we've done something that has made maintenance and code-reuse more difficult.

Well, but the problem is at a more fundamental level. When writing code we make assumptions about invariants on various levels. So when auditing unsafe code you audit it with respect to local and global invariants.

For instance, if I write a program with GC turned off as an invariant. Then I might audit code that packs information into lower bits of addresses in pointers values as safe. Then some other guy takes over the code base and decides to turn on the GC. Well, effectively the program is broken at a global level, because the actual scope of @trusted that we can be certain of is the whole program! :-D

>At the language level we can't stop programmers from writing
> code with nasty dependencies but we can make it easier to write code with fewer entanglements.

As long as people continue to modify, refactor, redesign and change invariants then you need something more explicit.

For instance if my unsafe region had been marked with a tag that said pointer-value-manipulation, and you have a timestamp on it, and you have an association between pointer-value-manipulation and turning on GC, then the compiler could start listing all the weak spots that has to go through a new audit.

But with no knowledge of WHY a region is unsafe, when it was audited and how/when the surrounding changed, the compiler can't do much, so we are left with a feature that essentially does nothing.

> Perhaps I misunderstand you but I'd say it's good for a lot. As a contrasting exercise one can think about what would happen if @safe/@trusted/@system became compiler noops starting tomorrow and forevermore.

No, @safe does something, but you cannot know what the scope of @trusted should be, because even global invariants can change. So you might as well do what other languages do and just put an "unsafe" compiler-bypass-checking-silencer on the offending statement/expression.

> Yes, I think things can be made better but there's already, to my way of thinking at least, a lot of value.

Ok, but it doesn't do anything more than a comment.

> I think that finer granularity/specificity might be useful, particularly if can improve basic readability/nesting.


For it to work, you need to list all the invariants that the audit of the unsafe region makes assumptions about.

With such a list you could actually trigger warnings about unsafe regions when the invariants change.

Scope is not really meaningful. The scope of the unsafe statement is unknown, because the code base is changing.



June 16, 2021
On Wednesday, 16 June 2021 at 23:15:19 UTC, Ola Fosheim Grøstad wrote:
> On Wednesday, 16 June 2021 at 22:54:51 UTC, Bruce Carneal wrote:
>> We all work to isolate dependencies, safety related and otherwise, so that we can reason about the whole with more confidence.  Whenever we introduce something that impedes our ability to "treeify" dependencies, something that makes analysis more of a graph analysis than a tree analysis, we've done something that has made maintenance and code-reuse more difficult.
>
> Well, but the problem is at a more fundamental level...

Fundamental problems sometimes admit incremental improvements towards resolution.  I'm more disposed to improvement-through-simplifying-but-possibly-large-rewrites than incremental change but in this case I'd go with incremental.

>
> For instance, if I write a program with GC turned off as an invariant. Then I might audit code that packs information into lower bits of addresses in pointers values as safe. Then some other guy takes over the code base and decides to turn on the GC. Well, effectively the program is broken at a global level, because the actual scope of @trusted that we can be certain of is the whole program! :-D
>

Sure, we have responsibility for the whole program.  Anything that lets us confidently subdivide that problem is welcome.

>>At the language level we can't stop programmers from writing
>> code with nasty dependencies but we can make it easier to write code with fewer entanglements.
>
> As long as people continue to modify, refactor, redesign and change invariants then you need something more explicit.

I disagree.  I believe that more general mechanisms can help that do not preclude the finer granularity mechanisms which you advocate (and which I am interested in).

>
> For instance if my unsafe region had been marked with a tag that said pointer-value-manipulation, and you have a timestamp on it, and you have ...

I believe providing the compiler with more information can be a very good thing, perhaps worthy of another thread.

>
>> Perhaps I misunderstand you but I'd say it's good for a lot. As a contrasting exercise one can think about what would happen if @safe/@trusted/@system became compiler noops starting tomorrow and forevermore.
>
> No, @safe does something, but you cannot know what the scope of @trusted should be, because even global invariants can change. So you might as well do what other languages do and just put an "unsafe" compiler-bypass-checking-silencer on the offending statement/expression.

Yes, @trusted works within a broader framework, a *manually managed hence dangerous* framework.  A practical path forward is to improve the compilers ability to check things and localize/minimize the unchecked.  As far as how the programmer deals with all the rest, well, I'd say we're back to "best practices" and "convention".

We all want the language/compiler to do more on the safety front, at least if improvements come at very little coding inconvenience, but something like an @trusted transition zone will be needed at the, evolving programmer defined, boundary between machine checkable and "you're on your own".

> ...
>> Yes, I think things can be made better but there's already, to my way of thinking at least, a lot of value.
>
> Ok, but it doesn't do anything more than a comment.

In line with my comments both above and below, I disagree.

>
>> I think that finer granularity/specificity might be useful, particularly if can improve basic readability/nesting.
>
>
> For it to work, you need to list all the invariants that the audit of the unsafe region makes assumptions about.
>
> With such a list you could actually trigger warnings about unsafe regions when the invariants change.

Yes.  The compiler will need enough information to act.

>
> Scope is not really meaningful. The scope of the unsafe statement is unknown, because the code base is changing.

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.

June 16, 2021
On 6/16/21 5:32 PM, Paul Backus wrote:
> On Wednesday, 16 June 2021 at 21:26:08 UTC, Bruce Carneal wrote:
>> I like the notion that others have mentioned of @safe checking by default within @trusted code (which would require @system blocks to disable checking).  Perhaps we could adopt an opt-in strategy where such @safe checking is triggered by the presence of an @system block.
> 
> Under this proposal, @system lambdas/blocks within @trusted code would have the exact same semantics as @trusted blocks/lambdas within @safe code currently do. It's pure bikeshedding.

Yes, and that leaves @safe code to actually not require manual checking, as opposed to today, where any @safe code with @trusted blocks today requires manual checking of all the @safe code (I agree just changing trusted/system code this way, and doing nothing with @safe would be bikeshedding).

In reality, @safe code should be a function of its inputs, and what is considered a safe input. With @trusted lambdas, the inputs are "everything".

-Steve
June 17, 2021
On Thursday, 17 June 2021 at 00:34:12 UTC, Steven Schveighoffer wrote:
> On 6/16/21 5:32 PM, Paul Backus wrote:
>> On Wednesday, 16 June 2021 at 21:26:08 UTC, Bruce Carneal wrote:
>>> I like the notion that others have mentioned of @safe checking by default within @trusted code (which would require @system blocks to disable checking).  Perhaps we could adopt an opt-in strategy where such @safe checking is triggered by the presence of an @system block.
>> 
>> Under this proposal, @system lambdas/blocks within @trusted code would have the exact same semantics as @trusted blocks/lambdas within @safe code currently do. It's pure bikeshedding.
>
> Yes, and that leaves @safe code to actually not require manual checking, as opposed to today, where any @safe code with @trusted blocks today requires manual checking of all the @safe code (I agree just changing trusted/system code this way, and doing nothing with @safe would be bikeshedding).
>
> In reality, @safe code should be a function of its inputs, and what is considered a safe input. With @trusted lambdas, the inputs are "everything".

It's impossible to guarantee, at the language level, that @safe code can never require manual review. The programmer is allowed to use any and all knowledge at their disposal to verify the memory safety of @trusted (or in your proposal, @system-block) code, including knowledge about @safe code.

You might say, "the only thing a @trusted function can possibly know about a @safe function is its signature, so that doesn't matter," but that's not quite true. If the @trusted function and the @safe function are in the same module, the @trusted function can (in principle) rely on the inner workings of the safe function without invalidating its proof of memory safety, since the programmer knows that any given version of the @trusted function will only ever call the corresponding version of the @safe function.

Of course, such a @trusted function should never pass code review. But the fact that it can exist in principle means that you cannot truly rely on @safe to mean "no manual checking required", even if @trusted lambdas and nested functions are forbidden.