August 26

On Sunday, 18 August 2024 at 04:43:34 UTC, Manu wrote:

>

I just tried using ImportC for the first time ever, but I was surprised
when I immediately received a sea of errors calling the C symbols from
nothrow @nogc functions.
My entire program is nothrow @nogc... I assumed ImportC would be
supremely suitable in this context, but apparently not...

Is there something I've missed? Is there a plan for this?
I found just one single very short forum thread...

I found the same.

I'm still using ImportC on my project, temporarily as -betterC and commenting out the @nogc nothrow attributes but this must be fixed at some point.

https://issues.dlang.org/show_bug.cgi?id=23812

https://github.com/schveiguy/draylib/blob/7de20a4cd2359d4df01acc159f953aa6dbe04347/source/raylib/rtext.d#L3

-Steve

August 26

On Wednesday, 21 August 2024 at 19:41:00 UTC, Walter Bright wrote:

>

C code can call C++ code which can throw.

Does this actually interact with D code properly? Like, does this work?

void fn() nothrow {
   try {
      cFunctionThatCallsCplusplusThatThrows();
   } catch(Exception e) {
   }
}
>

C code can also call D code with can throw and/or gc.

D attributes are all subtractive, meaning they remove capability from the called function. But C code can do anything.

I don't think you understand the problem here.

printf doesn't use the GC. It doesn't throw. This is not conjecture or philosophy, it objectively, explicitly does not do this.

Yet, if I use importC, I can't call printf from a nothrow @nogc function. Consider that I don't want to have to mark a function as using the GC and throwing because printf made me do it.

If I import core.stdc.stdio, then I can use it, but that basically means importC has failed if you have to do that.

In addition, I have already run into situations where I import C code that includes stdio.h, so even if I want to use core.stdc.stdio, I can't.

This must be fixed. There is no other option. If this is not fixed, you cannot use importC to actually import C.

https://issues.dlang.org/show_bug.cgi?id=23812

-Steve

August 26
On 8/26/24 03:16, Manu wrote:
> On Mon, 26 Aug 2024, 07:56 Timon Gehr via Digitalmars-d, <digitalmars- d@puremagic.com <mailto:digitalmars-d@puremagic.com>> wrote:
> 
>     On 8/25/24 13:06, Dom DiSc wrote:
>      >
>      > But I fully agree, this should be replaced by true trusted
>     blocks, the
>      > sooner the better.
> 
>     You cannot have a "trusted block". It just does not work. The interface
>     to any trusted thing has to be clearly delineated.
> 
> 
> Well it obviously does work in some sense, because it's the de facto standard that people generally expect in numerous languages.
> ...

No, it's laid out differently.

> People are going to have it one way or another; whether it's a ridiculous hack like `()@trusted { ... }();` or otherwise. It's what other languages with this sort of thing do.
> ...

No, e.g. Rust just does not distinguish trusted and untrusted safe functions.

> We don't have a better offering to motivate people to deviate from their patterns.
> 
> Resisting that degrades D.
> 

It should not be called "trusted" then.

Fundamentally, I agree on the substance (though probably, even better designs are possible). However, let's not invent another idiosyncratic keyword now.
August 26
On 8/26/24 07:37, Walter Bright wrote:
> On 8/24/2024 10:15 AM, Manu wrote:
>> *sigh* ... I'm not going to do that.
>> ImportC either works, or it doesn't... and it currently doesn't work, and I'm just going to move on.
>> By far the easiest and least ridiculous feeling thing can do right now is to just prototype the occasional C library call inline immediately before the call, which is what I've moved on with.
>> Fortunately my call volume is low.
> 
> You're right, that will work.
> 
> I tried to make C calls default to @trusted. Every single person in the community who voiced an opinion on it was dead set against it. But here you are, saying who cares what C does.
> 
> I've got a cannon on one side aimed at me, and a flak gun on the other side.
> 
> What do you suggest I do?
> 

Marking every C function `@trusted` would not solve his problem. What would solve his problem is if ImportC supported C extensions that let you mark groups of declarations using D attributes. Then you can put those in the C files that you import.
August 27
On Mon, 26 Aug 2024 at 15:41, Walter Bright via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> On 8/24/2024 10:15 AM, Manu wrote:
> > *sigh* ... I'm not going to do that.
> > ImportC either works, or it doesn't... and it currently doesn't work,
> and I'm
> > just going to move on.
> > By far the easiest and least ridiculous feeling thing can do right now
> is to
> > just prototype the occasional C library call inline immediately before
> the call,
> > which is what I've moved on with.
> > Fortunately my call volume is low.
>
> You're right, that will work.
>
> I tried to make C calls default to @trusted. Every single person in the
> community who voiced an opinion on it was dead set against it. But here
> you are,
> saying who cares what C does.
>
> I've got a cannon on one side aimed at me, and a flak gun on the other side.
>
> What do you suggest I do?


We're not talking about @trusted, we're talking about nothrow and @nogc...
the community voices that have presented here so far seem to agree; I don't
think you're being pressured by competing opinions.
I *suggest* you make the change, OR consider adding a command line arg to
override it; and optionally make that argument apply to an isolated source
tree if you're feeling particularly conservative. (I wouldn't do that, but
the more conservative might consider it)
The situation as it stands is a literal tragedy... you put a lot of work
into this.

