| |
 | Posted by Jonathan M Davis in reply to Kagamin | Permalink Reply |
|
Jonathan M Davis 
Posted in reply to Kagamin
| On Monday, December 16, 2024 2:47:27 AM MST Kagamin via Digitalmars-d wrote:
> On Saturday, 14 December 2024 at 10:20:34 UTC, Jonathan M Davis wrote:
> > If I want a function to be @safe, I'll mark it with @safe, and I'll get all of the appropriate checks.
>
> It's not always trivial. For example, I have an array copy function, it takes two arrays and calls memmove on them. It's, like, 80% safe, but it's not obvious what it would take to make it safer.
Whether we're talking about @safe or -preview=safer, they're both going to flag @system operations, requiring that a function that has @system operations be either @system or @trusted. The difference is that if you have a function that can be marked with @safe, and you mark it with @safe, you have a function that can be called from other @safe functions, whereas with -preview=safer, all you've done is track down instances where your code is doing @system operations (and you're then forced to explicitly mark the function as @system if it can't be @trusted). You still have to mark the function @safe or @trusted to be able to call it from @safe code.
As for how to make @system code be @safe, the only way to do that is to use @trusted. The question then is where exactly @trusted should be used, and that's obviously going to depend on the code in question. In principle, when you mark a function as @trusted, you're promising that it's 100% memory-safe in spite of the fact that it's doing something that's @system (though that obviously relies on the assumption that there are no compiler bugs which impact memory-safety and that all of the @trusted code that's being called is actually memory-safe).
If you have a function that's doing something with its arguments which are @system, and whether you can guarantee that it's actually @safe depends on the arguments that are given such that you can't guarantee that the code is memory-safe based solely based on what the function itself is doing, then that generally means that the function should be marked as @system, and it should then be documented what the requirements for the arguments are in order for what the function is doing to be memory-safe. Then the caller would make sure that it was passing in valid arguments and be marked @trusted.
One example of something like this would be a function like free. For free to be considered memory-safe, you have to pass it the correct arguments (otherwise, you can get issues like double-frees). So, free has to be @system, and it's the caller's responsibility to make sure that it's passing valid arguments to free. And if it does that, then it can be marked @trusted.
As to whether your particular function can be marked @trusted, I don't know, but it sounds like it probably can't be. If you can't be sure that the function is actually memory-safe, then that generally means that it's either doing something wrong that needs to be fixed, or that its memory safety depends on its arguments, in which case, the @trusted needs to be further up the call stack. But it's the kind of thing which really depends on what exactly the code is doing. In principle, to be able to mark a function as @trusted, it has to present an @safe API, since it's supposed to be impossible for an @safe function to doing anything that isn't memory-safe.
Either way, if you screw up and put @trusted in the wrong place, at least you know where to look when something happens which involves memory-safety having been violated, since only @trusted code can cause @safe code to do something that isn't memory-safe.
You might want to check out this blog post by Paul Backus:
https://pbackus.github.io/blog/what-does-memory-safety-really-mean-in-d.html
- Jonathan M Davis
|