@trust is an encapsulation method, not an escape

Walter Bright via Digitalmars-d digitalmars-d at puremagic.com
Thu Feb 5 15:39:37 PST 2015


Consider the following code excerpted from std.array.join:

   static U trustedCast(U, V)(V v) @trusted { return cast(U) v; }
   return trustedCast!RetType(result);

This is because the compiler would complain that the following line would not be 
@safe:

   return cast(RetType)(result);

The rationale is "I know it's safe, so I'll create an @trusted wrapper to 
eliminate the error." What comes next is "that's cumbersome. How about a better 
syntax:"

   trusted {
      return cast(RetType)(result);
   }

? It's the rationale behind "unsafe" blocks that appear in other languages. It 
seems like a perfectly reasonable request.

The trouble with it is, what if the cast is converting from an integer to a 
pointer? That could lead to memory corruption. The code allows a potentially 
memory corrupting operation to be inserted into code that is otherwise @safe.

The only way to deal with it is to then manually review everything about 
'RetType' and 'result' to prove to oneself that it is not converting random bit 
patterns into pointers. In other words, one is manually reviewing @safe code for 
memory corruption errors.

This is an abject failure of @safe, @trusted, and @system.

The solution is to regard @trusted as a means of encapsulating unsafe 
operations, not escaping them. Encapsulating them means that the interface from 
the @trusted code is such that it is usable from safe code without having to 
manually review the safe code for memory safety. For example (also from std.array):

   static void trustedMemcopy(T[] dest, T[] src) @trusted
   {
     assert(src.length == dest.length);
     memcpy(dest.ptr, src.ptr, src.length * T.sizeof);
   }

I don't have to review callers of trustedMemory() because it encapsulates an 
unsafe operation (memcpy) with a safe interface.

The reason @trusted applies only to functions, and not to blocks of code, is 
that functions are the construct in D that provides an interface. Arbitrary 
blocks of code do not have a structured interface. Adding @trusted { code } 
support will encourage incorrect uses like the opening example. The existence of 
@trusted blocks will require review of every line of code in the function that 
encloses it, and transitively every function that calls it!

Adding @trusted as a function attribute, on the other hand, only requires review 
of the function's interface to determine if it is acceptable to use in safe 
code. Safety review of its callers is unnecessary.



More information about the Digitalmars-d mailing list