Is there a way to slice non-array type in @safe?

Paul Backus snarwin at gmail.com
Fri Jul 12 00:59:40 UTC 2019


On Thursday, 11 July 2019 at 19:44:51 UTC, Stefanos Baziotis 
wrote:
> On Thursday, 11 July 2019 at 19:37:38 UTC, Nathan S. wrote:
>>
>> If you know that what you're doing cannot result in memory 
>> corruption but the compiler cannot automatically infer @safe, 
>> it is appropriate to use @trusted. (For this case make sure 
>> you're not returning the byte slices, since if the arguments 
>> were allocated on the stack you could end up with a pointer to 
>> an invalid stack frame. If it's the caller's responsibility to 
>> ensure the slice doesn't outlive the struct then it is the 
>> caller that should be @trusted or not.)
>
> Yes, @trusted is an option. I mean it's a good solution, but 
> from the standpoint of the language user, it seems unfortunate 
> that for the case static types
> @trusted has to be used while the array one can be @safe:
>
> int memcmp(T)(const T[] s1, const T[] s2) @safe
> {
>     const byte[] s1b = (cast(const(byte[]))s1)[0 .. s1.length * 
> T.sizeof];
>     const byte[] s2b = (cast(const(byte[]))s2)[0 .. s2.length * 
> T.sizeof];
> }

You can use a union:

int foo(T)(ref T s1, ref T s2) {
     import std.stdio;

     union U {
         T val;
         byte[T.sizeof] bytes;
     }

     const U s1u = { val: s1 };
     const U s2u = { val: s2 };

     writeln("s1 bytes: ", s1u.bytes);
     writeln("s2 bytes: ", s2u.bytes);

     return 0;
}

@safe void main() {
     double a = 12.345, b = 67.890;
     foo(a, b);
}

However, accessing the `bytes` member will still be considered 
@system if T is or contains a pointer. To fix this, you can use a 
@trusted nested function to do the union access; e.g.,

     @trusted ref const(ubyte[T.sizeof]) getBytes(ref U u) { 
return u.bytes; }
     // ...
     writeln("s1 bytes: ", getBytes(s1u));


More information about the Digitalmars-d-learn mailing list