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).
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With