Realistically speaking; C calls are not going to throw or gcalloc. You can
contrive a situation, but you have to go miles out of your way to arrange
that.
Any C library that operates via callbacks will have an API that also has
those attributes attached; in a nothrow @nogc C interface, the user can't
provide a callback that can throw or GC. The only risk vector is as you
described earlier; *mixed use* of the API and using a binary back-door.
The whole point of ImportC, is to use the API.

And if someone does a binary-back-door... who cares? That's called a BUG.
They're playing with fire already! C doesn't have any such type safety, and
they shouldn't expect it to.
They know what they did; they did it intentionally, surely knew what the
risk factors were, and they are naturally expected to not write such bugs
into their program.


August 27
On Tue, 27 Aug 2024 at 04:06, Timon Gehr via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> On 8/26/24 03:16, Manu wrote:
> > On Mon, 26 Aug 2024, 07:56 Timon Gehr via Digitalmars-d, <digitalmars- d@puremagic.com <mailto:digitalmars-d@puremagic.com>> wrote:
> >
> >     On 8/25/24 13:06, Dom DiSc wrote:
> >      >
> >      > But I fully agree, this should be replaced by true trusted
> >     blocks, the
> >      > sooner the better.
> >
> >     You cannot have a "trusted block". It just does not work. The
> interface
> >     to any trusted thing has to be clearly delineated.
> >
> >
> > Well it obviously does work in some sense, because it's the de facto
> > standard that people generally expect in numerous languages.
> > ...
>
> No, it's laid out differently.
>
> > People are going to have it one way or another; whether it's a
> > ridiculous hack like `()@trusted { ... }();` or otherwise. It's what
> > other languages with this sort of thing do.
> > ...
>
> No, e.g. Rust just does not distinguish trusted and untrusted safe functions.
>

Rust does:

unsafe {
  my_unsafe_code;
}

Perfect.

In C#:

unsafe {
  my_unsafe_code;
}

Perfect.

> We don't have a better offering to motivate people to deviate from their
> > patterns.
> >
> > Resisting that degrades D.
> >
>
> It should not be called "trusted" then.
>

Absolutely, 100%.

Fundamentally, I agree on the substance (though probably, even better
> designs are possible). However, let's not invent another idiosyncratic keyword now.
>

What 'another keyword' are you talking about?
I think the problem that you're pointing at here is that we're using
`@trusted` as a hack as if it meant what we all want; `unsafe` as in other
languages.
I understand that D's 'concept' is not quite like that, but nobody ever
wanted the definition that D presents that I'm aware of, and all we want is
an unsafe block.

I don't see any reason for @trusted... we only need @safe to invoke the escape analysis, and then the ability to write an unsafe block inside a function; which people are abusing the @trusted keyword to achieve. Why is the design we have better than the established designs?


August 27
On Monday, August 26, 2024 11:54:06 PM MDT Manu via Digitalmars-d wrote:
> We're not talking about @trusted, we're talking about nothrow and @nogc...
> the community voices that have presented here so far seem to agree; I don't
> think you're being pressured by competing opinions.
> I *suggest* you make the change, OR consider adding a command line arg to
> override it; and optionally make that argument apply to an isolated source
> tree if you're feeling particularly conservative. (I wouldn't do that, but
> the more conservative might consider it)
> The situation as it stands is a literal tragedy... you put a lot of work
> into this.
>
> Realistically speaking; C calls are not going to throw or gcalloc. You can
> contrive a situation, but you have to go miles out of your way to arrange
> that.
> Any C library that operates via callbacks will have an API that also has
> those attributes attached; in a nothrow @nogc C interface, the user can't
> provide a callback that can throw or GC. The only risk vector is as you
> described earlier; *mixed use* of the API and using a binary back-door.
> The whole point of ImportC, is to use the API.
>
> And if someone does a binary-back-door... who cares? That's called a BUG.
> They're playing with fire already! C doesn't have any such type safety, and
> they shouldn't expect it to.
> They know what they did; they did it intentionally, surely knew what the
> risk factors were, and they are naturally expected to not write such bugs
> into their program.

Yeah. We already have the ability to declare C bindings without importC. The normal use case for importC is to "import" actual C code without having to write and maintain a bunch of bindings, and realistically, that code is going to be implemented as nothrow and @nogc, because normal C code is nothrow and @nogc. Yes, it's _technically_ possible to have C functions using D features and import them with importC, but who is actually going to do that in practice?

Not treating importC functions as nothrow and @nogc is hurting the intended use case for importC without really enabling much. It seems to me that if anyone really wants to have C code using the GC or throwing exceptions, they can just use C bindings like they've been able to do for many years, whereas having importC assume nothrow and @nogc will make the feature work much better for the problem that it's actually trying to solve.

If need be, we can put it as a caveat in the importC documentation that extern(C) functions implemented with D which should not be treated as nothrow or @nogc cannot be used with importC, but I question that anyone will ever feel constrained by that. The current situation is a pessimization which makes importC worse for its actual use case for fear of causing problems for a use case which might not even ever exist in practice.

