| |
 | Posted by Jonathan M Davis in reply to Dom DiSc | Permalink Reply |
|
Jonathan M Davis 
Posted in reply to Dom DiSc
| 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
|