Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I do I/O in @safe functions in D?

Tags:

d

I am learning the D programming language, and I am trying to restrict myself to the SafeD subset of it where I can. However, I noticed that the I/O functions like writeln are all @system. How do I do I/O in SafeD?

I am using LDC2 on Fedora 19 x86-64 (downloaded from the Fedora package).

like image 591
Demi Avatar asked Sep 30 '13 18:09

Demi


2 Answers

You don't, or at least not directly. I/O requires making system calls, which means C functions, and C functions aren't going to be @safe. And since writeln currently calls printf underneath the hood, it definitely isn't going to be @safe, because it's trivial to do unsafe things with printf (like giving it %s and then passing it an integer instead of a string). It might be possible to make writeln @trusted under some circumstances, but I don't know what all would be involved with that. That would depend on how it's implemented.

It's fully expected that any non-trivial D program will use @system code. The trick is to isolate it. The majority of your program will hopefully be @safe, but sections of it are going to have to be @system. However, you then only have to examine a small section of your program for memory safety. Once you verify by hand that a function which calls @system functions is actually memory safe, you can mark it as @trusted and then you can use it in @safe code.

Unfortunately, it's also quite likely that certain core stuff in druntime and Phobos is going to be @system based on what it's doing with low level stuff, and not necessarily all of it has been marked with @trusted as it should be (e.g. std.array.appender might be @system when it should probably be able to be @trusted - I'm not sure what it currently is though; it probably depends on the element type of your array). So, it's likely that some improvements will need to be made to some standard library stuff in order to better support @safe (which is in progress, but I don't know where all of that stands right now), and you may end up having to use @trusted in more places right now than you will in the future. writeln may or may not be able to be @safe or @trusted in the future. But it definitely won't be if the types that you're using with it don't have @safe or @trusted toString functions, so part of whether writeln is @safe depends on what you're using it with, regardless of how it's implemented. However, it's not currently @safe or @trusted even with built-in types, so for now, you're out of luck.

If you really wanted to, you could create a wrapper for writeln which was @trusted, but you'd have to be uber careful to make sure that the code is actually memory safe - and simply creating a templated wrapper and marking it @trusted isn't going to cut it, because then you'd be treating it as @safe regardless of what type you passed to it. So, it's probably best to just not wrap it and then mark the caller as @trusted if you're sure that that particular use of writeln is memory safe. Of course, that also highlights part of why functions like writeln are currently @system in the first place: it's often hard to write @trusted templated code without trusting stuff that shouldn't be trusted (because it depends on the template arguments). Attribute inference often takes care of the problem, but if templated code is doing something that needs to be @trusted, it becomes difficult to mark a portion of the code as @trusted and leave the rest to inference, especially if the template arguments are mixed in with the @system stuff. I expect that we'll sort it out eventually for all of the standard library stuff though.

like image 123
Jonathan M Davis Avatar answered Nov 02 '22 03:11

Jonathan M Davis


I think we should make writeln and friends @trusted - although they use low-level primitives, they do enough checking to make sure that e.g. printf does not received messed-up arguments.

like image 29
Andrei Alexandrescu Avatar answered Nov 02 '22 03:11

Andrei Alexandrescu