@trusted attribute should be replaced with @trusted blocks

Steven Schveighoffer schveiguy at gmail.com
Thu Jan 16 15:30:45 UTC 2020


On 1/15/20 1:06 PM, ag0aep6g wrote:
> On 15.01.20 17:54, Joseph Rushton Wakeling wrote:
>> On Wednesday, 15 January 2020 at 14:30:02 UTC, Ogi wrote:
> [...]
>>> @safe fun() {
>>>     //safe code here
>>>     @trusted {
>>>         //those few lines that require manual checking
>>>     }
>>>     //we are safe again
>>> }
> [...]
>> 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.
> 
> Yup. But a proposal could specify that that's the intended meaning for 
> an @safe function that contains @trusted blocks. Whereas it's more of a 
> cheat when we use @trusted nested functions like that.
> 
> [...]
>> So, a better approach would be for the function to be marked up like 
>> this:
>>
>> @trusted fun ()    // alerts the outside user
>> {
>>      // lines that on their own are provably safe go here
>>      @system {
>>          // these lines are allowed to use @system code
>>      }
>>      // only provably safe lines here again
>> }
>>
>> ... and the compiler's behaviour would be to explicitly verify 
>> standard @safe rules for all the lines inside the @trusted function 
>> _except_ the ones inside a @system { ... } block.
>>
>> Cf. Steven Schveighoffer's remarks here: 
>> https://forum.dlang.org/post/qv7t8b$2h2t$1@digitalmars.com
>>
>> This way the function signature gives a clear indicator to the user 
>> which functions are provably @safe, and which are safe only on the 
>> assumption that the developer has done their job properly.
> 
> I don't think that's what Steven had in mind. In that world, @safe would 
> be very, very limited, because it couldn't be allowed to call @trusted 
> functions. That means @safe would only apply to trivial functions, and 
> @trusted would assume the role that @safe has today. But you'd have to 
> wrap every call from an @trusted to another @trusted function in an 
> @system block. It wouldn't be practical.

> The real purpose of @trusted in that example is to allow the @system 
> block in the body, and to signal to reviewers and maintainers that the 
> whole function is unsafe despite the mechanical checks that are done on 
> most of the lines. To a user, @trusted functions would still be the same 
> as @safe ones.

I'll interject here. I was thinking actually exactly along the lines of 
Joseph's code, and exactly what you are saying as well. And I think 
Joe's ideas are along the same lines, just they were misinterpreted here.

There are two things to look at for safety. One is that a function is 
safe or not safe (that is, it has a safe implementation, even if there 
are calls to system functions, so therefore is callable from 
mechanically checked safe code). This is the part where the compiler 
uses function attributes to determine what is callable and what is not.

The second is how much manual review is needed for the code. This is a 
signal to the reviewer/reader. In the current regime, the two reasons 
for marking are muddled -- we don't have a good way to say "this needs 
manual checking, but I also want the benefits of mechanical checking". 
This is why I proposed a change to trusted code STILL being mechanically 
checked, unless you want an escape. This would allow you to mark all 
code that needs manual review trusted, even if it's mechanically checked 
(it still needs review if the system-calling parts can muck with the data).

There may be a case as well to make data only accessible from system 
escapes, because the semantics of the data affect the memory safety of 
an aggregate.

> 
> Unfortunately, adding the mechanical checks of @safe to @trusted would 
> mean breaking all @trusted code that exists. So implementing that scheme 
> seems unrealistic.

Yeah, most likely. We would possibly need a fourth attribute for this 
purpose, or we can continue to rely on @safe/@trusted meaning what they 
mean today (it's doable, though confusing).

> 
> But as Steven says, it can be done when we use @trusted blocks instead 
> of @system blocks and @safe instead of @trusted on the function. I.e.:
> 
>      @safe fun ()
>      {
>          // lines that the compiler accepts as @safe go here
>          @trusted {
>              // these lines are allowed to use @system code
>          }
>          // only @safe lines here again
>      }
> 
> It weakens the meaning of @safe somewhat, but it's often treated that 
> way already. There's clearly a need.

@safe code is tremendously hampered without @trusted. You could only do 
things like simple math. As soon as you start needing things like memory 
allocation, or i/o, you need escapes. That is the reality we have.

-Steve


More information about the Digitalmars-d mailing list