Attribute transference from callbacks?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Sun Dec 8 17:27:18 UTC 2024


On Sunday, December 8, 2024 8:57:46 AM MST Jonathan M Davis via Digitalmars-d wrote:
> So, unless I'm missing something here (which is quite possible), this issue
> has already been solved.

Actually, after thinking about this further, I think that I _might_ get what
you're trying to say.

As I said, a function's attributes are fixed and can't be changed, and we
can't allow them to be violated. And they're in the name mangling to help
with that.

However, in principle, it's possible to write a function that can promise to
be @safe or nothrow or whatever as long as its delegate argument is (so all
of the checks are done on the basis that as long as the delegate meets the
appropriate requirements, the function does). The function can't really be
typed as @safe or nothrow or whatever at that point, since if it's saying
that it's @safe, then it would violate its attributes to call a delegate
that wasn't. However, if we had some form of conditional @safe / conditional
nothrow / etc., then a function could theoretically be typed with something
like @conditionalsafe to indicate that the as long as the delegate that it's
passed is @safe or @trusted, then the function call can be treated as @safe,
but if the delegate is @system, then the function can't retain its promise.
However, because the @safe was conditional, the type system can then treat
the call as @system, because the delegate argument was @system.

The implementation would potentially also have to be different from the
normal attributes (e.g. you couldn't remove any exception handling stuff
with conditional nothrow), but it could theoretically be implemented from
what I can tell at the moment.

I assume that you're suggesting inout on the delegate parameters to tell the
compiler that that particular attribute needs to be treated as conditional
on the function based on the attribute of the argument to that parameter,
which makes some sense.

So, I _think_ that I now get what you're proposing, but I'm not sure what
the consequences would be. My gut reaction is that we'd have to be _very_
careful about this to make sure that we weren't opening ourselves up to
additional issues. inout already causes us a fair bit of grief, and it's
trying something similar, albeit with type qualifiers. I'm also not sure
that something like this is needed often enough to be worth the extra
complication, but I don't know. It's only needed in cases where you want to
be able to make the function be able to be @safe but not require that it be
@safe. Normally, we'd just say that the delegate argument had to be
compatible with the attributes on the delegate parameter, and if we wanted
to make the function's attributes be inferred, we'd make it a template. And
in most cases, that's fine - though obviously, it's not fine in cases when
you can't use a template.

So, it _might_ be a good idea, but I don't know. I've never personally felt
the need, but I'm also perfectly fine with templating most code that would
need to take any kind of sink or output range. That's already what happens
with output ranges in general. A delegate sink can be an output range, but
output ranges are frequently structs of some kind. And particularly for
Phobos code, since it's generic, most of that stuff already has to be
templated on the element type anyway. So, using a delegate wouldn't avoid
templates except in cases where the code was not generic with regards to the
element type. But it's certainly true that in less generic code, it can make
perfect sense to have an output range or delegate sink which requires a
particular element type, and if you use a delegate in such a case, then you
can potentially avoid a template.

So, this may very well be an idea worth exploring, but I'm also skeptical
that the problem is big enough for it to be worth making attributes even
more complicated than they already are in order to solve it. At this point,
in most cases, I would suggest to folks that they only use attributes in
cases where they're really needed, since experience has shown that once a
code base gets large enough, attributes make refactoring a royal pain and
start causing more problems than they solve. And if you do need to support
attributes on much, then you almost need templates in order to reduce
problems with refactoring. And if you're not using attributes all over the
place, then this kind of problem with delegates isn't going to come up much.

- Jonathan M Davis





More information about the Digitalmars-d mailing list