On Sun, 25 Aug 2024 at 23:25, Paolo Invernizzi via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
On Sunday, 25 August 2024 at 12:47:13 UTC, Manu wrote:
> On Sun, 25 Aug 2024 at 21:56, Paolo Invernizzi via
> Digitalmars-d < digitalmars-d@puremagic.com> wrote:
>
>> On Sunday, 25 August 2024 at 11:40:06 UTC, Manu wrote:
>> > On Sun, 25 Aug 2024 at 21:31, Paolo Invernizzi via
>> > Digitalmars-d < digitalmars-d@puremagic.com> wrote:
>> >
>> >> On Sunday, 25 August 2024 at 10:32:31 UTC, Manu wrote:
>> >> > On Sun, 25 Aug 2024 at 19:56, Paolo Invernizzi via
>> >> > Digitalmars-d < digitalmars-d@puremagic.com> wrote:
>> >> >
>> >> >> On Saturday, 24 August 2024 at 17:43:38 UTC, Manu wrote:
>> >> >> > On Sun, 25 Aug 2024 at 03:31, Richard (Rikki) Andrew
>> >> >> > Cattermole via Digitalmars-d
>> >> >> > <digitalmars-d@puremagic.com> wrote:
>> >> >> >
>> >> >> >> On 25/08/2024 5:10 AM, Manu wrote:
>> >> >> >> > [...]
>> >> >> >>
>> >> >> >> I've been considering something along these lines.
>> >> >> >>
>> >> >> >> Specifically, ``@trusted`` does not mean the entire
>> >> >> >> body
>> >> >> >> shouldn't be verified. It just means that you are
>> >> >> >> going
>> >> >> >> to do something naughty that needs looking at.
>> >> >> >>
>> >> >> >> So you need annotated scopes inside of it, to do the
>> >> >> >> naughty thing.
>> >> >>
>> >> >> Just wrote a trusted function and call it: that's the
>> >> >> sane way to do it and respect code reviewer hard job.
>> >> >
>> >> >
>> >> > ...so, because I'm going to make one single unsafe
>> >> > function call inside of some function, I should eject all
>> >> > other related or unrelated safety checks for the entire
>> >> > surrounding context?
>> >>
>> >> No, you should isolate the unsafe part of code into a
>> >> function, explain why it’s unsafe, the intent of the code,
>> >> the
>> >> expected parameter values and the expected returns, so that
>> >> reviewer can check that the interface is really memory safe.
>> >>
>> >> Then call this extremely simple function from the rest of
>> >> safe code safe code.
>> >>
>> >>
>> > So, this then:
>> >
>> > extern(C) int myUnsafeFunction(int x, int y);
>> >
>> > @trusted int myPointlessWrapper(int x, int y)
>> > {
>> >   return  myUnsafeFunction (x, y);
>> > }
>> >
>> > @safe mySuperSafeFunction(...)
>> > {
>> >    //... lots of code
>> >
>> >   int r = myPointlessWrapper(arg1, arg2);
>> >
>> >   //... lots of code
>> > }
>> >
>> > Brilliant.
>>
>> That’s sidestepping the problem from your side: there’s no
>> explanation why myUnsafeFunction has an unsafe interface, under
>> what condition it’s unsafe, and what it’s supposed to do.
>> Neither
>> any check that it’s parameters are valid and they are not
>> turning
>> into memory unsafety.
>>
>> A reviewer for sure will ask you to add that information and
>> assurance about memory safety of calling myUnsadeFunction
>>
>> If the extern(C) function is intese memory safe, there should
>> be a way to mark the declaration @safe, also with importC, and
>> there we can reason about a solution.
>
>
> I think you might have missed the point here... we're talking
> about calling
> C libraries.
> It already has its interface nicely presented and documented,
> with expected
> arguments and returns all written out.
> We just want to call a function, that's all. There's no safety
> 'risk' here
> to comment on, unless you consider using a C library to be a
> risk in
> principle.

Using a C library IS a risk in principle, if it includes memory
unsafe function interfaces.
The memory unsafe C interface (@system) must be called from a
@trusted function that ensure that proper parameters and
conditions are properly set to not trigger memory unsafely:
that's basically the whole point of @trusted.

Right, but in ~95% of cases C functions don't have anything about them that makes them memory unsafe, or any relevant validation or concerning API material... they're just de-facto unsafe.

Here's some great functions that I plucked from top of my head:

float abs(float);
int rand();
void sleep(int);
int fclose(FILE);
pid_t getpid();

It's obviously stupid to write a wrapper function for every single C function we use. That's entirely self-defeating.
Why would anybody import a C header file if they have to write as many function wrappers as C function prototypes imported? Might as well have just written the prototypes... it's actually LESS code.

And then there's maybe kinda contentious ones, like:

FILE fopen(char* filename, char* mode);

Now, clearly there's a null-termination concern here, but that's not actually a category of issue that @safe is concerned with as far as I know.
Generally, the user just wants to do this:

unsafe {
  FILE f = fopen(filename.toStringz, "rb");
}

There's no value in writing a whole function wrapper to automate a call to toStringz().
I'm not even sure that call is actually unsafe anyway. toStringz() isn't unsafe...?


I further agree with you that would be good to have a clever way
to declare @safe declarations for SOME function automatically
declared by importC.

That list I wrote above and a million functions of that nature; they don't have any interaction with @safe... declaring them @system is nothing more than a nuisance. Nothing is added by not trusting them.
If there's some API tell-tales that can definitively determine the safety of a function, then maybe it could make an educated guess... but failing that, then there's a serious practical conundrum here.


BTW, nice to see you here again in the forum, Manu! :-P

🎉 🎉 🎉