How to fake pure
Jonathan M Davis
newsgroup.d at jmdavisprog.com
Tue Apr 8 14:00:56 UTC 2025
On Tuesday, April 8, 2025 5:28:57 AM MDT Dom DiSc via Digitalmars-d-learn wrote:
> Hi.
>
> I want to create my own allocator, but using malloc is not pure
> (it internally has to have some "global state"). But the GC also
> has this "global state" and still is considered "pure".
> So internally the impurity of the allocators has been hidden.
>
> How can I do this?
> adding @trusted doesn't do the trick, declaring it extern(C) also
> doesn't help.
> Do I have to compile the file containing the allocator with some
> special switches turned on or off or something?
You basically have to lie to the compiler and cast the function pointer to
pure or by using an extern(C) shim which lies (since C functions have no
name-mangling, it's possible for the attributes of the declaration to not
match the attributes of the definition).
That being said, core.memory has pureMalloc and pureFree which do that for
you already, including mucking around with errno to ensure that it's not
changed even though malloc and pure can change it.
That being said, personally, I think that it's a mistake to try to force
pure like this (and I don't think that pureMalloc or pureFree should ever
have been added). We already have a variety of compiler bugs related to
doing stuff based on pure (e.g. incorrectly implicitly converting to
immutable, because the compiler decides that the result has to be unique,
but it got the logic wrong, and it's not unique). And it seems to be
sufficiently difficult to reason about exactly what is implied by pure and
how the compiler will react because of it that determining whether what
you're doing is "logically" pure is very error-prone in general. In general,
when we try to make the compiler do more because of pure or treat more stuff
like pure, we end up with bugs, because it's pretty much a house of cards.
Of course, I'm also increasingly of the opinion that pure was a mistake in
general, because it does almost nothing in practice but routinely doesn't
work with straightforward code - and it's definitely one of those attributes
which gets in way when code needs to be refactored, since it's easy to end
up in a situation where you can't have a bunch of code be pure any longer
just because of one change that you need to make deep in the call stack
somewhere, and it can be very difficult and time-consuming to refactor in
such situations. So, by using pure, you're typically getting no actual
benefits, but you're often making your life harder down the line.
So, my advice is to only use pure when you actually need the guarantees that
it provides, and _maybe_ if your function is really simple, and you can be
absolutely sure that you're never going to need to make significant changes
to it, you could make it pure to enable its use in pure code, but in
general, I think that using pure is just a mistake that's going to cause
problems down the line - particularly with larger code bases. And that's
without considering the issues of lying to the compiler about what's pure in
order to get code to be treated as pure when the compiler doesn't think that
it is. If you lie to the compiler and get it wrong, you can get issues that
will be pretty hard to catch or debug, whereas if you just don't bother with
pure, you avoid all of the associated problems without actually losing
anything in almost all cases.
- Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list