It seems to me that it would be much better to just assume nothrow and @nogc and document that behavior, allowing the few (if any) who want something else to just write their own C bindings. As it is, they're probably writing their own extern(C) functions anyway rather than looking to import C headers, because their code is D rather than C.

- Jonathan M Davis



August 27
On Tue, 27 Aug 2024 at 04:17, Timon Gehr via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> On 8/26/24 07:37, Walter Bright wrote:
> > On 8/24/2024 10:15 AM, Manu wrote:
> >> *sigh* ... I'm not going to do that.
> >> ImportC either works, or it doesn't... and it currently doesn't work,
> >> and I'm just going to move on.
> >> By far the easiest and least ridiculous feeling thing can do right now
> >> is to just prototype the occasional C library call inline immediately
> >> before the call, which is what I've moved on with.
> >> Fortunately my call volume is low.
> >
> > You're right, that will work.
> >
> > I tried to make C calls default to @trusted. Every single person in the community who voiced an opinion on it was dead set against it. But here you are, saying who cares what C does.
> >
> > I've got a cannon on one side aimed at me, and a flak gun on the other side.
> >
> > What do you suggest I do?
> >
>
> Marking every C function `@trusted` would not solve his problem. What would solve his problem is if ImportC supported C extensions that let you mark groups of declarations using D attributes. Then you can put those in the C files that you import.
>

I could live with that... though I don't necessarily agree.
I stand with Walter in principle on this; C prototypes should just be
@trusted. If you import and link a C library; you are 'trusting' it by
definition. You're making use of some middleware, and you're not in control
of the code... it is as it is, and you decided to use it anyway. You either
trust it (and link it into your software), or you don't.
Nobody gains anything from causing a hassle every time you want to call
into a library that you've opted in to. The *whole point* is to use the
library; what possible advantage could there be to making that a pain in
the arse?

There's one edge case I can think of; source-available functions. If the C source is available in a header, then we can infer @safe-ty rather than blindly trust it.


Can we direct this thread back towards nothrow and @nogc? This wasn't actually a conversation about @trusted...


August 27
On Tuesday, 27 August 2024 at 06:32:06 UTC, Manu wrote:
> On Tue, 27 Aug 2024 at 04:17, Timon Gehr via Digitalmars-d < digitalmars-d@puremagic.com> wrote:
>
>> On 8/26/24 07:37, Walter Bright wrote:
>> > On 8/24/2024 10:15 AM, Manu wrote:
>> >> *sigh* ... I'm not going to do that.
>> >> ImportC either works, or it doesn't... and it currently doesn't work,
>> >> and I'm just going to move on.
>> >> By far the easiest and least ridiculous feeling thing can do right now
>> >> is to just prototype the occasional C library call inline immediately
>> >> before the call, which is what I've moved on with.
>> >> Fortunately my call volume is low.
>> >
>> > You're right, that will work.
>> >
>> > I tried to make C calls default to @trusted. Every single person in the community who voiced an opinion on it was dead set against it. But here you are, saying who cares what C does.
>> >
>> > I've got a cannon on one side aimed at me, and a flak gun on the other side.
>> >
>> > What do you suggest I do?
>> >
>>
>> Marking every C function `@trusted` would not solve his problem. What would solve his problem is if ImportC supported C extensions that let you mark groups of declarations using D attributes. Then you can put those in the C files that you import.
>>
>
> I could live with that... though I don't necessarily agree.
> I stand with Walter in principle on this; C prototypes should just be @trusted.

Again, a big NO

> If you import and link a C library; you are 'trusting' it by definition.

Again, a big NO

> You're making use of some middleware, and you're not in control
> of the code... it is as it is, and you decided to use it anyway.

@trusted relates to _memory safety_, nothing more, it's not about the distinction between crap codebases and excellent codebases.

You are in control of reading the documentation of the external C function
You are in control of understanding that some C function is NOT memory safe.
You are in control that you CAN'T call the function from @safe code without sanitising its input with some other @trusted D function.

You still mix memory safety with other completely different things.

> You either trust it (and link it into your software), or you don't.

That's nonsense, again, see above

> Nobody gains anything from causing a hassle every time you want  to call
> into a library that you've opted in to. The *whole point* is to use the
> library; what possible advantage could there be to making that a pain in the arse?

Best effort towards memory safety.
If you don't care and are searching for no hassles just don't use safe at all in your codebase

> Can we direct this thread back towards nothrow and @nogc? This wasn't actually a conversation about @trusted...

It seems to me actually that there's still a lot of confusion about @safe / @trusted / @system from time to time, as your thread is showing.

So I think this digression is just prophylaxis against the @trusted virus

 :-P




August 27
On 8/26/2024 11:14 PM, Manu wrote:
> Why is the design we have better than the established designs?

The idea is not to simply mark code as unsafe, but to encapsulate it within a safe interface. It's a different approach.

Yes, it is (initially) more work, but will pay off with more readability and maintainability. It is worth it.

A number of D features have a bias towards encapsulation rather than interleaving things.

The established designs are inferior, which is why we have D.